diff --git a/.gn b/.gn index abde532..6f793ba 100644 --- a/.gn +++ b/.gn
@@ -111,9 +111,9 @@ #"//components/nacl/*", #"//components/navigation_interception/*", #"//components/navigation_metrics/*", - #"//components/net_log/*", + "//components/net_log/*", #"//components/network_hints/*", - #"//components/network_time/*", + "//components/network_time/*", #"//components/offline_pages/*", #"//components/omnibox/*", #"//components/onc/*",
diff --git a/BUILD.gn b/BUILD.gn index bfa2537..881028d 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -79,7 +79,7 @@ "//url:url_unittests", ] - if (!is_ios && !is_android) { + if (!is_ios && !is_android && !is_chromecast) { deps += [ "//chrome", "//chrome/test:browser_tests", @@ -240,8 +240,14 @@ if (is_android) { deps += [ "//base/android/linker:chromium_android_linker", + "//base:base_junit_tests", "//build/android/gyp/test:hello_world", "//build/android/rezip", + "//components/invalidation/impl:components_invalidation_impl_junit_tests", + "//components/policy/android:components_policy_junit_tests", + "//content/public/android:content_junit_tests", + "//net/android:net_junit_tests", + "//testing/android/junit:junit_unittests", "//third_party/errorprone:chromium_errorprone", "//tools/android:android_tools", "//tools/android/heap_profiler:heap_profiler_unittests", @@ -283,6 +289,7 @@ if (!is_chromecast) { deps += [ "//android_webview:system_webview_apk", + "//chrome/android:chrome_junit_tests", "//chrome/android:chrome_public_apk", "//chrome/android:chrome_public_test_apk", "//chrome/test/chromedriver/test/webview_shell:chromedriver_webview_shell_apk", @@ -535,6 +542,9 @@ "//media/cast:cast_unittests", ] } + if (is_chromecast) { + deps += [ "//chromecast:cast_shell" ] + } } group("gn_only") { @@ -542,7 +552,7 @@ deps = [] - if (!is_ios) { + if (!is_ios && !is_chromecast) { deps += [ "//mandoline:all" ] } @@ -554,7 +564,7 @@ deps += [ "//components/mus/example:all" ] } - if (is_linux && !is_chromeos) { + if (is_linux && !is_chromeos && !is_chromecast) { # TODO(GYP): Figure out if any of these should be in gn_all # and figure out how cross-platform they are deps += [
diff --git a/DEPS b/DEPS index 367c802..9a98b5e 100644 --- a/DEPS +++ b/DEPS
@@ -39,11 +39,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '7600183ba7d8c8df6fbba1b32a73e6394216754e', + 'skia_revision': '143fd5547c614704d95ec82ff791ae5211b06f2d', # 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': '9f1869d3eac26e7a9594471c255f3348a0d45e37', + 'v8_revision': '6c386573cd88f683113881ba21a06c7bfa48f1a0', # 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. @@ -75,7 +75,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling google-toolbox-for-mac # and whatever else without interference from each other. - 'google_toolbox_for_mac_revision': 'ce47a231ea0b238fbe95538e86cc61d74c234be6', # from svn revision 705 + 'google_toolbox_for_mac_revision': '401878398253074c515c03cb3a3f8bb0cc8da6e9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling lighttpd # and whatever else without interference from each other. @@ -151,7 +151,7 @@ Var('chromium_git') + '/external/grit-i18n.git' + '@' + '4066463928d64337e6d70046aa4f18b833a2d0e3', # from svn revision 201 'src/tools/gyp': - Var('chromium_git') + '/external/gyp.git' + '@' + '3f21260b43401553c37bb28090b65a75577d5b4e', + Var('chromium_git') + '/external/gyp.git' + '@' + '2c1e6cced23554ce84806e570acea637f6473afc', 'src/tools/swarming_client': Var('chromium_git') + '/external/swarming.client.git' + '@' + Var('swarming_revision'), @@ -193,7 +193,7 @@ Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'd2733b2c43f65f0e779d5d014777fb8ea1e89873', 'src/third_party/libjingle/source/talk': - Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + '947c97c4a4fce815f911adab4e235094fc16362f', # commit position 10467 + Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + '1da435bae87437b4dcfdb9e13e59615ed2cadad5', # commit position 10491 'src/third_party/usrsctp/usrsctplib': Var('chromium_git') + '/external/usrsctplib.git' + '@' + '36444a999739e9e408f8f587cb4c3ffeef2e50ac', # from svn revision 9215 @@ -217,7 +217,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' + '@' + 'ca2e360843a5fc33e1cd911df457f119bbeafbfb', # commit position 10470 + Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'c8b569e0a7ad0b369e15f0197b3a558699ec8efa', # commit position 10494 'src/third_party/openmax_dl': Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' + Var('openmax_dl_revision'), @@ -280,7 +280,7 @@ 'src/third_party/catapult': Var('chromium_git') + '/external/github.com/catapult-project/catapult.git' + '@' + - '2e833914bbd78cf3db4b3ec7517c296faff84a6f', + 'bcbf96d51ccb1dcab12a5c035bf2226e0ec47a12', } @@ -339,7 +339,7 @@ Var('chromium_git') + '/external/github.com/swisspol/GCDWebServer.git' + '@' + '3d5fd0b8281a7224c057deb2d17709b5bea64836', 'src/third_party/google_toolbox_for_mac/src': - Var('chromium_git') + '/external/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'), + Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'), 'src/third_party/nss': Var('chromium_git') + '/chromium/deps/nss.git' + '@' + Var('nss_revision'), @@ -361,7 +361,7 @@ Var('chromium_git') + '/chromium/reference_builds/chrome_mac.git' + '@' + '8dc181329e7c5255f83b4b85dc2f71498a237955', 'src/third_party/google_toolbox_for_mac/src': - Var('chromium_git') + '/external/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'), + Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'), 'src/third_party/pdfsqueeze':
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index 644076b..18735e60 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -249,6 +249,8 @@ private boolean mIsAttachedToWindow; // Visiblity state of |mContentViewCore|. private boolean mIsContentViewCoreVisible; + private boolean mIsUpdateVisibilityTaskPending; + private Runnable mUpdateVisibilityRunnable; private Bitmap mFavicon; private boolean mHasRequestedVisitedHistoryFromClient; @@ -702,6 +704,12 @@ mBackgroundThreadClient = new BackgroundThreadClientImpl(); mIoThreadClient = new IoThreadClientImpl(); mInterceptNavigationDelegate = new InterceptNavigationDelegateImpl(); + mUpdateVisibilityRunnable = new Runnable() { + @Override + public void run() { + updateContentViewCoreVisibility(); + } + }; AwSettings.ZoomSupportChangeListener zoomListener = new AwSettings.ZoomSupportChangeListener() { @@ -2356,10 +2364,27 @@ && visible && !mIsWindowVisible; mIsWindowVisible = visible; if (!isDestroyed(NO_WARN)) nativeSetWindowVisibility(mNativeAwContents, mIsWindowVisible); - updateContentViewCoreVisibility(); + postUpdateContentViewCoreVisibility(); + } + + private void postUpdateContentViewCoreVisibility() { + if (mIsUpdateVisibilityTaskPending) return; + // When WebView is attached to a visible window, WebView will be + // attached to a window whose visibility is initially invisible, then + // the window visibility will be updated to true. This means CVC + // visibility will be set to false then true immediately, in the same + // function call of View#dispatchAttachedToWindow. DetachedFromWindow + // is a similar case, where window visibility changes before AwContents + // is detached from window. + // + // To prevent this flip of CVC visibility, post the task to update CVC + // visibility during attach, detach and window visibility change. + mIsUpdateVisibilityTaskPending = true; + mHandler.post(mUpdateVisibilityRunnable); } private void updateContentViewCoreVisibility() { + mIsUpdateVisibilityTaskPending = false; if (isDestroyed(NO_WARN)) return; boolean contentViewCoreVisible = nativeIsVisible(mNativeAwContents); @@ -3005,6 +3030,7 @@ nativeOnAttachedToWindow(mNativeAwContents, mContainerView.getWidth(), mContainerView.getHeight()); updateHardwareAcceleratedFeaturesToggle(); + postUpdateContentViewCoreVisibility(); setLocale(LocaleUtils.getDefaultLocale()); @@ -3026,6 +3052,7 @@ mContentViewCore.onDetachedFromWindow(); updateHardwareAcceleratedFeaturesToggle(); + postUpdateContentViewCoreVisibility(); if (mComponentCallbacks != null) { mContext.unregisterComponentCallbacks(mComponentCallbacks);
diff --git a/ash/display/window_tree_host_manager_unittest.cc b/ash/display/window_tree_host_manager_unittest.cc index 99d6950..5ea2343f 100644 --- a/ash/display/window_tree_host_manager_unittest.cc +++ b/ash/display/window_tree_host_manager_unittest.cc
@@ -24,6 +24,7 @@ #include "ui/aura/client/focus_change_observer.h" #include "ui/aura/client/focus_client.h" #include "ui/aura/env.h" +#include "ui/aura/window_observer.h" #include "ui/aura/window_tracker.h" #include "ui/aura/window_tree_host.h" #include "ui/events/event_handler.h" @@ -1293,6 +1294,69 @@ EXPECT_EQ(20, Shell::GetScreen()->GetPrimaryDisplay().id()); } +namespace { + +class RootWindowTestObserver : public aura::WindowObserver { + public: + RootWindowTestObserver() {} + ~RootWindowTestObserver() override {} + + void OnWindowBoundsChanged(aura::Window* window, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) override { + shelf_display_bounds_ = ScreenUtil::GetShelfDisplayBoundsInRoot(window); + } + + const gfx::Rect& shelf_display_bounds() const { + return shelf_display_bounds_; + } + + private: + gfx::Rect shelf_display_bounds_; + + DISALLOW_COPY_AND_ASSIGN(RootWindowTestObserver); +}; + +} // names + +// Make sure that GetShelfDisplayBoundsInRoot returns the correct bounds +// when primary display gets replaced in a following scenario. +// 1) Two displays connected: a) b) +// 2) both are disconnected and new one with the same size as b) is connected +// in one configuration event. +// See crbug.com/547280. +TEST_F(WindowTreeHostManagerTest, ReplacePrimary) { + if (!SupportsMultipleDisplays()) + return; + DisplayManager* display_manager = Shell::GetInstance()->display_manager(); + + DisplayInfo first_display_info = + CreateDisplayInfo(10, 0, gfx::Display::ROTATE_0); + first_display_info.SetBounds(gfx::Rect(0, 0, 400, 400)); + const DisplayInfo second_display_info = + CreateDisplayInfo(11, 500, gfx::Display::ROTATE_0); + + std::vector<DisplayInfo> display_info_list; + // Extended + display_info_list.push_back(first_display_info); + display_info_list.push_back(second_display_info); + display_manager->OnNativeDisplaysChanged(display_info_list); + aura::Window* primary_root = Shell::GetAllRootWindows()[0]; + + int64 new_display_id = 20; + RootWindowTestObserver test_observer; + primary_root->AddObserver(&test_observer); + + display_info_list.clear(); + const DisplayInfo new_first_display_info = + CreateDisplayInfo(new_display_id, 0, gfx::Display::ROTATE_0); + + display_info_list.push_back(new_first_display_info); + display_manager->OnNativeDisplaysChanged(display_info_list); + EXPECT_EQ("0,0 500x500", test_observer.shelf_display_bounds().ToString()); + primary_root->RemoveObserver(&test_observer); +} + TEST_F(WindowTreeHostManagerTest, UpdateMouseLocationAfterDisplayChange) { if (!SupportsMultipleDisplays()) return;
diff --git a/ash/screen_util.cc b/ash/screen_util.cc index d0e4121..02d90e2 100644 --- a/ash/screen_util.cc +++ b/ash/screen_util.cc
@@ -52,7 +52,7 @@ Shell::GetScreen()->GetDisplayNearestWindow(window).work_area()); } -gfx::Rect ScreenUtil::GetShelfDisplayBoundsInScreen(aura::Window* window) { +gfx::Rect ScreenUtil::GetShelfDisplayBoundsInRoot(aura::Window* window) { DisplayManager* display_manager = Shell::GetInstance()->display_manager(); if (display_manager->IsInUnifiedMode()) { // In unified desktop mode, there is only one shelf in the 1st display. @@ -65,9 +65,7 @@ size.Scale(scale, scale); return gfx::Rect(gfx::ToCeiledSize(size)); } else { - return gfx::Screen::GetScreenFor(window) - ->GetDisplayNearestWindow(window) - .bounds(); + return window->GetRootWindow()->bounds(); } }
diff --git a/ash/screen_util.h b/ash/screen_util.h index 971215e..79c03581 100644 --- a/ash/screen_util.h +++ b/ash/screen_util.h
@@ -44,7 +44,7 @@ // general use, we should consider always using physical display in // window layout instead of root window, and keep the logical // display only in display management code. - static gfx::Rect GetShelfDisplayBoundsInScreen(aura::Window* window); + static gfx::Rect GetShelfDisplayBoundsInRoot(aura::Window* window); // TODO(oshima): Move following two to wm/coordinate_conversion.h // Converts |rect| from |window|'s coordinates to the virtual screen
diff --git a/ash/screen_util_unittest.cc b/ash/screen_util_unittest.cc index f8d7f33..6adae38a 100644 --- a/ash/screen_util_unittest.cc +++ b/ash/screen_util_unittest.cc
@@ -125,24 +125,28 @@ NULL, CurrentContext(), gfx::Rect(10, 10, 100, 100)); UpdateDisplay("500x400"); - EXPECT_EQ("0,0 500x400", ScreenUtil::GetShelfDisplayBoundsInScreen( - widget->GetNativeWindow()).ToString()); + EXPECT_EQ("0,0 500x400", + ScreenUtil::GetShelfDisplayBoundsInRoot(widget->GetNativeWindow()) + .ToString()); UpdateDisplay("500x400,600x400"); - EXPECT_EQ("0,0 500x400", ScreenUtil::GetShelfDisplayBoundsInScreen( - widget->GetNativeWindow()).ToString()); + EXPECT_EQ("0,0 500x400", + ScreenUtil::GetShelfDisplayBoundsInRoot(widget->GetNativeWindow()) + .ToString()); // Move to the 2nd physical display. Shelf's display still should be // the first. widget->SetBounds(gfx::Rect(800, 0, 100, 100)); ASSERT_EQ("800,0 100x100", widget->GetWindowBoundsInScreen().ToString()); - EXPECT_EQ("0,0 500x400", ScreenUtil::GetShelfDisplayBoundsInScreen( - widget->GetNativeWindow()).ToString()); + EXPECT_EQ("0,0 500x400", + ScreenUtil::GetShelfDisplayBoundsInRoot(widget->GetNativeWindow()) + .ToString()); UpdateDisplay("600x500"); - EXPECT_EQ("0,0 600x500", ScreenUtil::GetShelfDisplayBoundsInScreen( - widget->GetNativeWindow()).ToString()); + EXPECT_EQ("0,0 600x500", + ScreenUtil::GetShelfDisplayBoundsInRoot(widget->GetNativeWindow()) + .ToString()); } } // namespace test
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc index 7f90844..5e1aab0 100644 --- a/ash/shelf/shelf_layout_manager.cc +++ b/ash/shelf/shelf_layout_manager.cc
@@ -749,10 +749,7 @@ const State& state, TargetBounds* target_bounds) { gfx::Rect available_bounds = - ScreenUtil::GetShelfDisplayBoundsInScreen(root_window_); - available_bounds = - ScreenUtil::ConvertRectFromScreen(root_window_, available_bounds); - + ScreenUtil::GetShelfDisplayBoundsInRoot(root_window_); gfx::Rect status_size( shelf_->status_area_widget()->GetWindowBoundsInScreen().size()); int shelf_width = 0, shelf_height = 0;
diff --git a/ash/system/web_notification/ash_popup_alignment_delegate_unittest.cc b/ash/system/web_notification/ash_popup_alignment_delegate_unittest.cc index f487c75..ad4358d8 100644 --- a/ash/system/web_notification/ash_popup_alignment_delegate_unittest.cc +++ b/ash/system/web_notification/ash_popup_alignment_delegate_unittest.cc
@@ -136,6 +136,9 @@ } TEST_F(AshPopupAlignmentDelegateTest, LockScreen) { + if (!SupportsHostWindowResize()) + return; + const gfx::Rect toast_size(0, 0, 10, 10); Shell::GetInstance()->SetShelfAlignment(
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc index 995b9f50..6658576 100644 --- a/ash/test/ash_test_helper.cc +++ b/ash/test/ash_test_helper.cc
@@ -32,6 +32,7 @@ #if defined(OS_CHROMEOS) #include "chromeos/audio/cras_audio_handler.h" #include "chromeos/dbus/dbus_thread_manager.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" #endif #if defined(OS_WIN) @@ -89,8 +90,13 @@ // Create DBusThreadManager for testing. if (!chromeos::DBusThreadManager::IsInitialized()) { chromeos::DBusThreadManager::Initialize(); + bluez::BluezDBusManager::Initialize( + chromeos::DBusThreadManager::Get()->GetSystemBus(), + chromeos::DBusThreadManager::Get()->IsUsingStub( + chromeos::DBusClientBundle::BLUETOOTH)); dbus_thread_manager_initialized_ = true; } + // Create CrasAudioHandler for testing since g_browser_process is not // created in AshTestBase tests. chromeos::CrasAudioHandler::InitializeForTesting(); @@ -137,6 +143,7 @@ #if defined(OS_CHROMEOS) chromeos::CrasAudioHandler::Shutdown(); if (dbus_thread_manager_initialized_) { + bluez::BluezDBusManager::Shutdown(); chromeos::DBusThreadManager::Shutdown(); dbus_thread_manager_initialized_ = false; }
diff --git a/ash/wm/app_list_controller.cc b/ash/wm/app_list_controller.cc index e4fdb79..67a50c3 100644 --- a/ash/wm/app_list_controller.cc +++ b/ash/wm/app_list_controller.cc
@@ -125,7 +125,8 @@ gfx::Point GetCenterOfDisplayForView(const views::View* view, int minimum_height) { aura::Window* window = view->GetWidget()->GetNativeView(); - gfx::Rect bounds = ScreenUtil::GetShelfDisplayBoundsInScreen(window); + gfx::Rect bounds = ScreenUtil::GetShelfDisplayBoundsInRoot(window); + bounds = ScreenUtil::ConvertRectToScreen(window->GetRootWindow(), bounds); // If the virtual keyboard is active, subtract it from the display bounds, so // that the app list is centered in the non-keyboard area of the display.
diff --git a/ash/wm/gestures/long_press_affordance_handler.cc b/ash/wm/gestures/long_press_affordance_handler.cc index 692510f..eafa30d 100644 --- a/ash/wm/gestures/long_press_affordance_handler.cc +++ b/ash/wm/gestures/long_press_affordance_handler.cc
@@ -100,10 +100,9 @@ SkColor* colors, SkScalar* pos, int num_colors) { - SkPoint sk_center; int radius = (end_radius + start_radius) / 2; int glow_width = end_radius - start_radius; - sk_center.iset(center.x(), center.y()); + SkPoint sk_center(PointToSkPoint(center)); skia::RefPtr<SkShader> shader = skia::AdoptRef(SkGradientShader::CreateTwoPointConical( sk_center, SkIntToScalar(start_radius), sk_center,
diff --git a/ash/wm/lock_layout_manager_unittest.cc b/ash/wm/lock_layout_manager_unittest.cc index 3f5ab9fc..944124c 100644 --- a/ash/wm/lock_layout_manager_unittest.cc +++ b/ash/wm/lock_layout_manager_unittest.cc
@@ -129,6 +129,9 @@ } TEST_F(LockLayoutManagerTest, MaximizedFullscreenWindowBoundsAreEqualToScreen) { + if (!SupportsHostWindowResize()) + return; + gfx::Rect screen_bounds = Shell::GetScreen()->GetPrimaryDisplay().bounds(); views::Widget::InitParams widget_params( @@ -178,6 +181,9 @@ } TEST_F(LockLayoutManagerTest, KeyboardBounds) { + if (!SupportsHostWindowResize()) + return; + gfx::Display primary_display = Shell::GetScreen()->GetPrimaryDisplay(); gfx::Rect screen_bounds = primary_display.bounds();
diff --git a/ash/wm/lock_window_state.cc b/ash/wm/lock_window_state.cc index d153fb25..6230dd1 100644 --- a/ash/wm/lock_window_state.cc +++ b/ash/wm/lock_window_state.cc
@@ -190,7 +190,7 @@ keyboard_bounds = keyboard_controller->current_keyboard_bounds(); } gfx::Rect bounds = - ScreenUtil::GetShelfDisplayBoundsInScreen(window_state->window()); + ScreenUtil::GetShelfDisplayBoundsInRoot(window_state->window()); bounds.set_height(bounds.height() - keyboard_bounds.height());
diff --git a/base/android/java/src/org/chromium/base/ApkAssets.java b/base/android/java/src/org/chromium/base/ApkAssets.java index a30054f..e00be99 100644 --- a/base/android/java/src/org/chromium/base/ApkAssets.java +++ b/base/android/java/src/org/chromium/base/ApkAssets.java
@@ -33,19 +33,6 @@ afd.getStartOffset(), afd.getLength() }; } catch (IOException e) { - // TODO(michaelbai): Remove dump assets once crbug.com/547235 fixed. - try { - String[] assets = context.getAssets().list(""); - StringBuffer sb = new StringBuffer("Dump assets(" + assets.length + "):\n"); - for (String asset : assets) { - sb.append(asset); - sb.append("\n"); - } - Log.e(LOGTAG, sb.toString()); - } catch (IOException ioe) { - Log.e(LOGTAG, "Error while list assets: " + ioe); - } - Log.e(LOGTAG, "Error while loading asset " + fileName + ": " + e); return new long[] {-1, -1, -1}; } finally {
diff --git a/base/android/jni_array.cc b/base/android/jni_array.cc index e419b34..e4f3f0b 100644 --- a/base/android/jni_array.cc +++ b/base/android/jni_array.cc
@@ -25,8 +25,9 @@ } // namespace -ScopedJavaLocalRef<jbyteArray> ToJavaByteArray( - JNIEnv* env, const uint8* bytes, size_t len) { +ScopedJavaLocalRef<jbyteArray> ToJavaByteArray(JNIEnv* env, + const uint8_t* bytes, + size_t len) { jbyteArray byte_array = env->NewByteArray(len); CheckException(env); DCHECK(byte_array); @@ -38,6 +39,12 @@ return ScopedJavaLocalRef<jbyteArray>(env, byte_array); } +ScopedJavaLocalRef<jbyteArray> ToJavaByteArray( + JNIEnv* env, + const std::vector<uint8_t>& bytes) { + return ToJavaByteArray(env, bytes.data(), bytes.size()); +} + ScopedJavaLocalRef<jintArray> ToJavaIntArray( JNIEnv* env, const int* ints, size_t len) { jintArray int_array = env->NewIntArray(len); @@ -56,8 +63,9 @@ return ToJavaIntArray(env, ints.data(), ints.size()); } -ScopedJavaLocalRef<jlongArray> ToJavaLongArray( - JNIEnv* env, const int64* longs, size_t len) { +ScopedJavaLocalRef<jlongArray> ToJavaLongArray(JNIEnv* env, + const int64_t* longs, + size_t len) { jlongArray long_array = env->NewLongArray(len); CheckException(env); DCHECK(long_array); @@ -69,9 +77,10 @@ return ScopedJavaLocalRef<jlongArray>(env, long_array); } -// Returns a new Java long array converted from the given int64 array. +// Returns a new Java long array converted from the given int64_t array. BASE_EXPORT ScopedJavaLocalRef<jlongArray> ToJavaLongArray( - JNIEnv* env, const std::vector<int64>& longs) { + JNIEnv* env, + const std::vector<int64_t>& longs) { return ToJavaLongArray(env, longs.data(), longs.size()); } @@ -83,8 +92,8 @@ CheckException(env); for (size_t i = 0; i < v.size(); ++i) { - ScopedJavaLocalRef<jbyteArray> byte_array = ToJavaByteArray(env, - reinterpret_cast<const uint8*>(v[i].data()), v[i].length()); + ScopedJavaLocalRef<jbyteArray> byte_array = ToJavaByteArray( + env, reinterpret_cast<const uint8_t*>(v[i].data()), v[i].length()); env->SetObjectArrayElement(joa, i, byte_array.obj()); } return ScopedJavaLocalRef<jobjectArray>(env, joa); @@ -150,7 +159,7 @@ void AppendJavaByteArrayToByteVector(JNIEnv* env, jbyteArray byte_array, - std::vector<uint8>* out) { + std::vector<uint8_t>* out) { DCHECK(out); if (!byte_array) return; @@ -165,7 +174,7 @@ void JavaByteArrayToByteVector(JNIEnv* env, jbyteArray byte_array, - std::vector<uint8>* out) { + std::vector<uint8_t>* out) { DCHECK(out); DCHECK(byte_array); out->clear(); @@ -187,7 +196,7 @@ void JavaLongArrayToInt64Vector(JNIEnv* env, jlongArray long_array, - std::vector<int64>* out) { + std::vector<int64_t>* out) { DCHECK(out); std::vector<jlong> temp; JavaLongArrayToLongVector(env, long_array, &temp);
diff --git a/base/android/jni_array.h b/base/android/jni_array.h index 658239d..86e63c5 100644 --- a/base/android/jni_array.h +++ b/base/android/jni_array.h
@@ -6,19 +6,24 @@ #define BASE_ANDROID_JNI_ARRAY_H_ #include <jni.h> +#include <stdint.h> #include <string> #include <vector> #include "base/android/scoped_java_ref.h" -#include "base/basictypes.h" #include "base/strings/string16.h" namespace base { namespace android { // Returns a new Java byte array converted from the given bytes array. +BASE_EXPORT ScopedJavaLocalRef<jbyteArray> ToJavaByteArray(JNIEnv* env, + const uint8_t* bytes, + size_t len); + BASE_EXPORT ScopedJavaLocalRef<jbyteArray> ToJavaByteArray( - JNIEnv* env, const uint8* bytes, size_t len); + JNIEnv* env, + const std::vector<uint8_t>& bytes); // Returns a new Java int array converted from the given int array. BASE_EXPORT ScopedJavaLocalRef<jintArray> ToJavaIntArray( @@ -28,11 +33,13 @@ JNIEnv* env, const std::vector<int>& ints); // Returns a new Java long array converted from the given int64 array. -BASE_EXPORT ScopedJavaLocalRef<jlongArray> ToJavaLongArray( - JNIEnv* env, const int64* longs, size_t len); +BASE_EXPORT ScopedJavaLocalRef<jlongArray> ToJavaLongArray(JNIEnv* env, + const int64_t* longs, + size_t len); BASE_EXPORT ScopedJavaLocalRef<jlongArray> ToJavaLongArray( - JNIEnv* env, const std::vector<int64>& longs); + JNIEnv* env, + const std::vector<int64_t>& longs); // Returns a array of Java byte array converted from |v|. BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray( @@ -56,16 +63,14 @@ std::vector<std::string>* out); // Appends the Java bytes in |bytes_array| onto the end of |out|. -BASE_EXPORT void AppendJavaByteArrayToByteVector( - JNIEnv* env, - jbyteArray byte_array, - std::vector<uint8>* out); +BASE_EXPORT void AppendJavaByteArrayToByteVector(JNIEnv* env, + jbyteArray byte_array, + std::vector<uint8_t>* out); // Replaces the content of |out| with the Java bytes in |bytes_array|. -BASE_EXPORT void JavaByteArrayToByteVector( - JNIEnv* env, - jbyteArray byte_array, - std::vector<uint8>* out); +BASE_EXPORT void JavaByteArrayToByteVector(JNIEnv* env, + jbyteArray byte_array, + std::vector<uint8_t>* out); // Replaces the content of |out| with the Java ints in |int_array|. BASE_EXPORT void JavaIntArrayToIntVector( @@ -74,10 +79,9 @@ std::vector<int>* out); // Replaces the content of |out| with the Java longs in |long_array|. -BASE_EXPORT void JavaLongArrayToInt64Vector( - JNIEnv* env, - jlongArray long_array, - std::vector<int64>* out); +BASE_EXPORT void JavaLongArrayToInt64Vector(JNIEnv* env, + jlongArray long_array, + std::vector<int64_t>* out); // Replaces the content of |out| with the Java longs in |long_array|. BASE_EXPORT void JavaLongArrayToLongVector(
diff --git a/base/android/jni_array_unittest.cc b/base/android/jni_array_unittest.cc index e9ae3fc..f81014e8 100644 --- a/base/android/jni_array_unittest.cc +++ b/base/android/jni_array_unittest.cc
@@ -12,22 +12,31 @@ namespace android { TEST(JniArray, BasicConversions) { - const uint8 kBytes[] = { 0, 1, 2, 3 }; + const uint8_t kBytes[] = {0, 1, 2, 3}; const size_t kLen = arraysize(kBytes); JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jbyteArray> bytes = ToJavaByteArray(env, kBytes, kLen); ASSERT_TRUE(bytes.obj()); - std::vector<uint8> vec(5); - JavaByteArrayToByteVector(env, bytes.obj(), &vec); - EXPECT_EQ(4U, vec.size()); - std::vector<uint8> expected_vec(kBytes, kBytes + kLen); - EXPECT_EQ(expected_vec, vec); + std::vector<uint8_t> inputVector(kBytes, kBytes + kLen); + ScopedJavaLocalRef<jbyteArray> bytesFromVector = + ToJavaByteArray(env, inputVector); + ASSERT_TRUE(bytesFromVector.obj()); - AppendJavaByteArrayToByteVector(env, bytes.obj(), &vec); - EXPECT_EQ(8U, vec.size()); + std::vector<uint8_t> vectorFromBytes(5); + std::vector<uint8_t> vectorFromVector(5); + JavaByteArrayToByteVector(env, bytes.obj(), &vectorFromBytes); + JavaByteArrayToByteVector(env, bytesFromVector.obj(), &vectorFromVector); + EXPECT_EQ(4U, vectorFromBytes.size()); + EXPECT_EQ(4U, vectorFromVector.size()); + std::vector<uint8_t> expected_vec(kBytes, kBytes + kLen); + EXPECT_EQ(expected_vec, vectorFromBytes); + EXPECT_EQ(expected_vec, vectorFromVector); + + AppendJavaByteArrayToByteVector(env, bytes.obj(), &vectorFromBytes); + EXPECT_EQ(8U, vectorFromBytes.size()); expected_vec.insert(expected_vec.end(), kBytes, kBytes + kLen); - EXPECT_EQ(expected_vec, vec); + EXPECT_EQ(expected_vec, vectorFromBytes); } void CheckIntConversion( @@ -58,11 +67,10 @@ CheckIntConversion(env, kInts, kLen, ToJavaIntArray(env, vec)); } -void CheckLongConversion( - JNIEnv* env, - const int64* long_array, - const size_t len, - const ScopedJavaLocalRef<jlongArray>& longs) { +void CheckLongConversion(JNIEnv* env, + const int64_t* long_array, + const size_t len, + const ScopedJavaLocalRef<jlongArray>& longs) { ASSERT_TRUE(longs.obj()); jsize java_array_len = env->GetArrayLength(longs.obj()); @@ -76,13 +84,13 @@ } TEST(JniArray, LongConversions) { - const int64 kLongs[] = { 0, 1, -1, kint64min, kint64max}; + const int64_t kLongs[] = {0, 1, -1, kint64min, kint64max}; const size_t kLen = arraysize(kLongs); JNIEnv* env = AttachCurrentThread(); CheckLongConversion(env, kLongs, kLen, ToJavaLongArray(env, kLongs, kLen)); - const std::vector<int64> vec(kLongs, kLongs + kLen); + const std::vector<int64_t> vec(kLongs, kLongs + kLen); CheckLongConversion(env, kLongs, kLen, ToJavaLongArray(env, vec)); } @@ -120,7 +128,7 @@ } TEST(JniArray, JavaLongArrayToInt64Vector) { - const int64 kInt64s[] = {0LL, 1LL, -1LL}; + const int64_t kInt64s[] = {0LL, 1LL, -1LL}; const size_t kLen = arraysize(kInt64s); JNIEnv* env = AttachCurrentThread(); @@ -133,7 +141,7 @@ ASSERT_FALSE(HasException(env)); } - std::vector<int64> int64s; + std::vector<int64_t> int64s; JavaLongArrayToInt64Vector(env, jlongs.obj(), &int64s); ASSERT_EQ(static_cast<jsize>(int64s.size()), @@ -148,7 +156,7 @@ } TEST(JniArray, JavaLongArrayToLongVector) { - const int64 kInt64s[] = {0LL, 1LL, -1LL}; + const int64_t kInt64s[] = {0LL, 1LL, -1LL}; const size_t kLen = arraysize(kInt64s); JNIEnv* env = AttachCurrentThread(); @@ -217,9 +225,9 @@ char text[16]; for (int i = 0; i < kMaxItems; ++i) { snprintf(text, sizeof text, "%d", i); - ScopedJavaLocalRef<jbyteArray> byte_array = ToJavaByteArray( - env, reinterpret_cast<uint8*>(text), - static_cast<size_t>(strlen(text))); + ScopedJavaLocalRef<jbyteArray> byte_array = + ToJavaByteArray(env, reinterpret_cast<uint8_t*>(text), + static_cast<size_t>(strlen(text))); ASSERT_TRUE(byte_array.obj()); env->SetObjectArrayElement(array.obj(), i, byte_array.obj());
diff --git a/base/android/linker/config.gni b/base/android/linker/config.gni index 99cbcf0e..a84aca6 100644 --- a/base/android/linker/config.gni +++ b/base/android/linker/config.gni
@@ -2,7 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# TODO(GYP) add "|| profiling_full_stack_frames -# Only enable the chromium linker on regular builds, since the -# component build crashes on Android 4.4. See b/11379966 -chromium_linker_supported = !is_component_build +import("//build/config/android/config.gni") + +# Chromium linker crashes on component builds on Android 4.4. See b/11379966 +# Chromium linker causes instrumentation to return incorrect results. +chromium_linker_supported = !is_component_build && !use_order_profiling
diff --git a/base/atomicops_unittest.cc b/base/atomicops_unittest.cc index 3fd5597..7298609 100644 --- a/base/atomicops_unittest.cc +++ b/base/atomicops_unittest.cc
@@ -89,6 +89,13 @@ EXPECT_EQ(1, value); EXPECT_EQ(0, prev); + // Verify that CAS will *not* change "value" if it doesn't match the + // expected number. CAS will always return the actual value of the + // variable from before any change. + AtomicType fail = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 2); + EXPECT_EQ(1, value); + EXPECT_EQ(1, fail); + // Use test value that has non-zero bits in both halves, more for testing // 64-bit implementation on 32-bit platforms. const AtomicType k_test_val = (static_cast<uint64_t>(1) <<
diff --git a/base/debug/stack_trace_posix.cc b/base/debug/stack_trace_posix.cc index d8eb005..9d0e6515 100644 --- a/base/debug/stack_trace_posix.cc +++ b/base/debug/stack_trace_posix.cc
@@ -344,7 +344,7 @@ { " trp: ", context->uc_mcontext.gregs[REG_TRAPNO] }, { " msk: ", context->uc_mcontext.gregs[REG_OLDMASK] }, { " cr2: ", context->uc_mcontext.gregs[REG_CR2] }, -#endif +#endif // ARCH_CPU_32_BITS }; #if ARCH_CPU_32_BITS @@ -363,52 +363,13 @@ PrintToStderr("\n"); } PrintToStderr("\n"); -#endif -#elif defined(OS_MACOSX) - // TODO(shess): Port to 64-bit, and ARM architecture (32 and 64-bit). -#if ARCH_CPU_X86_FAMILY && ARCH_CPU_32_BITS - ucontext_t* context = reinterpret_cast<ucontext_t*>(void_context); - size_t len; - - // NOTE: Even |snprintf()| is not on the approved list for signal - // handlers, but buffered I/O is definitely not on the list due to - // potential for |malloc()|. - len = static_cast<size_t>( - snprintf(buf, sizeof(buf), - "ax: %x, bx: %x, cx: %x, dx: %x\n", - context->uc_mcontext->__ss.__eax, - context->uc_mcontext->__ss.__ebx, - context->uc_mcontext->__ss.__ecx, - context->uc_mcontext->__ss.__edx)); - write(STDERR_FILENO, buf, std::min(len, sizeof(buf) - 1)); - - len = static_cast<size_t>( - snprintf(buf, sizeof(buf), - "di: %x, si: %x, bp: %x, sp: %x, ss: %x, flags: %x\n", - context->uc_mcontext->__ss.__edi, - context->uc_mcontext->__ss.__esi, - context->uc_mcontext->__ss.__ebp, - context->uc_mcontext->__ss.__esp, - context->uc_mcontext->__ss.__ss, - context->uc_mcontext->__ss.__eflags)); - write(STDERR_FILENO, buf, std::min(len, sizeof(buf) - 1)); - - len = static_cast<size_t>( - snprintf(buf, sizeof(buf), - "ip: %x, cs: %x, ds: %x, es: %x, fs: %x, gs: %x\n", - context->uc_mcontext->__ss.__eip, - context->uc_mcontext->__ss.__cs, - context->uc_mcontext->__ss.__ds, - context->uc_mcontext->__ss.__es, - context->uc_mcontext->__ss.__fs, - context->uc_mcontext->__ss.__gs)); - write(STDERR_FILENO, buf, std::min(len, sizeof(buf) - 1)); -#endif // ARCH_CPU_32_BITS -#endif // defined(OS_MACOSX) +#endif // ARCH_CPU_X86_FAMILY +#endif // defined(OS_LINUX) PrintToStderr("[end of stack trace]\n"); - _exit(1); + if (::signal(signal, SIG_DFL) == SIG_ERR) + _exit(1); } class PrintBacktraceOutputHandler : public BacktraceOutputHandler {
diff --git a/base/memory/scoped_ptr.h b/base/memory/scoped_ptr.h index 2399e95..c4d75a4 100644 --- a/base/memory/scoped_ptr.h +++ b/base/memory/scoped_ptr.h
@@ -216,11 +216,17 @@ } ~scoped_ptr_impl() { - if (data_.ptr != nullptr) { - // Not using get_deleter() saves one function call in non-optimized - // builds. - static_cast<D&>(data_)(data_.ptr); - } + // Match libc++, which calls reset() in its destructor. + // Use nullptr as the new value for three reasons: + // 1. libc++ does it. + // 2. Avoids infinitely recursing into destructors if two classes are owned + // in a reference cycle (see ScopedPtrTest.ReferenceCycle). + // 3. If |this| is accessed in the future, in a use-after-free bug, attempts + // to dereference |this|'s pointer should cause either a failure or a + // segfault closer to the problem. If |this| wasn't reset to nullptr, + // the access would cause the deleted memory to be read or written + // leading to other more subtle issues. + reset(nullptr); } void reset(T* p) {
diff --git a/base/memory/scoped_ptr_unittest.cc b/base/memory/scoped_ptr_unittest.cc index 71d995c..eb5bf00 100644 --- a/base/memory/scoped_ptr_unittest.cc +++ b/base/memory/scoped_ptr_unittest.cc
@@ -709,10 +709,20 @@ a->b.reset(new StructB); a->b->a.reset(a); - // Break the cycle by calling reset(). This will cause |a| (and hence, |a.b|) + // Break the cycle by calling reset(). This will cause |a| (and hence, |a->b|) // to be deleted before the call to reset() returns. This tests that the // implementation of scoped_ptr::reset() doesn't access |this| after it // deletes the underlying pointer. This behaviour is consistent with the // definition of unique_ptr::reset in C++11. a->b.reset(); + + // Go again, but this time, break the cycle by invoking |a|'s destructor. This + // tests that the implementation of ~scoped_ptr doesn't infinitely recurse + // into the destructors of |a| and |a->b|. Note, deleting |a| instead will + // cause |a| to be double-free'd because |a->b| owns |a| and deletes it via + // its destructor. + a = new StructA; + a->b.reset(new StructB); + a->b->a.reset(a); + a->~StructA(); }
diff --git a/base/threading/sequenced_task_runner_handle_unittest.cc b/base/threading/sequenced_task_runner_handle_unittest.cc index df7a1175..1080262 100644 --- a/base/threading/sequenced_task_runner_handle_unittest.cc +++ b/base/threading/sequenced_task_runner_handle_unittest.cc
@@ -12,6 +12,7 @@ #include "base/sequence_checker_impl.h" #include "base/sequenced_task_runner.h" #include "base/synchronization/waitable_event.h" +#include "base/test/sequenced_worker_pool_owner.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/sequenced_worker_pool.h" #include "base/threading/simple_thread.h" @@ -51,13 +52,16 @@ } TEST_F(SequencedTaskRunnerHandleTest, FromSequencedWorkerPool) { - scoped_refptr<SequencedWorkerPool> pool(new SequencedWorkerPool(3, "Test")); + // Wrap the SequencedWorkerPool to avoid leaks due to its asynchronous + // destruction. + SequencedWorkerPoolOwner owner(3, "Test"); WaitableEvent event(false, false); - pool->PostSequencedWorkerTask( - pool->GetSequenceToken(), FROM_HERE, + owner.pool()->PostSequencedWorkerTask( + owner.pool()->GetSequenceToken(), FROM_HERE, base::Bind(&SequencedTaskRunnerHandleTest::GetTaskRunner, base::Bind(&WaitableEvent::Signal, base::Unretained(&event)))); event.Wait(); + owner.pool()->Shutdown(); } class ThreadRunner : public DelegateSimpleThread::Delegate {
diff --git a/base/time/time.h b/base/time/time.h index 8da08ffd..49440859 100644 --- a/base/time/time.h +++ b/base/time/time.h
@@ -421,7 +421,7 @@ // To avoid overflow in QPC to Microseconds calculations, since we multiply // by kMicrosecondsPerSecond, then the QPC value should not exceed // (2^63 - 1) / 1E6. If it exceeds that threshold, we divide then multiply. - static const int64 kQPCOverflowThreshold = 0x8637BD05AF7; + enum : int64 { kQPCOverflowThreshold = 0x8637BD05AF7 }; #endif // Represents an exploded time that can be formatted nicely. This is kind of
diff --git a/base/trace_event/common/trace_event_common.h b/base/trace_event/common/trace_event_common.h index 679e923..9a61b19b 100644 --- a/base/trace_event/common/trace_event_common.h +++ b/base/trace_event/common/trace_event_common.h
@@ -1024,6 +1024,7 @@ #define TRACE_EVENT_FLAG_FLOW_IN (static_cast<unsigned int>(1 << 8)) #define TRACE_EVENT_FLAG_FLOW_OUT (static_cast<unsigned int>(1 << 9)) #define TRACE_EVENT_FLAG_HAS_CONTEXT_ID (static_cast<unsigned int>(1 << 10)) +#define TRACE_EVENT_FLAG_HAS_PROCESS_ID (static_cast<unsigned int>(1 << 11)) #define TRACE_EVENT_FLAG_SCOPE_MASK \ (static_cast<unsigned int>(TRACE_EVENT_FLAG_SCOPE_OFFSET | \
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc index c7d8e08..eec2ff39 100644 --- a/base/trace_event/memory_dump_manager.cc +++ b/base/trace_event/memory_dump_manager.cc
@@ -182,11 +182,12 @@ void MemoryDumpManager::RegisterDumpProvider( MemoryDumpProvider* mdp, const char* name, - const scoped_refptr<SingleThreadTaskRunner>& task_runner) { + const scoped_refptr<SingleThreadTaskRunner>& task_runner, + const MemoryDumpProvider::Options& options) { if (dumper_registrations_ignored_for_testing_) return; - MemoryDumpProviderInfo mdp_info(mdp, name, task_runner); + MemoryDumpProviderInfo mdp_info(mdp, name, task_runner, options); AutoLock lock(lock_); auto iter_new = dump_providers_.insert(mdp_info); @@ -203,6 +204,13 @@ mdp->OnHeapProfilingEnabled(true); } +void MemoryDumpManager::RegisterDumpProvider( + MemoryDumpProvider* mdp, + const char* name, + const scoped_refptr<SingleThreadTaskRunner>& task_runner) { + RegisterDumpProvider(mdp, name, task_runner, MemoryDumpProvider::Options()); +} + void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) { AutoLock lock(lock_); @@ -323,6 +331,11 @@ const uint64_t dump_guid = pmd_async_state->req_args.dump_guid; const char* dump_provider_name = nullptr; + // Pid of the target process being dumped. Often kNullProcessId (= current + // process), non-zero when the coordinator process creates dumps on behalf + // of child processes (see crbug.com/461788). + ProcessId pid; + // DO NOT put any LOG() statement in the locked sections, as in some contexts // (GPU process) LOG() ends up performing PostTask/IPCs. MemoryDumpProvider* mdp; @@ -333,6 +346,7 @@ auto mdp_info = pmd_async_state->next_dump_provider; mdp = mdp_info->dump_provider; dump_provider_name = mdp_info->name; + pid = mdp_info->options.target_pid; // If the dump provider did not specify a thread affinity, dump on // |dump_thread_|. @@ -382,8 +396,9 @@ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "dump_provider.name", dump_provider_name); MemoryDumpArgs args = {pmd_async_state->req_args.level_of_detail}; - dump_successful = - mdp->OnMemoryDump(args, &pmd_async_state->process_memory_dump); + ProcessMemoryDump* process_memory_dump = + pmd_async_state->GetOrCreateMemoryDumpContainerForProcess(pid); + dump_successful = mdp->OnMemoryDump(args, process_memory_dump); } { @@ -433,20 +448,25 @@ "MemoryDumpManager::FinalizeDumpAndAddToTrace", TRACE_ID_MANGLE(dump_guid), TRACE_EVENT_FLAG_FLOW_IN); - TracedValue* traced_value = new TracedValue(); - scoped_refptr<ConvertableToTraceFormat> event_value(traced_value); - pmd_async_state->process_memory_dump.AsValueInto(traced_value); - traced_value->SetString("level_of_detail", - MemoryDumpLevelOfDetailToString( - pmd_async_state->req_args.level_of_detail)); - const char* const event_name = - MemoryDumpTypeToString(pmd_async_state->req_args.dump_type); + for (const auto& kv : pmd_async_state->process_dumps) { + ProcessId pid = kv.first; // kNullProcessId for the current process. + ProcessMemoryDump* process_memory_dump = kv.second; + TracedValue* traced_value = new TracedValue(); + scoped_refptr<ConvertableToTraceFormat> event_value(traced_value); + process_memory_dump->AsValueInto(traced_value); + traced_value->SetString("level_of_detail", + MemoryDumpLevelOfDetailToString( + pmd_async_state->req_args.level_of_detail)); + const char* const event_name = + MemoryDumpTypeToString(pmd_async_state->req_args.dump_type); - TRACE_EVENT_API_ADD_TRACE_EVENT( - TRACE_EVENT_PHASE_MEMORY_DUMP, - TraceLog::GetCategoryGroupEnabled(kTraceCategory), event_name, dump_guid, - kTraceEventNumArgs, kTraceEventArgNames, kTraceEventArgTypes, - nullptr /* arg_values */, &event_value, TRACE_EVENT_FLAG_HAS_ID); + TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID( + TRACE_EVENT_PHASE_MEMORY_DUMP, + TraceLog::GetCategoryGroupEnabled(kTraceCategory), event_name, + dump_guid, pid, kTraceEventNumArgs, kTraceEventArgNames, + kTraceEventArgTypes, nullptr /* arg_values */, &event_value, + TRACE_EVENT_FLAG_HAS_ID); + } if (!pmd_async_state->callback.is_null()) { pmd_async_state->callback.Run(dump_guid, true /* success */); @@ -577,10 +597,12 @@ MemoryDumpManager::MemoryDumpProviderInfo::MemoryDumpProviderInfo( MemoryDumpProvider* dump_provider, const char* name, - const scoped_refptr<SingleThreadTaskRunner>& task_runner) + const scoped_refptr<SingleThreadTaskRunner>& task_runner, + const MemoryDumpProvider::Options& options) : dump_provider(dump_provider), name(name), task_runner(task_runner), + options(options), consecutive_failures(0), disabled(false), unregistered(false) {} @@ -601,9 +623,9 @@ const scoped_refptr<MemoryDumpSessionState>& session_state, MemoryDumpCallback callback, const scoped_refptr<SingleThreadTaskRunner>& dump_thread_task_runner) - : process_memory_dump(session_state), - req_args(req_args), + : req_args(req_args), next_dump_provider(next_dump_provider), + session_state(session_state), callback(callback), callback_task_runner(MessageLoop::current()->task_runner()), dump_thread_task_runner(dump_thread_task_runner) {} @@ -611,5 +633,15 @@ MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() { } +ProcessMemoryDump* MemoryDumpManager::ProcessMemoryDumpAsyncState:: + GetOrCreateMemoryDumpContainerForProcess(ProcessId pid) { + auto iter = process_dumps.find(pid); + if (iter == process_dumps.end()) { + scoped_ptr<ProcessMemoryDump> new_pmd(new ProcessMemoryDump(session_state)); + iter = process_dumps.insert(pid, new_pmd.Pass()).first; + } + return iter->second; +} + } // namespace trace_event } // namespace base
diff --git a/base/trace_event/memory_dump_manager.h b/base/trace_event/memory_dump_manager.h index aca8828..7f0508b4 100644 --- a/base/trace_event/memory_dump_manager.h +++ b/base/trace_event/memory_dump_manager.h
@@ -9,6 +9,7 @@ #include "base/atomicops.h" #include "base/containers/hash_tables.h" +#include "base/containers/scoped_ptr_map.h" #include "base/memory/ref_counted.h" #include "base/memory/singleton.h" #include "base/synchronization/lock.h" @@ -63,13 +64,19 @@ // - name: a friendly name (duplicates allowed). Used for debugging and // run-time profiling of memory-infra internals. Must be a long-lived // C string. - // - task_runner: (optional) if non-null, all the calls to |mdp| will be + // - task_runner: if non-null, all the calls to |mdp| will be // issued on the given thread. Otherwise, |mdp| should be able to // handle calls on arbitrary threads. + // - options: extra optional arguments. See memory_dump_provider.h. void RegisterDumpProvider( MemoryDumpProvider* mdp, const char* name, const scoped_refptr<SingleThreadTaskRunner>& task_runner); + void RegisterDumpProvider( + MemoryDumpProvider* mdp, + const char* name, + const scoped_refptr<SingleThreadTaskRunner>& task_runner, + const MemoryDumpProvider::Options& options); void UnregisterDumpProvider(MemoryDumpProvider* mdp); // Requests a memory dump. The dump might happen or not depending on the @@ -128,7 +135,8 @@ MemoryDumpProviderInfo( MemoryDumpProvider* dump_provider, const char* name, - const scoped_refptr<SingleThreadTaskRunner>& task_runner); + const scoped_refptr<SingleThreadTaskRunner>& task_runner, + const MemoryDumpProvider::Options& options); ~MemoryDumpProviderInfo(); // Define a total order based on the thread (i.e. |task_runner|) affinity, @@ -137,7 +145,13 @@ MemoryDumpProvider* const dump_provider; const char* const name; - scoped_refptr<SingleThreadTaskRunner> task_runner; // Optional. + + // The task_runner affinity. Can be nullptr, in which case the dump provider + // will be invoked on |dump_thread_|. + scoped_refptr<SingleThreadTaskRunner> task_runner; + + // The |options| arg passed to RegisterDumpProvider(). + const MemoryDumpProvider::Options options; // For fail-safe logic (auto-disable failing MDPs). These fields are mutable // as can be safely changed without impacting the order within the set. @@ -164,9 +178,14 @@ const scoped_refptr<SingleThreadTaskRunner>& dump_thread_task_runner); ~ProcessMemoryDumpAsyncState(); - // The ProcessMemoryDump container, where each dump provider will dump its - // own MemoryAllocatorDump(s) upon the OnMemoryDump() call. - ProcessMemoryDump process_memory_dump; + // Gets or creates the memory dump container for the given target process. + ProcessMemoryDump* GetOrCreateMemoryDumpContainerForProcess(ProcessId pid); + + // A map of ProcessId -> ProcessMemoryDump, one for each target process + // being dumped from the current process. Typically each process dumps only + // for itself, unless dump providers specify a different |target_process| in + // MemoryDumpProvider::Options. + ScopedPtrMap<ProcessId, scoped_ptr<ProcessMemoryDump>> process_dumps; // The arguments passed to the initial CreateProcessDump() request. const MemoryDumpRequestArgs req_args; @@ -175,6 +194,9 @@ // invoked (or dump_providers_.end() if at the end of the sequence). MemoryDumpProviderInfoSet::iterator next_dump_provider; + // The trace-global session state. + scoped_refptr<MemoryDumpSessionState> session_state; + // Callback passed to the initial call to CreateProcessDump(). MemoryDumpCallback callback;
diff --git a/base/trace_event/memory_dump_manager_unittest.cc b/base/trace_event/memory_dump_manager_unittest.cc index da93ee1..75a6c26 100644 --- a/base/trace_event/memory_dump_manager_unittest.cc +++ b/base/trace_event/memory_dump_manager_unittest.cc
@@ -11,10 +11,12 @@ #include "base/strings/stringprintf.h" #include "base/synchronization/waitable_event.h" #include "base/test/test_io_thread.h" +#include "base/test/trace_event_analyzer.h" #include "base/thread_task_runner_handle.h" #include "base/threading/thread.h" #include "base/trace_event/memory_dump_provider.h" #include "base/trace_event/process_memory_dump.h" +#include "base/trace_event/trace_buffer.h" #include "base/trace_event/trace_config_memory_test_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -39,18 +41,30 @@ } namespace { + void RegisterDumpProvider( MemoryDumpProvider* mdp, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, + const MemoryDumpProvider::Options& options) { MemoryDumpManager* mdm = MemoryDumpManager::GetInstance(); mdm->set_dumper_registrations_ignored_for_testing(false); - mdm->RegisterDumpProvider(mdp, "TestDumpProvider", task_runner); + mdm->RegisterDumpProvider(mdp, "TestDumpProvider", task_runner, options); mdm->set_dumper_registrations_ignored_for_testing(true); } void RegisterDumpProvider(MemoryDumpProvider* mdp) { - RegisterDumpProvider(mdp, nullptr); + RegisterDumpProvider(mdp, nullptr, MemoryDumpProvider::Options()); } + +void OnTraceDataCollected(Closure quit_closure, + trace_event::TraceResultBuffer* buffer, + const scoped_refptr<RefCountedString>& json, + bool has_more_events) { + buffer->AddFragment(json->data()); + if (!has_more_events) + quit_closure.Run(); +} + } // namespace // Testing MemoryDumpManagerDelegate which, by default, short-circuits dump @@ -81,6 +95,8 @@ class MemoryDumpManagerTest : public testing::Test { public: + MemoryDumpManagerTest() : testing::Test(), kDefaultOptions() {} + void SetUp() override { last_callback_success_ = false; message_loop_.reset(new MessageLoop()); @@ -144,6 +160,7 @@ return MemoryDumpManager::kMaxConsecutiveFailuresCount; } + const MemoryDumpProvider::Options kDefaultOptions; scoped_ptr<MemoryDumpManager> mdm_; scoped_ptr<MemoryDumpManagerDelegateForTesting> delegate_; bool last_callback_success_; @@ -189,7 +206,7 @@ EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED, MemoryDumpLevelOfDetail::DETAILED); - TraceLog::GetInstance()->SetDisabled(); + DisableTracing(); } // Checks that requesting dumps with high level of detail actually propagates @@ -366,7 +383,7 @@ scoped_refptr<SingleThreadTaskRunner> task_runner = thread->task_runner(); MockMemoryDumpProvider* mdp = new MockMemoryDumpProvider(); mdps.push_back(mdp); - RegisterDumpProvider(mdp, task_runner); + RegisterDumpProvider(mdp, task_runner, kDefaultOptions); EXPECT_CALL(*mdp, OnMemoryDump(_, _)) .Times(i) .WillRepeatedly(Invoke( @@ -481,8 +498,8 @@ MockMemoryDumpProvider mdp1; MockMemoryDumpProvider mdp2; - RegisterDumpProvider(&mdp1, ThreadTaskRunnerHandle::Get()); - RegisterDumpProvider(&mdp2, ThreadTaskRunnerHandle::Get()); + RegisterDumpProvider(&mdp1, ThreadTaskRunnerHandle::Get(), kDefaultOptions); + RegisterDumpProvider(&mdp2, ThreadTaskRunnerHandle::Get(), kDefaultOptions); EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(4); @@ -521,7 +538,8 @@ for (int i = 0; i < 2; i++) { threads.push_back(new TestIOThread(TestIOThread::kAutoStart)); mdps.push_back(new MockMemoryDumpProvider()); - RegisterDumpProvider(mdps.back(), threads.back()->task_runner()); + RegisterDumpProvider(mdps.back(), threads.back()->task_runner(), + kDefaultOptions); } int on_memory_dump_call_count = 0; @@ -707,7 +725,8 @@ scoped_ptr<Thread> mdp_thread(new Thread("test thread")); mdp_thread->Start(); MockMemoryDumpProvider mdp_with_affinity; - RegisterDumpProvider(&mdp_with_affinity, mdp_thread->task_runner()); + RegisterDumpProvider(&mdp_with_affinity, mdp_thread->task_runner(), + kDefaultOptions); // Register also an unbound dump provider. Unbound dump providers are always // invoked after bound ones. @@ -748,5 +767,61 @@ EXPECT_FALSE(last_callback_success_); } +TEST_F(MemoryDumpManagerTest, DumpOnBehalfOfOtherProcess) { + using trace_analyzer::Query; + + InitializeMemoryDumpManager(false /* is_coordinator */); + + // Standard provider with default options (create dump for current process). + MemoryDumpProvider::Options options; + MockMemoryDumpProvider mdp1; + RegisterDumpProvider(&mdp1, nullptr, options); + + // Provider with out-of-process dumping. + MockMemoryDumpProvider mdp2; + options.target_pid = 123; + RegisterDumpProvider(&mdp2, nullptr, options); + + // Another provider with out-of-process dumping. + MockMemoryDumpProvider mdp3; + options.target_pid = 456; + RegisterDumpProvider(&mdp3, nullptr, options); + + EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); + EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1); + EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true)); + EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true)); + EXPECT_CALL(mdp3, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true)); + RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED, + MemoryDumpLevelOfDetail::DETAILED); + DisableTracing(); + + // Flush the trace into JSON. + trace_event::TraceResultBuffer buffer; + TraceResultBuffer::SimpleOutput trace_output; + buffer.SetOutputCallback(trace_output.GetCallback()); + RunLoop run_loop; + buffer.Start(); + trace_event::TraceLog::GetInstance()->Flush( + Bind(&OnTraceDataCollected, run_loop.QuitClosure(), Unretained(&buffer))); + run_loop.Run(); + buffer.Finish(); + + // Analyze the JSON. + scoped_ptr<trace_analyzer::TraceAnalyzer> analyzer = make_scoped_ptr( + trace_analyzer::TraceAnalyzer::Create(trace_output.json_output)); + trace_analyzer::TraceEventVector events; + analyzer->FindEvents(Query::EventPhaseIs(TRACE_EVENT_PHASE_MEMORY_DUMP), + &events); + + ASSERT_EQ(3u, events.size()); + ASSERT_EQ(1u, trace_analyzer::CountMatches(events, Query::EventPidIs(123))); + ASSERT_EQ(1u, trace_analyzer::CountMatches(events, Query::EventPidIs(456))); + ASSERT_EQ(1u, trace_analyzer::CountMatches( + events, Query::EventPidIs(GetCurrentProcId()))); + ASSERT_EQ(events[0]->id, events[1]->id); + ASSERT_EQ(events[0]->id, events[2]->id); +} + } // namespace trace_event } // namespace base
diff --git a/base/trace_event/memory_dump_provider.h b/base/trace_event/memory_dump_provider.h index 35df620..48eaaaeb 100644 --- a/base/trace_event/memory_dump_provider.h +++ b/base/trace_event/memory_dump_provider.h
@@ -7,6 +7,7 @@ #include "base/base_export.h" #include "base/macros.h" +#include "base/process/process_handle.h" #include "base/trace_event/memory_dump_request_args.h" namespace base { @@ -23,6 +24,18 @@ // The contract interface that memory dump providers must implement. class BASE_EXPORT MemoryDumpProvider { public: + // Optional arguments for MemoryDumpManager::RegisterDumpProvider(). + struct Options { + Options() : target_pid(kNullProcessId) {} + explicit Options(ProcessId target_pid) : target_pid(target_pid) {} + + // If the dump provider generates dumps on behalf of another process, + // |target_process| contains the pid of that process. + // The default value is kNullProcessId, which means that the dump provider + // generates dumps for the current process. + ProcessId target_pid; + }; + // Called by the MemoryDumpManager when generating memory dumps. // The |args| specify if the embedder should generate light/heavy dumps on // dump requests. The embedder should return true if the |pmd| was
diff --git a/base/trace_event/memory_profiler_allocation_context.cc b/base/trace_event/memory_profiler_allocation_context.cc index bafbf7f..6d02876 100644 --- a/base/trace_event/memory_profiler_allocation_context.cc +++ b/base/trace_event/memory_profiler_allocation_context.cc
@@ -114,6 +114,10 @@ out->append("}"); // End the |stackFrames| dictionary. } +bool operator==(const AllocationContext& lhs, const AllocationContext& rhs) { + return (lhs.backtrace == rhs.backtrace) && (lhs.type_id == rhs.type_id); +} + AllocationContextTracker* AllocationContextTracker::GetThreadLocalTracker() { auto tracker = static_cast<AllocationContextTracker*>(g_tls_alloc_ctx_tracker.Get()); @@ -181,6 +185,8 @@ std::fill(dst, dst_end, nullptr); } + ctx.type_id = 0; + return ctx; } @@ -188,6 +194,7 @@ } // namespace base namespace BASE_HASH_NAMESPACE { +using base::trace_event::AllocationContext; using base::trace_event::Backtrace; size_t hash<Backtrace>::operator()(const Backtrace& backtrace) const { @@ -195,4 +202,14 @@ sizeof(backtrace.frames)); } +size_t hash<AllocationContext>::operator()(const AllocationContext& ctx) const { + size_t ctx_hash = hash<Backtrace>()(ctx.backtrace); + + // Multiply one side to break the commutativity of +. Multiplication with a + // number coprime to |numeric_limits<size_t>::max() + 1| is bijective so + // randomness is preserved. The type ID is assumed to be distributed randomly + // already so there is no need to hash it. + return (ctx_hash * 3) + static_cast<size_t>(ctx.type_id); +} + } // BASE_HASH_NAMESPACE
diff --git a/base/trace_event/memory_profiler_allocation_context.h b/base/trace_event/memory_profiler_allocation_context.h index 31c134d..7c110ef 100644 --- a/base/trace_event/memory_profiler_allocation_context.h +++ b/base/trace_event/memory_profiler_allocation_context.h
@@ -142,10 +142,23 @@ // when heap profiling is enabled. To simplify memory management for // bookkeeping, this struct has a fixed size. All |const char*|s here // must have static lifetime. +// TODO(ruuda): Make the default constructor private to avoid accidentally +// constructing an instance and forgetting to initialize it. Only +// |AllocationContextTracker| should be able to construct. (And tests.) struct BASE_EXPORT AllocationContext { + // A type ID is a number that is unique for every C++ type. A type ID is + // stored instead of the type name to avoid inflating the binary with type + // name strings. There is an out of band lookup table mapping IDs to the type + // names. A value of 0 means that the type is not known. + using TypeId = uint16_t; + Backtrace backtrace; + TypeId type_id; }; +bool BASE_EXPORT operator==(const AllocationContext& lhs, + const AllocationContext& rhs); + // The allocation context tracker keeps track of thread-local context for heap // profiling. It includes a pseudo stack of trace events. On every allocation // the tracker provides a snapshot of its context in the form of an @@ -207,6 +220,11 @@ size_t operator()(const base::trace_event::Backtrace& backtrace) const; }; +template <> +struct hash<base::trace_event::AllocationContext> { + size_t operator()(const base::trace_event::AllocationContext& context) const; +}; + } // BASE_HASH_NAMESPACE #endif // BASE_TRACE_EVENT_MEMORY_PROFILER_ALLOCATION_CONTEXT_H_
diff --git a/base/trace_event/memory_profiler_heap_dump_writer.cc b/base/trace_event/memory_profiler_heap_dump_writer.cc index 37395ac..81b1285 100644 --- a/base/trace_event/memory_profiler_heap_dump_writer.cc +++ b/base/trace_event/memory_profiler_heap_dump_writer.cc
@@ -4,8 +4,8 @@ #include "base/trace_event/memory_profiler_heap_dump_writer.h" +#include <algorithm> #include <iterator> -#include <numeric> #include "base/format_macros.h" #include "base/strings/stringprintf.h" @@ -15,6 +15,8 @@ namespace base { namespace trace_event { +using TypeId = AllocationContext::TypeId; + namespace { template <typename T> @@ -24,8 +26,12 @@ } template <typename T> -size_t PairSizeAdd(size_t acc, const std::pair<T, size_t>& rhs) { - return acc + rhs.second; +std::vector<std::pair<T, size_t>> SortDescending( + const hash_map<T, size_t>& grouped) { + std::vector<std::pair<T, size_t>> sorted; + std::copy(grouped.begin(), grouped.end(), std::back_inserter(sorted)); + std::sort(sorted.begin(), sorted.end(), PairSizeGt<T>); + return sorted; } } // namespace @@ -38,38 +44,50 @@ void HeapDumpWriter::InsertAllocation(const AllocationContext& context, size_t size) { - bytes_by_backtrace_[context.backtrace] += size; + bytes_by_context_[context] += size; } scoped_refptr<TracedValue> HeapDumpWriter::WriteHeapDump() { - // Sort the backtraces by size in descending order. - std::vector<std::pair<Backtrace, size_t>> sorted_by_backtrace; + // Group by backtrace and by type ID, and compute the total heap size while + // iterating anyway. + size_t total_size = 0; + hash_map<Backtrace, size_t> bytes_by_backtrace; + hash_map<TypeId, size_t> bytes_by_type; - std::copy(bytes_by_backtrace_.begin(), bytes_by_backtrace_.end(), - std::back_inserter(sorted_by_backtrace)); - std::sort(sorted_by_backtrace.begin(), sorted_by_backtrace.end(), - PairSizeGt<Backtrace>); + for (auto context_size : bytes_by_context_) { + total_size += context_size.second; + bytes_by_backtrace[context_size.first.backtrace] += context_size.second; + bytes_by_type[context_size.first.type_id] += context_size.second; + } + + // Sort the backtraces and type IDs by size. + auto sorted_bytes_by_backtrace = SortDescending(bytes_by_backtrace); + auto sorted_bytes_by_type = SortDescending(bytes_by_type); traced_value_->BeginArray("entries"); // The global size, no column specified. { - size_t total_size = - std::accumulate(sorted_by_backtrace.begin(), sorted_by_backtrace.end(), - size_t(0), PairSizeAdd<Backtrace>); traced_value_->BeginDictionary(); WriteSize(total_size); traced_value_->EndDictionary(); } - // Size per backtrace. - for (auto it = sorted_by_backtrace.begin(); - it != sorted_by_backtrace.end(); it++) { + // Entries with the size per backtrace. + for (const auto& entry : sorted_bytes_by_backtrace) { traced_value_->BeginDictionary(); // Insert a forward reference to the backtrace that will be written to the // |stackFrames| dictionary later on. - WriteStackFrameIndex(stack_frame_deduplicator_->Insert(it->first)); - WriteSize(it->second); + WriteStackFrameIndex(stack_frame_deduplicator_->Insert(entry.first)); + WriteSize(entry.second); + traced_value_->EndDictionary(); + } + + // Entries with the size per type. + for (const auto& entry : sorted_bytes_by_type) { + traced_value_->BeginDictionary(); + WriteTypeId(entry.first); + WriteSize(entry.second); traced_value_->EndDictionary(); } @@ -91,6 +109,19 @@ } } +void HeapDumpWriter::WriteTypeId(TypeId type_id) { + if (type_id == 0) { + // Type ID 0 represents "unknown type". Instead of writing it as "0" which + // could be mistaken for an actual type ID, an unknown type is represented + // by the empty string. + traced_value_->SetString("type", ""); + } else { + // Format the type ID as a string. + SStringPrintf(&buffer_, "%i", type_id); + traced_value_->SetString("type", buffer_); + } +} + void HeapDumpWriter::WriteSize(size_t size) { // Format size as hexadecimal string into |buffer_|. SStringPrintf(&buffer_, "%" PRIx64, static_cast<uint64_t>(size));
diff --git a/base/trace_event/memory_profiler_heap_dump_writer.h b/base/trace_event/memory_profiler_heap_dump_writer.h index f05e338f..10a64e5 100644 --- a/base/trace_event/memory_profiler_heap_dump_writer.h +++ b/base/trace_event/memory_profiler_heap_dump_writer.h
@@ -44,6 +44,9 @@ // dictionary. void WriteStackFrameIndex(int index); + // Writes a "type" key with the stringified type ID. + void WriteTypeId(AllocationContext::TypeId type_id); + // Writes a "size" key with value |size| as a hexidecimal string to the traced // value. void WriteSize(size_t size); @@ -55,8 +58,9 @@ // this heap dump writer instance. StackFrameDeduplicator* const stack_frame_deduplicator_; - // A map of backtrace to the number of bytes allocated for that backtrace. - hash_map<Backtrace, size_t> bytes_by_backtrace_; + // A map of allocation context to the number of bytes allocated for that + // context. + hash_map<AllocationContext, size_t> bytes_by_context_; // Buffer for converting integers into strings, that is re-used throughout the // dump.
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h index 8137251..37320ea 100644 --- a/base/trace_event/trace_event.h +++ b/base/trace_event/trace_event.h
@@ -125,6 +125,26 @@ #define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_CONTEXT_ID \ base::trace_event::TraceLog::GetInstance()->AddTraceEventWithContextId +// Add a trace event to the platform tracing system overriding the pid. +// The resulting event will have tid = pid == (process_id passed here). +// base::trace_event::TraceEventHandle +// TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID( +// char phase, +// const unsigned char* category_group_enabled, +// const char* name, +// unsigned long long id, +// unsigned long long context_id, +// int process_id, +// int num_args, +// const char** arg_names, +// const unsigned char* arg_types, +// const unsigned long long* arg_values, +// const scoped_refptr<ConvertableToTraceFormat>* +// convertable_values, +// unsigned int flags) +#define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID \ + base::trace_event::TraceLog::GetInstance()->AddTraceEventWithProcessId + // Add a trace event to the platform tracing system. // base::trace_event::TraceEventHandle // TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP(
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc index 60ef16b..778ecbf0b 100644 --- a/base/trace_event/trace_event_impl.cc +++ b/base/trace_event/trace_event_impl.cc
@@ -6,6 +6,7 @@ #include "base/format_macros.h" #include "base/json/string_escape.h" +#include "base/process/process_handle.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -60,7 +61,10 @@ context_id_ = other.context_id_; category_group_enabled_ = other.category_group_enabled_; name_ = other.name_; - thread_id_ = other.thread_id_; + if (other.flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID) + process_id_ = other.process_id_; + else + thread_id_ = other.thread_id_; phase_ = other.phase_; flags_ = other.flags_; parameter_copy_storage_ = other.parameter_copy_storage_; @@ -270,7 +274,16 @@ std::string* out, const ArgumentFilterPredicate& argument_filter_predicate) const { int64 time_int64 = timestamp_.ToInternalValue(); - int process_id = TraceLog::GetInstance()->process_id(); + int process_id; + int thread_id; + if ((flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID) && + process_id_ != kNullProcessId) { + process_id = process_id_; + thread_id = -1; + } else { + process_id = TraceLog::GetInstance()->process_id(); + thread_id = thread_id_; + } const char* category_group_name = TraceLog::GetCategoryGroupName(category_group_enabled_); @@ -279,7 +292,7 @@ StringAppendF(out, "{\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 "," "\"ph\":\"%c\",\"cat\":\"%s\",\"name\":\"%s\",\"args\":", - process_id, thread_id_, time_int64, phase_, category_group_name, + process_id, thread_id, time_int64, phase_, category_group_name, name_); // Output argument names and values, stop at first NULL argument name.
diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h index 59401631..cb8b144 100644 --- a/base/trace_event/trace_event_impl.h +++ b/base/trace_event/trace_event_impl.h
@@ -168,7 +168,13 @@ const unsigned char* category_group_enabled_; const char* name_; scoped_refptr<base::RefCountedString> parameter_copy_storage_; - int thread_id_; + // Depending on TRACE_EVENT_FLAG_HAS_PROCESS_ID the event will have either: + // tid: thread_id_, pid: current_process_id (default case). + // tid: -1, pid: process_id_ (when flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID). + union { + int thread_id_; + int process_id_; + }; unsigned int flags_; unsigned long long bind_id_; unsigned char arg_types_[kTraceMaxNumArgs];
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc index a8d50caf..c9cb1b3 100644 --- a/base/trace_event/trace_log.cc +++ b/base/trace_event/trace_log.cc
@@ -1129,6 +1129,36 @@ flags | TRACE_EVENT_FLAG_HAS_CONTEXT_ID); } +TraceEventHandle TraceLog::AddTraceEventWithProcessId( + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int process_id, + int num_args, + const char** arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + const scoped_refptr<ConvertableToTraceFormat>* convertable_values, + unsigned int flags) { + base::TraceTicks now = base::TraceTicks::Now(); + return AddTraceEventWithThreadIdAndTimestamp( + phase, + category_group_enabled, + name, + id, + trace_event_internal::kNoId, // context_id + trace_event_internal::kNoId, // bind_id + process_id, + now, + num_args, + arg_names, + arg_types, + arg_values, + convertable_values, + flags | TRACE_EVENT_FLAG_HAS_PROCESS_ID); +} + // Handle legacy calls to AddTraceEventWithThreadIdAndTimestamp // with kNoId as bind_id TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
diff --git a/base/trace_event/trace_log.h b/base/trace_event/trace_log.h index 425c7f35..a68a3805 100644 --- a/base/trace_event/trace_log.h +++ b/base/trace_event/trace_log.h
@@ -202,6 +202,18 @@ const unsigned long long* arg_values, const scoped_refptr<ConvertableToTraceFormat>* convertable_values, unsigned int flags); + TraceEventHandle AddTraceEventWithProcessId( + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int process_id, + int num_args, + const char** arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + const scoped_refptr<ConvertableToTraceFormat>* convertable_values, + unsigned int flags); TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( char phase, const unsigned char* category_group_enabled,
diff --git a/blimp/common/BUILD.gn b/blimp/common/BUILD.gn index 5e439ba..4c3e275 100644 --- a/blimp/common/BUILD.gn +++ b/blimp/common/BUILD.gn
@@ -6,10 +6,6 @@ component("blimp_common") { sources = [ - # TODO(dtrainor): Remove this once the LayerTreeHost settings for Blimp - # are finalized or are pushed from the server component. See - # crbug.com/527655. - "../../content/public/common/content_switches.cc", "blimp_common_export.h", "compositor/blimp_layer_tree_settings.cc", "compositor/blimp_layer_tree_settings.h", @@ -17,6 +13,15 @@ "compositor/blimp_task_graph_runner.h", ] + if (is_android) { + sources += [ + # TODO(dtrainor): Remove this once the LayerTreeHost settings for Blimp + # are finalized or are pushed from the server component. See + # crbug.com/527655. + "../../content/public/common/content_switches.cc", + ] + } + defines = [ "BLIMP_COMMON_IMPLEMENTATION=1" ] deps = [
diff --git a/blimp/docs/build.md b/blimp/docs/build.md index 1162375..5f5a3a1 100644 --- a/blimp/docs/build.md +++ b/blimp/docs/build.md
@@ -36,6 +36,8 @@ is_component_build = true symbol_level = 1 # Use -g1 instead of -g2 use_goma = true +use_aura = true +use_ozone = true ``` # Building
diff --git a/blimp/engine/BUILD.gn b/blimp/engine/BUILD.gn index 7009257b..3522ae2c 100644 --- a/blimp/engine/BUILD.gn +++ b/blimp/engine/BUILD.gn
@@ -61,10 +61,6 @@ ":blimp_engine_app", ":pak", "//sandbox/linux:chrome_sandbox", - - # TODO(maniscalco): Get rid of osmesa once we no longer depend on X - # (crbug.com/540932, crbug.com/541203). - "//third_party/mesa:osmesa", ] }
diff --git a/blimp/engine/Dockerfile b/blimp/engine/Dockerfile index c5ea7a3d..21a4d224 100644 --- a/blimp/engine/Dockerfile +++ b/blimp/engine/Dockerfile
@@ -1,16 +1,13 @@ FROM ubuntu:trusty -# TODO(maniscalco): Remove X related packages once we no longer depend on X -# (crbug.com/540932). +# Run the command below to update the lib list. +# ldd ./blimp_engine_app | grep usr/lib | awk '{print $3}' | xargs -n1 \ +# dpkg-query -S | awk -F: '{print $1}' RUN apt-get update && \ - apt-get install -yq libasound2 libatk1.0-0 libavahi-client3 libavahi-common3 \ - libcairo2 libcups2 libdatrie1 libdbus-glib-1-2 libffi6 libfontconfig1 \ - libgconf-2-4 libglib2.0-0 libgnutls26 libgraphite2-3 libgssapi-krb5-2 \ - libk5crypto3 libkrb5-3 libkrb5support0 libnspr4 libnss3 libotf0 libp11-kit0 \ - libpango1.0-0 libpixman-1-0 libstdc++6 libtasn1-6 libthai0 libx11-6 libxau6 \ - libxcb1 libxcb-render0 libxcb-shm0 libxcomposite1 libxcursor1 libxdamage1 \ - libxdmcp6 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 \ - xvfb + apt-get install -yq libnss3 libnss3 libnss3 libnspr4 libnspr4 libnspr4 \ + libfreetype6 libfontconfig1 libdrm2 libasound2 libcups2 libgssapi-krb5-2 \ + libkrb5-3 libk5crypto3 libstdc++6 libgnutls26 libavahi-common3 \ + libavahi-client3 libkrb5support0 libtasn1-6 libp11-kit0 libffi6 RUN mkdir /engine @@ -23,11 +20,4 @@ USER blimp_user WORKDIR "/engine" -# Invoke xvfb-run using a shell command string to work around a bug where -# xvfb-run fails to invoke the engine and hangs. -# -# TODO(maniscalco): Once we no longer depend on X, stop using the shell command -# string, xvfb-run, and the use-gl flag. (crbug.com/540932, crbug.com/541203). -ENTRYPOINT ["/bin/sh", "-c", \ - "/usr/bin/xvfb-run -a /engine/blimp_engine_app --use-gl=osmesa $@", \ - "/usr/bin/xvfb-run"] +ENTRYPOINT ["/engine/blimp_engine_app", "--disable-gpu"]
diff --git a/blimp/engine/engine-manifest.txt b/blimp/engine/engine-manifest.txt index a5dcbf4..9b78601 100644 --- a/blimp/engine/engine-manifest.txt +++ b/blimp/engine/engine-manifest.txt
@@ -7,7 +7,5 @@ ./blimp_engine_app icudtl.dat natives_blob.bin -snapshot_blob.bin blimp_engine.pak ./chrome_sandbox -./libosmesa.so
diff --git a/blimp/net/BUILD.gn b/blimp/net/BUILD.gn index b4d23751..1b4da84 100644 --- a/blimp/net/BUILD.gn +++ b/blimp/net/BUILD.gn
@@ -10,12 +10,15 @@ "blimp_message_dispatcher.h", "blimp_message_receiver.h", "blimp_net_export.h", + "blimp_transport.h", "common.cc", "common.h", "packet_reader.cc", "packet_reader.h", "packet_writer.cc", "packet_writer.h", + "tcp_client_transport.cc", + "tcp_client_transport.h", ] defines = [ "BLIMP_NET_IMPLEMENTATION=1" ]
diff --git a/blimp/net/blimp_transport.h b/blimp/net/blimp_transport.h new file mode 100644 index 0000000..5ee9fff --- /dev/null +++ b/blimp/net/blimp_transport.h
@@ -0,0 +1,39 @@ +// Copyright 2015 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 BLIMP_NET_BLIMP_TRANSPORT_H_ +#define BLIMP_NET_BLIMP_TRANSPORT_H_ + +#include "base/memory/scoped_ptr.h" +#include "net/base/completion_callback.h" +#include "net/socket/stream_socket.h" + +namespace blimp { + +// An interface which encapsulates the transport-specific code for +// establishing network connections between the client and engine. +// Subclasses of BlimpTransport are responsible for defining their own +// methods for receiving connection arguments. +class BlimpTransport { + public: + virtual ~BlimpTransport() {} + + // Initiate or listen for a connection. + // + // Returns net::OK if a connection is established synchronously. + // Returns an error code if a synchronous error occurred. + // Returns net::ERR_IO_PENDING if the connection is being established + // asynchronously. |callback| is later invoked with the connection outcome. + // + // If the connection is successful, the connected socket can be taken by + // calling TakeConnectedSocket(). + virtual int Connect(const net::CompletionCallback& callback) = 0; + + // Returns the connected socket following a successful Connect(). + virtual scoped_ptr<net::StreamSocket> TakeConnectedSocket() = 0; +}; + +} // namespace blimp + +#endif // BLIMP_NET_BLIMP_TRANSPORT_H_
diff --git a/blimp/net/tcp_client_transport.cc b/blimp/net/tcp_client_transport.cc new file mode 100644 index 0000000..3d52aa4 --- /dev/null +++ b/blimp/net/tcp_client_transport.cc
@@ -0,0 +1,54 @@ +// Copyright 2015 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 "blimp/net/tcp_client_transport.h" + +#include "base/callback.h" +#include "base/callback_helpers.h" +#include "base/memory/scoped_ptr.h" +#include "net/socket/stream_socket.h" +#include "net/socket/tcp_client_socket.h" + +namespace blimp { + +TCPClientTransport::TCPClientTransport(const net::AddressList& addresses, + net::NetLog* net_log) + : addresses_(addresses), net_log_(net_log) {} + +TCPClientTransport::~TCPClientTransport() {} + +int TCPClientTransport::Connect(const net::CompletionCallback& callback) { + DCHECK(!socket_); + DCHECK(!callback.is_null()); + + socket_.reset( + new net::TCPClientSocket(addresses_, net_log_, net::NetLog::Source())); + net::CompletionCallback completion_callback = base::Bind( + &TCPClientTransport::OnTCPConnectComplete, base::Unretained(this)); + + int result = socket_->Connect(completion_callback); + if (result == net::ERR_IO_PENDING) { + connect_callback_ = callback; + } else if (result != net::OK) { + socket_ = nullptr; + } + + return result; +} + +scoped_ptr<net::StreamSocket> TCPClientTransport::TakeConnectedSocket() { + DCHECK(socket_); + DCHECK(connect_callback_.is_null()); + return socket_.Pass(); +} + +void TCPClientTransport::OnTCPConnectComplete(int result) { + DCHECK(socket_); + if (result != net::OK) { + socket_ = nullptr; + } + base::ResetAndReturn(&connect_callback_).Run(result); +} + +} // namespace blimp
diff --git a/blimp/net/tcp_client_transport.h b/blimp/net/tcp_client_transport.h new file mode 100644 index 0000000..ac383d50 --- /dev/null +++ b/blimp/net/tcp_client_transport.h
@@ -0,0 +1,46 @@ +// Copyright 2015 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 BLIMP_NET_TCP_CLIENT_TRANSPORT_H_ +#define BLIMP_NET_TCP_CLIENT_TRANSPORT_H_ + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "blimp/net/blimp_transport.h" +#include "net/base/address_list.h" +#include "net/base/net_errors.h" + +namespace net { +class NetLog; +class StreamSocket; +} // namespace net + +namespace blimp { + +// BlimpTransport which creates a TCP connection to one of the specified +// |addresses| on each call to Connect(). +class TCPClientTransport : public BlimpTransport { + public: + TCPClientTransport(const net::AddressList& addresses, net::NetLog* net_log); + ~TCPClientTransport() override; + + // BlimpTransport implementation. + int Connect(const net::CompletionCallback& callback) override; + scoped_ptr<net::StreamSocket> TakeConnectedSocket() override; + + private: + void OnTCPConnectComplete(int result); + + net::AddressList addresses_; + net::NetLog* net_log_; + scoped_ptr<net::StreamSocket> socket_; + net::CompletionCallback connect_callback_; + + DISALLOW_COPY_AND_ASSIGN(TCPClientTransport); +}; + +} // namespace blimp + +#endif // BLIMP_NET_TCP_CLIENT_TRANSPORT_H_
diff --git a/build/android/findbugs_filter/findbugs_exclude.xml b/build/android/findbugs_filter/findbugs_exclude.xml index dbff9d96..320a2bf 100644 --- a/build/android/findbugs_filter/findbugs_exclude.xml +++ b/build/android/findbugs_filter/findbugs_exclude.xml
@@ -14,8 +14,9 @@ <Match> <Class name="~.*\.R(\$\w+)?" /> </Match> + <!-- Skip the generated Manifest class (including nested classes). --> <Match> - <Class name="~org\.chromium\..*\.Manifest(\$\w+)?" /> + <Class name="~.*\.Manifest(\$\w+)?" /> </Match> <Bug pattern="DM_STRING_CTOR" /> <!-- Ignore "reliance on default String encoding" warnings, as we're not multi-platform -->
diff --git a/build/android/gyp/java_google_api_keys.py b/build/android/gyp/java_google_api_keys.py new file mode 100755 index 0000000..2f7b6e46 --- /dev/null +++ b/build/android/gyp/java_google_api_keys.py
@@ -0,0 +1,129 @@ +#!/usr/bin/env python +# +# Copyright 2015 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. + +# Generates a Java file with API keys. + +import argparse +import os +import string +import sys +import zipfile + +sys.path.append( + os.path.abspath(os.path.join(sys.path[0], '../../../google_apis'))) +import google_api_keys + +sys.path.append(os.path.abspath(os.path.join( + os.path.dirname(__file__), os.pardir))) +from pylib import constants + + +PACKAGE = 'org.chromium.chrome' +CLASSNAME = 'GoogleAPIKeys' +HERMETIC_TIMESTAMP = (2001, 1, 1, 0, 0, 0) +HERMETIC_FILE_ATTR = (0644 << 16L) + + +def GetScriptName(): + return os.path.relpath(__file__, constants.DIR_SOURCE_ROOT) + + +def GenerateOutput(constant_definitions): + template = string.Template(""" +// Copyright 2015 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. + +// This file is autogenerated by +// ${SCRIPT_NAME} +// From +// ${SOURCE_PATH} + +package ${PACKAGE}; + +public class ${CLASS_NAME} { +${CONSTANT_ENTRIES} +} +""") + + constant_template = string.Template( + ' public static final String ${NAME} = "${VALUE}";') + constant_entries_list = [] + for constant_name, constant_value in constant_definitions.iteritems(): + values = { + 'NAME': constant_name, + 'VALUE': constant_value, + } + constant_entries_list.append(constant_template.substitute(values)) + constant_entries_string = '\n'.join(constant_entries_list) + + values = { + 'CLASS_NAME': CLASSNAME, + 'CONSTANT_ENTRIES': constant_entries_string, + 'PACKAGE': PACKAGE, + 'SCRIPT_NAME': GetScriptName(), + 'SOURCE_PATH': 'google_api_keys/google_api_keys.h', + } + return template.substitute(values) + + +def _DoWriteJavaOutput(output_path, constant_definition): + folder = os.path.dirname(output_path) + if folder and not os.path.exists(folder): + os.makedirs(folder) + with open(output_path, 'w') as out_file: + out_file.write(GenerateOutput(constant_definition)) + + +def _DoWriteJarOutput(output_path, constant_definition): + folder = os.path.dirname(output_path) + if folder and not os.path.exists(folder): + os.makedirs(folder) + with zipfile.ZipFile(output_path, 'w') as srcjar: + path = '%s/%s' % (PACKAGE.replace('.', '/'), CLASSNAME + '.java') + zipinfo = zipfile.ZipInfo(filename=path, + date_time=HERMETIC_TIMESTAMP) + zipinfo.external_attr = HERMETIC_FILE_ATTR + srcjar.writestr(zipinfo, GenerateOutput(constant_definition)) + + +def _DoMain(argv): + parser = argparse.ArgumentParser() + parser.add_argument("--out", help="Path for java output.") + parser.add_argument("--srcjar", help="Path for srcjar output.") + options = parser.parse_args(argv) + if not options.out and not options.srcjar: + parser.print_help() + sys.exit(-1) + + values = {} + values['GOOGLE_API_KEY'] = google_api_keys.GetAPIKey() + values['GOOGLE_API_KEY_REMOTING'] = google_api_keys.GetAPIKeyRemoting() + values['GOOGLE_CLIENT_ID_MAIN'] = google_api_keys.GetClientID('MAIN') + values['GOOGLE_CLIENT_SECRET_MAIN'] = google_api_keys.GetClientSecret('MAIN') + values['GOOGLE_CLIENT_ID_CLOUD_PRINT'] = google_api_keys.GetClientID( + 'CLOUD_PRINT') + values['GOOGLE_CLIENT_SECRET_CLOUD_PRINT'] = google_api_keys.GetClientSecret( + 'CLOUD_PRINT') + values['GOOGLE_CLIENT_ID_REMOTING'] = google_api_keys.GetClientID('REMOTING') + values['GOOGLE_CLIENT_SECRET_REMOTING'] = google_api_keys.GetClientSecret( + 'REMOTING') + values['GOOGLE_CLIENT_ID_REMOTING_HOST'] = google_api_keys.GetClientID( + 'REMOTING_HOST') + values['GOOGLE_CLIENT_SECRET_REMOTING_HOST'] = (google_api_keys. + GetClientSecret('REMOTING_HOST')) + values['GOOGLE_CLIENT_ID_REMOTING_IDENTITY_API'] = (google_api_keys. + GetClientID('REMOTING_IDENTITY_API')) + + if options.out: + _DoWriteJavaOutput(options.out, values) + if options.srcjar: + _DoWriteJarOutput(options.srcjar, values) + + +if __name__ == '__main__': + _DoMain(sys.argv[1:]) +
diff --git a/build/android/gyp/java_google_api_keys_tests.py b/build/android/gyp/java_google_api_keys_tests.py new file mode 100755 index 0000000..eb24ea4 --- /dev/null +++ b/build/android/gyp/java_google_api_keys_tests.py
@@ -0,0 +1,61 @@ +#!/usr/bin/env python +# Copyright 2015 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. + +"""Tests for java_google_api_keys.py. + +This test suite contains various tests for the C++ -> Java Google API Keys +generator. +""" + +import collections +import argparse +import os +import sys +import unittest + +import java_google_api_keys + +sys.path.append(os.path.join(os.path.dirname(__file__), "gyp")) +from util import build_utils + + +class TestJavaGoogleAPIKeys(unittest.TestCase): + def testOutput(self): + definition = {'E1': 'abc', 'E2': 'defgh'} + output = java_google_api_keys.GenerateOutput(definition) + expected = """ +// Copyright 2015 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. + +// This file is autogenerated by +// %s +// From +// google_api_keys/google_api_keys.h + +package org.chromium.chrome; + +public class GoogleAPIKeys { + public static final String E1 = "abc"; + public static final String E2 = "defgh"; +} +""" + self.assertEqual(expected % java_google_api_keys.GetScriptName(), output) + + +def main(argv): + parser = argparse.ArgumentParser() + parser.add_argument("--stamp", help="File to touch on success.") + options = parser.parse_args(argv) + + suite = unittest.TestLoader().loadTestsFromTestCase(TestJavaGoogleAPIKeys) + unittest.TextTestRunner(verbosity=0).run(suite) + + if options.stamp: + build_utils.Touch(options.stamp) + +if __name__ == '__main__': + main(sys.argv[1:]) +
diff --git a/build/android/gyp/package_resources.py b/build/android/gyp/package_resources.py index 68c7b49..a1f3840c 100755 --- a/build/android/gyp/package_resources.py +++ b/build/android/gyp/package_resources.py
@@ -296,15 +296,26 @@ options.language_splits)) input_paths = [ options.android_manifest ] + options.resource_zips + + input_strings = [] + input_strings.extend(package_command) + + # The md5_check.py doesn't count file path in md5 intentionally, + # in order to repackage resources when assets' name changed, we need + # to put assets into input_strings, as we know the assets path isn't + # changed among each build if there is no asset change. if options.asset_dir and os.path.exists(options.asset_dir): + asset_paths = [] for root, _, filenames in os.walk(options.asset_dir): - input_paths.extend(os.path.join(root, f) for f in filenames) + asset_paths.extend(os.path.join(root, f) for f in filenames) + input_paths.extend(asset_paths) + input_strings.extend(sorted(asset_paths)) build_utils.CallAndWriteDepfileIfStale( lambda: _OnStaleMd5(package_command, options), options, input_paths=input_paths, - input_strings=package_command, + input_strings=input_strings, output_paths=output_paths)
diff --git a/build/android/java_google_api_keys.gyp b/build/android/java_google_api_keys.gyp new file mode 100644 index 0000000..df046b6 --- /dev/null +++ b/build/android/java_google_api_keys.gyp
@@ -0,0 +1,45 @@ +# Copyright 2015 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. + +# This file provides an action to generate Java source files from the Google +# API keys using a Python script. + +{ + 'targets': [ + { + 'target_name': 'google_api_keys_java', + 'type': 'none', + 'variables': { + # Location where all generated Java sources will be placed. + 'output_dir': '<(SHARED_INTERMEDIATE_DIR)/java_google_api_keys', + 'generator_path': '<(DEPTH)/build/android/gyp/java_google_api_keys.py', + 'output_file': '<(output_dir)/GoogleAPIKeys.java', + }, + 'direct_dependent_settings': { + 'variables': { + # Ensure that the output directory is used in the class path + # when building targets that depend on this one. + 'generated_src_dirs': [ + '<(output_dir)/', + ], + }, + }, + 'actions': [ + { + 'action_name': 'generate_java_google_api_keys', + 'inputs': [ + '<(generator_path)', + ], + 'outputs': [ + '<(output_file)', + ], + 'action': [ + 'python', '<(generator_path)', '--out', '<(output_file)' + ], + 'message': 'Generating Java from Google API Keys header', + }, + ], + }, + ], +}
diff --git a/build/android/play_services/config.json b/build/android/play_services/config.json new file mode 100644 index 0000000..df669e92 --- /dev/null +++ b/build/android/play_services/config.json
@@ -0,0 +1,3 @@ +{ + "version_number": 8115000 +}
diff --git a/build/android/play_services/config.yaml b/build/android/play_services/config.yaml deleted file mode 100644 index de83be0..0000000 --- a/build/android/play_services/config.yaml +++ /dev/null
@@ -1,7 +0,0 @@ ---- -## -# Configuration file for the Google Play services related scripts. -# - -# Mirrors @integer/google_play_services_version from the library. -version_number: 8115000
diff --git a/build/android/play_services/update.py b/build/android/play_services/update.py index 5966db2..b2d57ad 100755 --- a/build/android/play_services/update.py +++ b/build/android/play_services/update.py
@@ -42,7 +42,7 @@ # Path to the default configuration file. It exposes the currently installed # version of the library in a human readable way. CONFIG_DEFAULT_PATH = os.path.join(constants.DIR_SOURCE_ROOT, 'build', - 'android', 'play_services', 'config.yaml') + 'android', 'play_services', 'config.json') LICENSE_FILE_NAME = 'LICENSE' LIBRARY_FILE_NAME = 'google_play_services_library.zip' @@ -123,7 +123,7 @@ help='name of the bucket where the files are stored', default=GMS_CLOUD_STORAGE) parser.add_argument('--config', - help='YAML Configuration file', + help='JSON Configuration file', default=CONFIG_DEFAULT_PATH) parser.add_argument('--dry-run', action='store_true', @@ -157,8 +157,9 @@ logging.debug('The Google Play services library is up to date.') return 0 + config = utils.ConfigParser(args.config) bucket_path = _VerifyBucketPathFormat(args.bucket, - utils.GetVersionNumber(args.config), + config.version_number, args.dry_run) tmp_root = tempfile.mkdtemp() @@ -245,13 +246,13 @@ logging.error('The repo is dirty. Please commit or stash your changes.') return -1 - old_version_number = utils.GetVersionNumber(args.config) + config = utils.ConfigParser(args.config) version_xml = os.path.join(paths.lib, 'res', 'values', 'version.xml') new_version_number = utils.GetVersionNumberFromLibraryResources(version_xml) logging.debug('comparing versions: new=%d, old=%s', - new_version_number, old_version_number) - if new_version_number <= old_version_number and not args.force: + new_version_number, config.version_number) + if new_version_number <= config.version_number and not args.force: logging.info('The checked in version of the library is already the latest ' 'one. No update needed. Please rerun with --force to skip ' 'this check.') @@ -281,13 +282,13 @@ finally: shutil.rmtree(tmp_root) - utils.UpdateVersionNumber(args.config, new_version_number) + config.UpdateVersionNumber(new_version_number) if not args.skip_git: commit_message = ('Update the Google Play services dependency to %s\n' '\n') % new_version_number utils.MakeLocalCommit(constants.DIR_SOURCE_ROOT, - [new_lib_zip_sha1, new_license_sha1, args.config], + [new_lib_zip_sha1, new_license_sha1, config.path], commit_message) return 0
diff --git a/build/android/play_services/utils.py b/build/android/play_services/utils.py index 94e684bc..90339d2 100644 --- a/build/android/play_services/utils.py +++ b/build/android/play_services/utils.py
@@ -9,20 +9,17 @@ import argparse import filecmp +import json import logging import os import re import sys -import yaml import zipfile sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir)) from devil.utils import cmd_helper -_CONFIG_VERSION_NUMBER_KEY = 'version_number' -_YAML_VERSION_NUMBER_PATTERN = re.compile( - r'(^\s*%s\s*:\s*)(\d+)(.*$)' % _CONFIG_VERSION_NUMBER_KEY, re.MULTILINE) _XML_VERSION_NUMBER_PATTERN = re.compile( r'<integer name="google_play_services_version">(\d+)<\/integer>') @@ -37,6 +34,39 @@ pass +class ConfigParser(object): + '''Reads and writes the configuration files for play services related scripts + + The configuration files are JSON files. Here is the data they are expected + to contain: + + - version_number + Number. Mirrors @integer/google_play_services_version from the library. + Example: 815000 + + ''' + _VERSION_NUMBER_KEY = 'version_number' + + def __init__(self, path): + self.path = path + self.data = {} + + with open(path, 'r') as stream: + self.data = json.load(stream) + + @property + def version_number(self): + return self.data[self._VERSION_NUMBER_KEY] + + def UpdateVersionNumber(self, new_version_number): + '''Updates the version number and saves it in the configuration file. ''' + + with open(self.path, 'w') as stream: + self.data[self._VERSION_NUMBER_KEY] = new_version_number + json.dump(self.data, stream, sort_keys=True, indent=2) + stream.write(os.linesep) + + def FileEquals(expected_file, actual_file): ''' Returns whether the two files are equal. Returns False if any of the files @@ -72,38 +102,6 @@ return int(match.group(1)) -def UpdateVersionNumber(config_file_path, new_version_number): - '''Updates the version number in the update/preprocess configuration file.''' - - with open(config_file_path, 'r+') as stream: - config_content = stream.read() - # Implemented as string replacement instead of yaml parsing to preserve - # whitespace and comments. - updated = _YAML_VERSION_NUMBER_PATTERN.sub( - r'\g<1>%s\g<3>' % new_version_number, config_content) - stream.seek(0) - stream.write(updated) - - -def GetVersionNumber(config_file_path): - ''' - Returns the version number from an update/preprocess configuration file. - ''' - - return int(GetConfig(config_file_path)[_CONFIG_VERSION_NUMBER_KEY]) - - -def GetConfig(path): - ''' - Returns the configuration from an an update/preprocess configuration file as - as dictionary. - ''' - - with open(path, 'r') as stream: - config = yaml.load(stream) - return config - - def MakeLocalCommit(repo_root, files_to_commit, message): '''Makes a local git commit.'''
diff --git a/build/android/pylib/constants/__init__.py b/build/android/pylib/constants/__init__.py index 0b61403..25c0b0f5 100644 --- a/build/android/pylib/constants/__init__.py +++ b/build/android/pylib/constants/__init__.py
@@ -194,6 +194,7 @@ 'path': os.path.join(DIR_SOURCE_ROOT, 'build', 'android', 'gyp'), 'test_modules': [ 'java_cpp_enum_tests', + 'java_google_api_keys_tests', ] }, }
diff --git a/build/android/v8_external_startup_data_arch_suffix.gypi b/build/android/v8_external_startup_data_arch_suffix.gypi new file mode 100644 index 0000000..7af2443f --- /dev/null +++ b/build/android/v8_external_startup_data_arch_suffix.gypi
@@ -0,0 +1,21 @@ +# Copyright (c) 2015 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. + +{ + 'variables': { + 'arch_suffix': '<(arch_suffix)', + 'variables': { + # This help to find out if target_arch is set to something else. + 'arch_suffix': '<(target_arch)', + 'conditions': [ + ['target_arch=="arm" or target_arch=="ia32" or target_arch=="mipsel"', { + 'arch_suffix': '32', + }], + ['target_arch=="arm64" or target_arch=="x64" or target_arch=="mips64el"', { + 'arch_suffix':'64' + }], + ], + } + } +}
diff --git a/build/common.gypi b/build/common.gypi index 2f4d922..780f43d 100644 --- a/build/common.gypi +++ b/build/common.gypi
@@ -649,7 +649,6 @@ 'enable_mdns%' : 0, 'enable_service_discovery%': 0, - 'enable_wifi_bootstrapping%': 0, 'enable_hangout_services_extension%': 0, # Enable the Syzygy optimization step. @@ -1010,10 +1009,6 @@ 'enable_print_preview%': 0, }], - ['OS=="win" or OS=="mac"', { - 'enable_wifi_bootstrapping%' : 1, - }], - # Path to sas.dll, which provides the SendSAS function. # http://msdn.microsoft.com/en-us/library/windows/desktop/dd979761(v=vs.85).aspx ['target_arch=="x64"', { @@ -1241,7 +1236,6 @@ 'native_memory_pressure_signals%': '<(native_memory_pressure_signals)', 'enable_mdns%' : '<(enable_mdns)', 'enable_service_discovery%' : '<(enable_service_discovery)', - 'enable_wifi_bootstrapping%': '<(enable_wifi_bootstrapping)', 'enable_hangout_services_extension%' : '<(enable_hangout_services_extension)', 'proprietary_codecs%': '<(proprietary_codecs)', 'use_goma%': '<(use_goma)', @@ -2192,9 +2186,6 @@ ['notifications==1', { 'grit_defines': ['-D', 'enable_notifications'], }], - ['enable_wifi_bootstrapping==1', { - 'grit_defines': ['-D', 'enable_wifi_bootstrapping'], - }], ['mac_views_browser==1', { 'grit_defines': ['-D', 'mac_views_browser'], }], @@ -3040,9 +3031,6 @@ ['enable_service_discovery==1', { 'defines' : [ 'ENABLE_SERVICE_DISCOVERY=1' ], }], - ['enable_wifi_bootstrapping==1', { - 'defines' : [ 'ENABLE_WIFI_BOOTSTRAPPING=1' ], - }], ['enable_hangout_services_extension==1', { 'defines': ['ENABLE_HANGOUT_SERVICES_EXTENSION=1'], }],
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn index 6573cb47..9e5e776 100644 --- a/build/config/BUILD.gn +++ b/build/config/BUILD.gn
@@ -218,9 +218,6 @@ if (enable_autofill_dialog) { defines += [ "ENABLE_AUTOFILL_DIALOG=1" ] } - if (enable_wifi_bootstrapping) { - defines += [ "ENABLE_WIFI_BOOTSTRAPPING=1" ] - } if (enable_image_loader_extension) { defines += [ "IMAGE_LOADER_EXTENSION=1" ] }
diff --git a/build/config/features.gni b/build/config/features.gni index 41b53e6b..0f639bed 100644 --- a/build/config/features.gni +++ b/build/config/features.gni
@@ -182,8 +182,6 @@ enable_service_discovery = enable_mdns || is_mac -enable_wifi_bootstrapping = is_win || is_mac - # Image loader extension is enabled on ChromeOS only. enable_image_loader_extension = is_chromeos
diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi index 718c40e9..c0f55d24 100644 --- a/build/gn_migration.gypi +++ b/build/gn_migration.gypi
@@ -176,6 +176,7 @@ }], ['OS=="android"', { 'dependencies': [ + '../base/base.gyp:base_junit_tests', '../base/base.gyp:base_unittests_apk', '../base/base.gyp:chromium_android_linker', '../breakpad/breakpad.gyp:breakpad_unittests_deps', @@ -188,19 +189,23 @@ '../cc/cc_tests.gyp:cc_unittests_apk', #"//clank" TODO(GYP) - conditional somehow? '../components/components_tests.gyp:components_browsertests_apk', + '../components/components_tests.gyp:components_junit_tests', '../components/components_tests.gyp:components_unittests_apk', '../content/content_shell_and_tests.gyp:content_browsertests_apk', '../content/content_shell_and_tests.gyp:content_gl_tests_apk', + '../content/content_shell_and_tests.gyp:content_junit_tests', '../content/content_shell_and_tests.gyp:content_shell_apk', '../content/content_shell_and_tests.gyp:content_unittests_apk', '../device/device_tests.gyp:device_unittests_apk', '../gpu/gpu.gyp:gpu_unittests_apk', '../media/media.gyp:media_unittests_apk', '../media/midi/midi.gyp:midi_unittests_apk', + '../net/net.gyp:net_junit_tests', '../net/net.gyp:net_unittests_apk', '../skia/skia_tests.gyp:skia_unittests_apk', '../sql/sql.gyp:sql_unittests_apk', '../sync/sync.gyp:sync_unit_tests_apk', + '../testing/android/junit/junit_test.gyp:junit_unit_tests', '../third_party/WebKit/Source/platform/blink_platform_tests.gyp:blink_heap_unittests_apk', '../third_party/WebKit/Source/platform/blink_platform_tests.gyp:blink_platform_unittests_apk', '../third_party/WebKit/Source/web/web_tests.gyp:webkit_unit_tests_apk', @@ -250,6 +255,7 @@ '../chrome/android/chrome_apk.gyp:chrome_public_apk', '../chrome/android/chrome_apk.gyp:chrome_public_test_apk', '../chrome/chrome.gyp:chromedriver_webview_shell_apk', + '../chrome/chrome.gyp:chrome_junit_tests', '../chrome/chrome.gyp:unit_tests_apk', '../third_party/custom_tabs_client/custom_tabs_client.gyp:custom_tabs_client_example_apk', ], @@ -514,6 +520,11 @@ '../win8/win8.gyp:metro_viewer', ], }], + ['chromecast==1', { + 'dependencies': [ + '../chromecast/chromecast.gyp:cast_shell', + ] + }] ], }, { @@ -741,25 +752,20 @@ ['OS=="android"', { 'dependencies': [ '../base/base.gyp:base_perftests_apk', - '../base/base.gyp:base_junit_tests', '../cc/cc_tests.gyp:cc_perftests_apk', '../components/components.gyp:cronet_sample_apk', '../components/components.gyp:cronet_sample_test_apk', '../components/components.gyp:cronet_test_apk', '../components/components.gyp:cronet_test_instrumentation_apk', '../components/components.gyp:cronet_perf_test_apk', - '../components/components_tests.gyp:components_junit_tests', '../content/content_shell_and_tests.gyp:chromium_linker_test_apk', - '../content/content_shell_and_tests.gyp:content_junit_tests', '../content/content_shell_and_tests.gyp:content_shell_test_apk', '../content/content_shell_and_tests.gyp:video_decode_accelerator_unittest_apk', '../gpu/gpu.gyp:gl_tests_apk', '../gpu/gpu.gyp:gpu_perftests_apk', '../ipc/ipc.gyp:ipc_tests_apk', '../media/media.gyp:media_perftests_apk', - '../net/net.gyp:net_junit_tests', '../sandbox/sandbox.gyp:sandbox_linux_unittests_deps', - '../testing/android/junit/junit_test.gyp:junit_unit_tests', '../tools/android/android_tools.gyp:memconsumer', '../ui/android/ui_android.gyp:ui_android_unittests_apk', '../url/url.gyp:url_unittests', @@ -777,7 +783,6 @@ '../android_webview/android_webview_shell.gyp:system_webview_shell_page_cycler_apk', '../chrome/android/chrome_apk.gyp:chrome_sync_shell_apk', '../chrome/android/chrome_apk.gyp:chrome_sync_shell_test_apk', - '../chrome/chrome.gyp:chrome_junit_tests', '../remoting/remoting.gyp:remoting_apk', ], }],
diff --git a/build/secondary/tools/grit/grit_rule.gni b/build/secondary/tools/grit/grit_rule.gni index f5c08ea..a5cf81a 100644 --- a/build/secondary/tools/grit/grit_rule.gni +++ b/build/secondary/tools/grit/grit_rule.gni
@@ -270,12 +270,6 @@ "enable_notifications", ] } -if (enable_wifi_bootstrapping) { - grit_defines += [ - "-D", - "enable_wifi_bootstrapping", - ] -} if (enable_service_discovery) { grit_defines += [ "-D",
diff --git a/build/util/version.gni b/build/util/version.gni index d1bf6ef..fba8d25 100644 --- a/build/util/version.gni +++ b/build/util/version.gni
@@ -17,11 +17,15 @@ # all values we need at once. _version_dictionary_template = "full = \"@MAJOR@.@MINOR@.@BUILD@.@PATCH@\" " + "major = \"@MAJOR@\" minor = \"@MINOR@\" " + - "build = \"@BUILD@\" patch = \"@PATCH@\"" + "build = \"@BUILD@\" patch = \"@PATCH@\" " + + "remoting = \"@REMOTING_PATCH\" " # The file containing the Chrome version number. chrome_version_file = "//chrome/VERSION" +# The file containing the Chromoting version number. +remoting_version_file = "//remoting/VERSION" + _result = exec_script("version.py", [ "-f", @@ -40,3 +44,4 @@ chrome_version_minor = _result.minor chrome_version_build = _result.build chrome_version_patch = _result.patch +remoting_version_patch = _result.remoting
diff --git a/build_overrides/v8.gni b/build_overrides/v8.gni index ee1b666..f1f27de 100644 --- a/build_overrides/v8.gni +++ b/build_overrides/v8.gni
@@ -22,3 +22,21 @@ v8_extra_library_files = [] v8_experimental_extra_library_files = [ "../third_party/WebKit/Source/core/streams/ByteLengthQueuingStrategy.js" ] + +if (is_android) { + v8_external_startup_data_renaming_sources = [ + "$root_out_dir/natives_blob.bin", + "$root_out_dir/snapshot_blob.bin", + ] + if (current_cpu == "arm" || current_cpu == "x86" || current_cpu == "mipsel") { + v8_external_startup_data_renaming_destinations = [ + "natives_blob_32.bin", + "snapshot_blob_32.bin", + ] + } else { + v8_external_startup_data_renaming_destinations = [ + "natives_blob_64.bin", + "snapshot_blob_64.bin", + ] + } +}
diff --git a/cc/DEPS b/cc/DEPS index 8bf3649b..3d2bec6c 100644 --- a/cc/DEPS +++ b/cc/DEPS
@@ -8,6 +8,7 @@ "+gpu/command_buffer/common/gpu_memory_allocation.h", "+gpu/command_buffer/common/mailbox.h", "+gpu/command_buffer/common/mailbox_holder.h", + "+gpu/command_buffer/common/sync_token.h", "+media", "+skia/ext", "+third_party/khronos/GLES2/gl2.h",
diff --git a/cc/animation/animation_timeline.cc b/cc/animation/animation_timeline.cc index c3f5e69..a5d320b 100644 --- a/cc/animation/animation_timeline.cc +++ b/cc/animation/animation_timeline.cc
@@ -50,8 +50,6 @@ ErasePlayers(iter, iter + 1); break; } - - player->SetAnimationHost(nullptr); } AnimationPlayer* AnimationTimeline::GetPlayerById(int player_id) const { @@ -103,6 +101,7 @@ if (player->element_animations()) player->DetachLayer(); player->SetAnimationTimeline(nullptr); + player->SetAnimationHost(nullptr); } players_.erase(begin, end);
diff --git a/cc/blink/web_external_texture_layer_impl.cc b/cc/blink/web_external_texture_layer_impl.cc index acc7df44..92414a9 100644 --- a/cc/blink/web_external_texture_layer_impl.cc +++ b/cc/blink/web_external_texture_layer_impl.cc
@@ -81,9 +81,15 @@ if (bitmap) { *mailbox = cc::TextureMailbox(bitmap->shared_bitmap(), bitmap->size()); } else { + gpu::SyncToken sync_token; + static_assert(sizeof(sync_token) <= sizeof(client_mailbox.syncToken), + "Size of web external sync token too small."); + if (client_mailbox.validSyncToken) + memcpy(&sync_token, client_mailbox.syncToken, sizeof(sync_token)); + // TODO(achaulk): pass a valid size here if allowOverlay is set. - *mailbox = cc::TextureMailbox(name, GL_TEXTURE_2D, client_mailbox.syncPoint, - gfx::Size(), client_mailbox.allowOverlay); + *mailbox = cc::TextureMailbox(name, sync_token, GL_TEXTURE_2D, gfx::Size(), + client_mailbox.allowOverlay); } mailbox->set_nearest_neighbor(client_mailbox.nearestNeighbor); @@ -112,12 +118,16 @@ base::WeakPtr<WebExternalTextureLayerImpl> layer, const blink::WebExternalTextureMailbox& mailbox, WebExternalBitmapImpl* bitmap, - unsigned sync_point, + const gpu::SyncToken& sync_token, bool lost_resource) { DCHECK(layer); blink::WebExternalTextureMailbox available_mailbox; + static_assert(sizeof(sync_token) <= sizeof(available_mailbox.syncToken), + "Size of web external sync token too small."); memcpy(available_mailbox.name, mailbox.name, sizeof(available_mailbox.name)); - available_mailbox.syncPoint = sync_point; + memcpy(available_mailbox.syncToken, sync_token.GetConstData(), + sizeof(sync_token)); + available_mailbox.validSyncToken = sync_token.HasData(); if (bitmap) layer->free_bitmaps_.push_back(bitmap); layer->client_->mailboxReleased(available_mailbox, lost_resource);
diff --git a/cc/blink/web_external_texture_layer_impl.h b/cc/blink/web_external_texture_layer_impl.h index 5425ae53..8438a89 100644 --- a/cc/blink/web_external_texture_layer_impl.h +++ b/cc/blink/web_external_texture_layer_impl.h
@@ -56,7 +56,7 @@ base::WeakPtr<WebExternalTextureLayerImpl> layer, const blink::WebExternalTextureMailbox& mailbox, WebExternalBitmapImpl* bitmap, - unsigned sync_point, + const gpu::SyncToken& sync_token, bool lost_resource); WebExternalBitmapImpl* AllocateBitmap();
diff --git a/cc/layers/texture_layer.cc b/cc/layers/texture_layer.cc index c9fb61b..5ddc8b66 100644 --- a/cc/layers/texture_layer.cc +++ b/cc/layers/texture_layer.cc
@@ -154,7 +154,8 @@ mailbox, release_callback.Pass(), requires_commit, allow_mailbox_reuse); } -static void IgnoreReleaseCallback(uint32 sync_point, bool lost) {} +static void IgnoreReleaseCallback(const gpu::SyncToken& sync_token, bool lost) { +} void TextureLayer::SetTextureMailboxWithoutReleaseCallback( const TextureMailbox& mailbox) { @@ -163,7 +164,7 @@ // multiple times for the same mailbox. DCHECK(!mailbox.IsValid() || !holder_ref_ || !mailbox.Equals(holder_ref_->holder()->mailbox()) || - mailbox.sync_point() != holder_ref_->holder()->mailbox().sync_point()); + mailbox.sync_token() != holder_ref_->holder()->mailbox().sync_token()); scoped_ptr<SingleReleaseCallback> release; bool requires_commit = true; bool allow_mailbox_reuse = true; @@ -267,9 +268,8 @@ : internal_references_(0), mailbox_(mailbox), release_callback_(release_callback.Pass()), - sync_point_(mailbox.sync_point()), - is_lost_(false) { -} + sync_token_(mailbox.sync_token()), + is_lost_(false) {} TextureLayer::TextureMailboxHolder::~TextureMailboxHolder() { DCHECK_EQ(0u, internal_references_); @@ -283,10 +283,11 @@ new TextureMailboxHolder(mailbox, release_callback.Pass()))); } -void TextureLayer::TextureMailboxHolder::Return(uint32 sync_point, - bool is_lost) { +void TextureLayer::TextureMailboxHolder::Return( + const gpu::SyncToken& sync_token, + bool is_lost) { base::AutoLock lock(arguments_lock_); - sync_point_ = sync_point; + sync_token_ = sync_token; is_lost_ = is_lost; } @@ -307,17 +308,17 @@ void TextureLayer::TextureMailboxHolder::InternalRelease() { DCHECK(main_thread_checker_.CalledOnValidThread()); if (!--internal_references_) { - release_callback_->Run(sync_point_, is_lost_); + release_callback_->Run(sync_token_, is_lost_); mailbox_ = TextureMailbox(); release_callback_ = nullptr; } } void TextureLayer::TextureMailboxHolder::ReturnAndReleaseOnImplThread( - uint32 sync_point, + const gpu::SyncToken& sync_token, bool is_lost, BlockingTaskRunner* main_thread_task_runner) { - Return(sync_point, is_lost); + Return(sync_token, is_lost); main_thread_task_runner->PostTask( FROM_HERE, base::Bind(&TextureMailboxHolder::InternalRelease, this)); }
diff --git a/cc/layers/texture_layer.h b/cc/layers/texture_layer.h index 0c0b2ec..b1e9243 100644 --- a/cc/layers/texture_layer.h +++ b/cc/layers/texture_layer.h
@@ -14,6 +14,10 @@ #include "cc/layers/layer.h" #include "cc/resources/texture_mailbox.h" +namespace gpu { +struct SyncToken; +} + namespace cc { class BlockingTaskRunner; class SingleReleaseCallback; @@ -38,7 +42,7 @@ }; const TextureMailbox& mailbox() const { return mailbox_; } - void Return(uint32 sync_point, bool is_lost); + void Return(const gpu::SyncToken& sync_token, bool is_lost); // Gets a ReleaseCallback that can be called from another thread. Note: the // caller must ensure the callback is called. @@ -63,7 +67,7 @@ void InternalAddRef(); void InternalRelease(); void ReturnAndReleaseOnImplThread( - uint32 sync_point, + const gpu::SyncToken& sync_token, bool is_lost, BlockingTaskRunner* main_thread_task_runner); @@ -73,12 +77,12 @@ TextureMailbox mailbox_; scoped_ptr<SingleReleaseCallback> release_callback_; - // This lock guards the sync_point_ and is_lost_ fields because they can be + // This lock guards the sync_token_ and is_lost_ fields because they can be // accessed on both the impl and main thread. We do this to ensure that the // values of these fields are well-ordered such that the last call to // ReturnAndReleaseOnImplThread() defines their values. base::Lock arguments_lock_; - uint32 sync_point_; + gpu::SyncToken sync_token_; bool is_lost_; base::ThreadChecker main_thread_checker_; DISALLOW_COPY_AND_ASSIGN(TextureMailboxHolder);
diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc index 0cc5c9f..8433df2 100644 --- a/cc/layers/texture_layer_impl.cc +++ b/cc/layers/texture_layer_impl.cc
@@ -247,7 +247,7 @@ if (own_mailbox_) { DCHECK(!external_texture_resource_); if (release_callback_) { - release_callback_->Run(texture_mailbox_.sync_point(), false, + release_callback_->Run(texture_mailbox_.sync_token(), false, layer_tree_impl() ->task_runner_provider() ->blocking_main_thread_task_runner());
diff --git a/cc/layers/texture_layer_impl_unittest.cc b/cc/layers/texture_layer_impl_unittest.cc index 27efd97..fe2e006f 100644 --- a/cc/layers/texture_layer_impl_unittest.cc +++ b/cc/layers/texture_layer_impl_unittest.cc
@@ -12,10 +12,9 @@ namespace cc { namespace { -void IgnoreCallback(uint32 sync_point, +void IgnoreCallback(const gpu::SyncToken& sync_token, bool lost, - BlockingTaskRunner* main_thread_task_runner) { -} + BlockingTaskRunner* main_thread_task_runner) {} TEST(TextureLayerImplTest, VisibleOpaqueRegion) { const gfx::Size layer_bounds(100, 100); @@ -52,7 +51,7 @@ gpu::Mailbox mailbox; impl.output_surface()->context_provider()->ContextGL()->GenMailboxCHROMIUM( mailbox.name); - TextureMailbox texture_mailbox(mailbox, GL_TEXTURE_2D, 0); + TextureMailbox texture_mailbox(mailbox, gpu::SyncToken(), GL_TEXTURE_2D); TextureLayerImpl* texture_layer_impl = impl.AddChildToRoot<TextureLayerImpl>();
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc index 2af2df1..a04ff66 100644 --- a/cc/layers/texture_layer_unittest.cc +++ b/cc/layers/texture_layer_unittest.cc
@@ -115,20 +115,20 @@ public: MOCK_METHOD3(Release, void(const gpu::Mailbox& mailbox, - uint32 sync_point, + const gpu::SyncToken& sync_token, bool lost_resource)); MOCK_METHOD3(Release2, void(SharedBitmap* shared_bitmap, - uint32 sync_point, + const gpu::SyncToken& sync_token, bool lost_resource)); MOCK_METHOD4(ReleaseImpl, void(const gpu::Mailbox& mailbox, - uint32 sync_point, + const gpu::SyncToken& sync_token, bool lost_resource, BlockingTaskRunner* main_thread_task_runner)); MOCK_METHOD4(ReleaseImpl2, void(SharedBitmap* shared_bitmap, - uint32 sync_point, + const gpu::SyncToken& sync_token, bool lost_resource, BlockingTaskRunner* main_thread_task_runner)); }; @@ -137,8 +137,8 @@ explicit CommonMailboxObjects(SharedBitmapManager* manager) : mailbox_name1_(MailboxFromChar('1')), mailbox_name2_(MailboxFromChar('2')), - sync_point1_(1), - sync_point2_(2) { + sync_token1_(1), + sync_token2_(2) { release_mailbox1_ = base::Bind(&MockMailboxCallback::Release, base::Unretained(&mock_callback_), mailbox_name1_); @@ -153,8 +153,8 @@ mailbox_name2_); const uint32 arbitrary_target1 = GL_TEXTURE_2D; const uint32 arbitrary_target2 = GL_TEXTURE_EXTERNAL_OES; - mailbox1_ = TextureMailbox(mailbox_name1_, arbitrary_target1, sync_point1_); - mailbox2_ = TextureMailbox(mailbox_name2_, arbitrary_target2, sync_point2_); + mailbox1_ = TextureMailbox(mailbox_name1_, sync_token1_, arbitrary_target1); + mailbox2_ = TextureMailbox(mailbox_name2_, sync_token2_, arbitrary_target2); gfx::Size size(128, 128); shared_bitmap_ = manager->AllocateSharedBitmap(size); DCHECK(shared_bitmap_); @@ -179,8 +179,8 @@ TextureMailbox mailbox1_; TextureMailbox mailbox2_; TextureMailbox mailbox3_; - uint32 sync_point1_; - uint32 sync_point2_; + gpu::SyncToken sync_token1_; + gpu::SyncToken sync_token2_; scoped_ptr<SharedBitmap> shared_bitmap_; }; @@ -252,10 +252,10 @@ protected: void TearDown() override { Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); - EXPECT_CALL(test_data_.mock_callback_, - Release(test_data_.mailbox_name1_, - test_data_.sync_point1_, - false)).Times(1); + EXPECT_CALL( + test_data_.mock_callback_, + Release(test_data_.mailbox_name1_, test_data_.sync_token1_, false)) + .Times(1); TextureLayerTest::TearDown(); } }; @@ -276,10 +276,9 @@ Mock::VerifyAndClearExpectations(layer_tree_host_.get()); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); - EXPECT_CALL(test_data_.mock_callback_, - Release(test_data_.mailbox_name1_, - test_data_.sync_point1_, - false)) + EXPECT_CALL( + test_data_.mock_callback_, + Release(test_data_.mailbox_name1_, test_data_.sync_token1_, false)) .Times(1); test_layer->SetTextureMailbox( test_data_.mailbox2_, @@ -288,10 +287,9 @@ Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); - EXPECT_CALL(test_data_.mock_callback_, - Release(test_data_.mailbox_name2_, - test_data_.sync_point2_, - false)) + EXPECT_CALL( + test_data_.mock_callback_, + Release(test_data_.mailbox_name2_, test_data_.sync_token2_, false)) .Times(1); test_layer->SetTextureMailbox(TextureMailbox(), nullptr); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); @@ -306,7 +304,8 @@ EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); EXPECT_CALL(test_data_.mock_callback_, - Release2(test_data_.shared_bitmap_.get(), 0, false)).Times(1); + Release2(test_data_.shared_bitmap_.get(), _, false)) + .Times(1); test_layer->SetTextureMailbox(TextureMailbox(), nullptr); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); @@ -324,8 +323,10 @@ ASSERT_TRUE(test_layer.get()); // These use the same gpu::Mailbox, but different sync points. - TextureMailbox mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D, 1); - TextureMailbox mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D, 2); + TextureMailbox mailbox1(MailboxFromChar('a'), gpu::SyncToken(1), + GL_TEXTURE_2D); + TextureMailbox mailbox2(MailboxFromChar('a'), gpu::SyncToken(2), + GL_TEXTURE_2D); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); layer_tree_host_->SetRootLayer(test_layer); @@ -428,8 +429,8 @@ // The compositors both destroy their impl trees before the main thread layer // is destroyed. - compositor1->Run(100, false, main_thread_task_runner_.get()); - compositor2->Run(200, false, main_thread_task_runner_.get()); + compositor1->Run(gpu::SyncToken(100), false, main_thread_task_runner_.get()); + compositor2->Run(gpu::SyncToken(200), false, main_thread_task_runner_.get()); Wait(main_thread_); @@ -439,7 +440,8 @@ // The main thread ref is the last one, so the mailbox is released back to the // embedder, with the last sync point provided by the impl trees. EXPECT_CALL(test_data_.mock_callback_, - Release(test_data_.mailbox_name1_, 200, false)).Times(1); + Release(test_data_.mailbox_name1_, gpu::SyncToken(200), false)) + .Times(1); main_thread_.message_loop()->task_runner()->PostTask( FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef, @@ -477,7 +479,7 @@ Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); // One compositor destroys their impl tree. - compositor1->Run(100, false, main_thread_task_runner_.get()); + compositor1->Run(gpu::SyncToken(100), false, main_thread_task_runner_.get()); // Then the main thread reference is destroyed. main_thread_.message_loop()->task_runner()->PostTask( @@ -492,9 +494,10 @@ // The second impl reference is destroyed last, causing the mailbox to be // released back to the embedder with the last sync point from the impl tree. EXPECT_CALL(test_data_.mock_callback_, - Release(test_data_.mailbox_name1_, 200, true)).Times(1); + Release(test_data_.mailbox_name1_, gpu::SyncToken(200), true)) + .Times(1); - compositor2->Run(200, true, main_thread_task_runner_.get()); + compositor2->Run(gpu::SyncToken(200), true, main_thread_task_runner_.get()); Wait(main_thread_); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); } @@ -533,7 +536,7 @@ base::Unretained(this))); // One compositor destroys their impl tree. - compositor2->Run(200, false, main_thread_task_runner_.get()); + compositor2->Run(gpu::SyncToken(200), false, main_thread_task_runner_.get()); Wait(main_thread_); @@ -543,9 +546,10 @@ // The second impl reference is destroyed last, causing the mailbox to be // released back to the embedder with the last sync point from the impl tree. EXPECT_CALL(test_data_.mock_callback_, - Release(test_data_.mailbox_name1_, 100, true)).Times(1); + Release(test_data_.mailbox_name1_, gpu::SyncToken(100), true)) + .Times(1); - compositor1->Run(100, true, main_thread_task_runner_.get()); + compositor1->Run(gpu::SyncToken(100), true, main_thread_task_runner_.get()); Wait(main_thread_); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); } @@ -584,7 +588,8 @@ base::Unretained(this))); EXPECT_CALL(test_data_.mock_callback_, - Release(test_data_.mailbox_name1_, 200, true)).Times(1); + Release(test_data_.mailbox_name1_, gpu::SyncToken(200), true)) + .Times(1); bool manual_reset = false; bool initially_signaled = false; @@ -603,7 +608,7 @@ // Before the main thread capturing starts, one compositor destroys their // impl reference. Since capturing did not start, this gets post-tasked to // the main thread. - compositor1->Run(100, false, main_thread_task_runner_.get()); + compositor1->Run(gpu::SyncToken(100), false, main_thread_task_runner_.get()); // Start capturing on the main thread. begin_capture.Signal(); @@ -614,7 +619,7 @@ // released before compositor1, whose reference will be released later when // the post-task is serviced. But since it was destroyed _on the impl thread_ // last, its sync point values should be used. - compositor2->Run(200, true, main_thread_task_runner_.get()); + compositor2->Run(gpu::SyncToken(200), true, main_thread_task_runner_.get()); stop_capture.Signal(); Wait(main_thread_); @@ -629,7 +634,7 @@ commit_count_(0) {} // Make sure callback is received on main and doesn't block the impl thread. - void ReleaseCallback(uint32 sync_point, bool lost_resource) { + void ReleaseCallback(const gpu::SyncToken& sync_token, bool lost_resource) { EXPECT_EQ(true, main_thread_.CalledOnValidThread()); EXPECT_FALSE(lost_resource); ++callback_count_; @@ -641,9 +646,9 @@ base::Bind( &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback, base::Unretained(this))); - layer_->SetTextureMailbox( - TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0), - callback.Pass()); + layer_->SetTextureMailbox(TextureMailbox(MailboxFromChar(mailbox_char), + gpu::SyncToken(), GL_TEXTURE_2D), + callback.Pass()); } void BeginTest() override { @@ -750,15 +755,16 @@ protected: TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {} - static void ReleaseCallback(uint32 sync_point, bool lost_resource) {} + static void ReleaseCallback(const gpu::SyncToken& sync_token, + bool lost_resource) {} void SetMailbox(char mailbox_char) { scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( base::Bind( &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback)); - layer_->SetTextureMailbox( - TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0), - callback.Pass()); + layer_->SetTextureMailbox(TextureMailbox(MailboxFromChar(mailbox_char), + gpu::SyncToken(), GL_TEXTURE_2D), + callback.Pass()); } void BeginTest() override { @@ -857,10 +863,11 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) { EXPECT_CALL( test_data_.mock_callback_, - ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _)) + ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_token1_, false, _)) .Times(AnyNumber()); - EXPECT_CALL(test_data_.mock_callback_, - ReleaseImpl2(test_data_.shared_bitmap_.get(), 0, false, _)) + EXPECT_CALL( + test_data_.mock_callback_, + ReleaseImpl2(test_data_.shared_bitmap_.get(), gpu::SyncToken(), false, _)) .Times(AnyNumber()); // Hardware mode. { @@ -944,7 +951,7 @@ // Test multiple commits without an activation. EXPECT_CALL( test_data_.mock_callback_, - ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _)) + ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_token1_, false, _)) .Times(1); pending_layer->SetTextureMailbox( test_data_.mailbox2_, @@ -978,7 +985,7 @@ // Test destructor. EXPECT_CALL( test_data_.mock_callback_, - ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _)) + ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_token1_, false, _)) .Times(1); pending_layer->SetTextureMailbox( test_data_.mailbox1_, @@ -1043,14 +1050,15 @@ return true; } - *texture_mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0); + *texture_mailbox = + TextureMailbox(MailboxFromChar('1'), gpu::SyncToken(), GL_TEXTURE_2D); *release_callback = SingleReleaseCallback::Create( base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased, base::Unretained(this))); return true; } - void MailboxReleased(uint32 sync_point, bool lost_resource) { + void MailboxReleased(const gpu::SyncToken& sync_token, bool lost_resource) { // Source frame number during callback is the same as the source frame // on which it was released. EXPECT_EQ(1, layer_tree_host()->source_frame_number()); @@ -1145,10 +1153,11 @@ } TextureMailbox MakeMailbox(char name) { - return TextureMailbox(MailboxFromChar(name), GL_TEXTURE_2D, 0); + return TextureMailbox(MailboxFromChar(name), gpu::SyncToken(), + GL_TEXTURE_2D); } - void MailboxReleased(uint32 sync_point, bool lost_resource) { + void MailboxReleased(const gpu::SyncToken& sync_token, bool lost_resource) { ++mailbox_returned_; } @@ -1268,14 +1277,15 @@ TextureMailbox* mailbox, scoped_ptr<SingleReleaseCallback>* release_callback, bool use_shared_memory) override { - *mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0); + *mailbox = + TextureMailbox(MailboxFromChar('1'), gpu::SyncToken(), GL_TEXTURE_2D); *release_callback = SingleReleaseCallback::Create( base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased, base::Unretained(this))); return true; } - void MailboxReleased(unsigned sync_point, bool lost_resource) { + void MailboxReleased(const gpu::SyncToken& sync_token, bool lost_resource) { mailbox_released_ = true; } @@ -1327,7 +1337,7 @@ class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest { public: - void ReleaseCallback(uint32 sync_point, bool lost_resource) { + void ReleaseCallback(const gpu::SyncToken& sync_token, bool lost_resource) { EXPECT_EQ(true, main_thread_.CalledOnValidThread()); EXPECT_FALSE(lost_resource); ++callback_count_; @@ -1340,9 +1350,9 @@ base::Bind( &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback, base::Unretained(this))); - layer_->SetTextureMailbox( - TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0), - callback.Pass()); + layer_->SetTextureMailbox(TextureMailbox(MailboxFromChar(mailbox_char), + gpu::SyncToken(), GL_TEXTURE_2D), + callback.Pass()); } void SetupTree() override { @@ -1396,7 +1406,7 @@ class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest { public: - void ReleaseCallback(uint32 sync_point, bool lost_resource) { + void ReleaseCallback(const gpu::SyncToken& sync_token, bool lost_resource) { EXPECT_EQ(true, main_thread_.CalledOnValidThread()); EXPECT_FALSE(lost_resource); ++callback_count_; @@ -1409,9 +1419,9 @@ base::Bind( &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback, base::Unretained(this))); - layer_->SetTextureMailbox( - TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0), - callback.Pass()); + layer_->SetTextureMailbox(TextureMailbox(MailboxFromChar(mailbox_char), + gpu::SyncToken(), GL_TEXTURE_2D), + callback.Pass()); } void SetupTree() override {
diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc index 220a9da..24cf44e4 100644 --- a/cc/layers/video_layer_impl.cc +++ b/cc/layers/video_layer_impl.cc
@@ -363,7 +363,7 @@ if (frame_resource_type_ == VideoFrameExternalResources::SOFTWARE_RESOURCE) { for (size_t i = 0; i < software_resources_.size(); ++i) { - software_release_callback_.Run(0, false, + software_release_callback_.Run(gpu::SyncToken(), false, layer_tree_impl() ->task_runner_provider() ->blocking_main_thread_task_runner());
diff --git a/cc/layers/video_layer_impl_unittest.cc b/cc/layers/video_layer_impl_unittest.cc index f13af9b..6efe46d 100644 --- a/cc/layers/video_layer_impl_unittest.cc +++ b/cc/layers/video_layer_impl_unittest.cc
@@ -287,8 +287,7 @@ EXPECT_EQ(gfx::Point3F(0, 0, 0), p2); } -void EmptyCallback(unsigned sync_point) { -} +void EmptyCallback(const gpu::SyncToken& sync_token) {} TEST(VideoLayerImplTest, SoftwareVideoFrameGeneratesYUVQuad) { gfx::Size layer_size(1000, 1000);
diff --git a/cc/output/copy_output_result.cc b/cc/output/copy_output_result.cc index 8dee046..704aa9ab 100644 --- a/cc/output/copy_output_result.cc +++ b/cc/output/copy_output_result.cc
@@ -30,7 +30,7 @@ CopyOutputResult::~CopyOutputResult() { if (release_callback_) - release_callback_->Run(0, false); + release_callback_->Run(gpu::SyncToken(), false); } scoped_ptr<SkBitmap> CopyOutputResult::TakeBitmap() {
diff --git a/cc/output/gl_frame_data.cc b/cc/output/gl_frame_data.cc index aa6cfbc..ef72148 100644 --- a/cc/output/gl_frame_data.cc +++ b/cc/output/gl_frame_data.cc
@@ -6,7 +6,7 @@ namespace cc { -GLFrameData::GLFrameData() : sync_point(0) {} +GLFrameData::GLFrameData() {} GLFrameData::~GLFrameData() {}
diff --git a/cc/output/gl_frame_data.h b/cc/output/gl_frame_data.h index d633d74..df6227f0 100644 --- a/cc/output/gl_frame_data.h +++ b/cc/output/gl_frame_data.h
@@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "cc/base/cc_export.h" #include "gpu/command_buffer/common/mailbox.h" +#include "gpu/command_buffer/common/sync_token.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" @@ -21,7 +22,7 @@ ~GLFrameData(); gpu::Mailbox mailbox; - uint32 sync_point; + gpu::SyncToken sync_token; gfx::Size size; gfx::Rect sub_buffer_rect; };
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc index 1d56429..8d28b2c 100644 --- a/cc/output/gl_renderer.cc +++ b/cc/output/gl_renderer.cc
@@ -488,13 +488,13 @@ } resource_provider_->SetReadLockFence(read_lock_fence.get()); - // Insert WaitSyncPointCHROMIUM on quad resources prior to drawing the frame, + // Insert WaitSyncTokenCHROMIUM on quad resources prior to drawing the frame, // so that drawing can proceed without GL context switching interruptions. ResourceProvider* resource_provider = resource_provider_; for (const auto& pass : *frame->render_passes_in_draw_order) { for (const auto& quad : pass->quad_list) { for (ResourceId resource_id : quad->resources) - resource_provider->WaitSyncPointIfNeeded(resource_id); + resource_provider->WaitSyncTokenIfNeeded(resource_id); } } @@ -2701,17 +2701,18 @@ DCHECK_EQ(static_cast<unsigned>(GL_TEXTURE_2D), request->texture_mailbox().target()); DCHECK(!mailbox.IsZero()); - unsigned incoming_sync_point = request->texture_mailbox().sync_point(); - if (incoming_sync_point) - gl_->WaitSyncPointCHROMIUM(incoming_sync_point); + const gpu::SyncToken& incoming_sync_token = + request->texture_mailbox().sync_token(); + if (incoming_sync_token.HasData()) + gl_->WaitSyncTokenCHROMIUM(incoming_sync_token.GetConstData()); texture_id = gl_->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); } GetFramebufferTexture(texture_id, RGBA_8888, window_rect); - unsigned sync_point = gl_->InsertSyncPointCHROMIUM(); - TextureMailbox texture_mailbox(mailbox, GL_TEXTURE_2D, sync_point); + gpu::SyncToken sync_token(gl_->InsertSyncPointCHROMIUM()); + TextureMailbox texture_mailbox(mailbox, sync_token, GL_TEXTURE_2D); scoped_ptr<SingleReleaseCallback> release_callback; if (own_mailbox) {
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc index 6d80d812..6af531c 100644 --- a/cc/output/gl_renderer_unittest.cc +++ b/cc/output/gl_renderer_unittest.cc
@@ -51,6 +51,12 @@ namespace cc { +MATCHER_P(MatchesSyncToken, sync_token, "") { + gpu::SyncToken other; + memcpy(&other, arg, sizeof(other)); + return other == sync_token; +} + class GLRendererTest : public testing::Test { protected: RenderPass* root_render_pass() { return render_passes_in_draw_order_.back(); } @@ -929,7 +935,7 @@ test_capabilities_.gpu.egl_image_external = true; } - MOCK_METHOD1(waitSyncPoint, void(unsigned sync_point)); + MOCK_METHOD1(waitSyncToken, void(const GLbyte* sync_token)); MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param)); MOCK_METHOD4(drawElements, void(GLenum mode, GLsizei count, GLenum type, GLintptr offset)); @@ -973,7 +979,7 @@ RenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_, RenderPassId(1, 1), gfx::Rect(100, 100), gfx::Transform()); - uint32_t mailbox_sync_point; + unsigned mailbox_sync_point; AddOneOfEveryQuadType(root_pass, resource_provider.get(), RenderPassId(0, 0), &mailbox_sync_point); @@ -987,7 +993,9 @@ // The sync points for all quads are waited on first. This sync point is // for a texture quad drawn later in the frame. - EXPECT_CALL(*context, waitSyncPoint(mailbox_sync_point)).Times(1); + gpu::SyncToken mailbox_sync_token(mailbox_sync_point); + EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(mailbox_sync_token))) + .Times(1); // yuv_quad is drawn with the default linear filter. EXPECT_CALL(*context, drawElements(_, _, _, _)); @@ -2023,10 +2031,9 @@ Strategy* strategy_; }; -void MailboxReleased(unsigned sync_point, +void MailboxReleased(const gpu::SyncToken& sync_token, bool lost_resource, - BlockingTaskRunner* main_thread_task_runner) { -} + BlockingTaskRunner* main_thread_task_runner) {} void IgnoreCopyResult(scoped_ptr<CopyOutputResult> result) { } @@ -2063,9 +2070,8 @@ root_pass->copy_requests.push_back( CopyOutputRequest::CreateRequest(base::Bind(&IgnoreCopyResult))); - unsigned sync_point = 0; TextureMailbox mailbox = - TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point, + TextureMailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), GL_TEXTURE_2D, gfx::Size(256, 256), true); scoped_ptr<SingleReleaseCallbackImpl> release_callback = SingleReleaseCallbackImpl::Create(base::Bind(&MailboxReleased)); @@ -2139,9 +2145,9 @@ SingleOverlayValidator validator_; }; -class WaitSyncPointCountingContext : public TestWebGraphicsContext3D { +class WaitSyncTokenCountingContext : public TestWebGraphicsContext3D { public: - MOCK_METHOD1(waitSyncPoint, void(unsigned sync_point)); + MOCK_METHOD1(waitSyncToken, void(const GLbyte* sync_token)); }; class MockOverlayScheduler { @@ -2154,10 +2160,10 @@ const gfx::RectF& uv_rect)); }; -TEST_F(GLRendererTest, OverlaySyncPointsAreProcessed) { - scoped_ptr<WaitSyncPointCountingContext> context_owned( - new WaitSyncPointCountingContext); - WaitSyncPointCountingContext* context = context_owned.get(); +TEST_F(GLRendererTest, OverlaySyncTokensAreProcessed) { + scoped_ptr<WaitSyncTokenCountingContext> context_owned( + new WaitSyncTokenCountingContext); + WaitSyncTokenCountingContext* context = context_owned.get(); MockOverlayScheduler overlay_scheduler; scoped_refptr<TestContextProvider> context_provider = @@ -2193,9 +2199,9 @@ viewport_rect, gfx::Transform()); root_pass->has_transparent_background = false; - unsigned sync_point = 29; + gpu::SyncToken sync_token(29); TextureMailbox mailbox = - TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point, + TextureMailbox(gpu::Mailbox::Generate(), sync_token, GL_TEXTURE_2D, gfx::Size(256, 256), true); scoped_ptr<SingleReleaseCallbackImpl> release_callback = SingleReleaseCallbackImpl::Create(base::Bind(&MailboxReleased)); @@ -2220,7 +2226,7 @@ // Verify that overlay_quad actually gets turned into an overlay, and even // though it's not drawn, that its sync point is waited on. - EXPECT_CALL(*context, waitSyncPoint(sync_point)).Times(1); + EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(sync_token))).Times(1); EXPECT_CALL(overlay_scheduler, Schedule(1, gfx::OVERLAY_TRANSFORM_NONE, _, viewport_rect, BoundingRect(uv_top_left, uv_bottom_right))).Times(1);
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc index 722002e..824b7fe 100644 --- a/cc/output/overlay_unittest.cc +++ b/cc/output/overlay_unittest.cc
@@ -53,10 +53,9 @@ const gfx::Transform kSwapTransform = gfx::Transform(0, 1, 1, 0, 0, 0); // x,y -> y,x. -void MailboxReleased(unsigned sync_point, +void MailboxReleased(const gpu::SyncToken& sync_token, bool lost_resource, - BlockingTaskRunner* main_thread_task_runner) { -} + BlockingTaskRunner* main_thread_task_runner) {} class SingleOverlayValidator : public OverlayCandidateValidator { public: @@ -206,10 +205,9 @@ ResourceId CreateResource(ResourceProvider* resource_provider, const gfx::Size& size, bool is_overlay_candidate) { - unsigned sync_point = 0; TextureMailbox mailbox = - TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point, size, - is_overlay_candidate); + TextureMailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), GL_TEXTURE_2D, + size, is_overlay_candidate); scoped_ptr<SingleReleaseCallbackImpl> release_callback = SingleReleaseCallbackImpl::Create(base::Bind(&MailboxReleased));
diff --git a/cc/output/renderer_settings.cc b/cc/output/renderer_settings.cc index db961c91..dce7e24d 100644 --- a/cc/output/renderer_settings.cc +++ b/cc/output/renderer_settings.cc
@@ -21,7 +21,8 @@ refresh_rate(60.0), highp_threshold_min(0), use_rgba_4444_textures(false), - texture_id_allocation_chunk_size(64) {} + texture_id_allocation_chunk_size(64), + use_gpu_memory_buffer_resources(false) {} RendererSettings::~RendererSettings() { }
diff --git a/cc/output/renderer_settings.h b/cc/output/renderer_settings.h index ce0a470..8022800 100644 --- a/cc/output/renderer_settings.h +++ b/cc/output/renderer_settings.h
@@ -26,6 +26,7 @@ int highp_threshold_min; bool use_rgba_4444_textures; size_t texture_id_allocation_chunk_size; + bool use_gpu_memory_buffer_resources; }; } // namespace cc
diff --git a/cc/output/texture_mailbox_deleter.cc b/cc/output/texture_mailbox_deleter.cc index 7729c4ec..642495f 100644 --- a/cc/output/texture_mailbox_deleter.cc +++ b/cc/output/texture_mailbox_deleter.cc
@@ -11,27 +11,30 @@ #include "cc/output/context_provider.h" #include "cc/resources/single_release_callback.h" #include "gpu/command_buffer/client/gles2_interface.h" +#include "gpu/command_buffer/common/sync_token.h" namespace cc { static void DeleteTextureOnImplThread( const scoped_refptr<ContextProvider>& context_provider, unsigned texture_id, - uint32 sync_point, + const gpu::SyncToken& sync_token, bool is_lost) { - if (sync_point) - context_provider->ContextGL()->WaitSyncPointCHROMIUM(sync_point); + if (sync_token.HasData()) { + context_provider->ContextGL()->WaitSyncTokenCHROMIUM( + sync_token.GetConstData()); + } context_provider->ContextGL()->DeleteTextures(1, &texture_id); } static void PostTaskFromMainToImplThread( scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner, ReleaseCallback run_impl_callback, - unsigned sync_point, + const gpu::SyncToken& sync_token, bool is_lost) { // This posts the task to RunDeleteTextureOnImplThread(). impl_task_runner->PostTask( - FROM_HERE, base::Bind(run_impl_callback, sync_point, is_lost)); + FROM_HERE, base::Bind(run_impl_callback, sync_token, is_lost)); } TextureMailboxDeleter::TextureMailboxDeleter( @@ -40,7 +43,7 @@ TextureMailboxDeleter::~TextureMailboxDeleter() { for (size_t i = 0; i < impl_callbacks_.size(); ++i) - impl_callbacks_.at(i)->Run(0, true); + impl_callbacks_.at(i)->Run(gpu::SyncToken(), true); } scoped_ptr<SingleReleaseCallback> TextureMailboxDeleter::GetReleaseCallback( @@ -78,12 +81,12 @@ void TextureMailboxDeleter::RunDeleteTextureOnImplThread( SingleReleaseCallback* impl_callback, - unsigned sync_point, + const gpu::SyncToken& sync_token, bool is_lost) { for (size_t i = 0; i < impl_callbacks_.size(); ++i) { if (impl_callbacks_.at(i) == impl_callback) { // Run the callback, then destroy it here on the impl thread. - impl_callbacks_.at(i)->Run(sync_point, is_lost); + impl_callbacks_.at(i)->Run(sync_token, is_lost); impl_callbacks_.erase(impl_callbacks_.begin() + i); return; }
diff --git a/cc/output/texture_mailbox_deleter.h b/cc/output/texture_mailbox_deleter.h index 19760ea..c065c04 100644 --- a/cc/output/texture_mailbox_deleter.h +++ b/cc/output/texture_mailbox_deleter.h
@@ -13,6 +13,10 @@ class SingleThreadTaskRunner; } +namespace gpu { +struct SyncToken; +} + namespace cc { class ContextProvider; class SingleReleaseCallback; @@ -40,7 +44,7 @@ // Runs the |impl_callback| to delete the texture and removes the callback // from the |impl_callbacks_| list. void RunDeleteTextureOnImplThread(SingleReleaseCallback* impl_callback, - uint32 sync_point, + const gpu::SyncToken& sync_token, bool is_lost); scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner_;
diff --git a/cc/output/texture_mailbox_deleter_unittest.cc b/cc/output/texture_mailbox_deleter_unittest.cc index 37b9712..84e7d46 100644 --- a/cc/output/texture_mailbox_deleter_unittest.cc +++ b/cc/output/texture_mailbox_deleter_unittest.cc
@@ -41,7 +41,7 @@ // Run the scoped release callback before destroying it, but it won't do // anything. - cb->Run(0, false); + cb->Run(gpu::SyncToken(), false); } TEST(TextureMailboxDeleterTest, NullTaskRunner) { @@ -62,7 +62,7 @@ EXPECT_FALSE(context_provider->HasOneRef()); EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures()); - cb->Run(0, false); + cb->Run(gpu::SyncToken(), false); // With no task runner the callback will immediately drops its ref on the // ContextProvider and delete the texture.
diff --git a/cc/playback/display_list_recording_source.cc b/cc/playback/display_list_recording_source.cc index a199866..3a30cf9 100644 --- a/cc/playback/display_list_recording_source.cc +++ b/cc/playback/display_list_recording_source.cc
@@ -148,13 +148,8 @@ // Count the area that is being invalidated. Region recorded_invalidation(*invalidation); recorded_invalidation.Intersect(recorded_viewport_); - for (Region::Iterator it(recorded_invalidation); it.has_rect(); it.next()) { - // gfx::Size::GetArea might overflow in this case, so use an explicit - // CheckedNumeric instead. - base::CheckedNumeric<int> checked_area = it.rect().size().width(); - checked_area *= it.rect().size().height(); - timer.AddArea(checked_area); - } + for (Region::Iterator it(recorded_invalidation); it.has_rect(); it.next()) + timer.AddArea(it.rect().size().GetCheckedArea()); if (!updated && !invalidation->Intersects(recorded_viewport_)) return false;
diff --git a/cc/resources/release_callback.h b/cc/resources/release_callback.h index b471381..1a7245c 100644 --- a/cc/resources/release_callback.h +++ b/cc/resources/release_callback.h
@@ -7,9 +7,14 @@ #include "base/callback.h" +namespace gpu { +struct SyncToken; +} // namespace gpu + namespace cc { -typedef base::Callback<void(uint32 sync_point, bool is_lost)> ReleaseCallback; +typedef base::Callback<void(const gpu::SyncToken& sync_token, bool is_lost)> + ReleaseCallback; } // namespace cc
diff --git a/cc/resources/release_callback_impl.h b/cc/resources/release_callback_impl.h index 89f22b6..c5dffb5 100644 --- a/cc/resources/release_callback_impl.h +++ b/cc/resources/release_callback_impl.h
@@ -7,10 +7,14 @@ #include "base/callback.h" +namespace gpu { +struct SyncToken; +} + namespace cc { class BlockingTaskRunner; -typedef base::Callback<void(uint32 sync_point, +typedef base::Callback<void(const gpu::SyncToken& sync_token, bool is_lost, BlockingTaskRunner* main_thread_task_runner)> ReleaseCallbackImpl;
diff --git a/cc/resources/resource_pool.cc b/cc/resources/resource_pool.cc index 57db90ed..28ab249 100644 --- a/cc/resources/resource_pool.cc +++ b/cc/resources/resource_pool.cc
@@ -79,7 +79,7 @@ DCHECK_EQ(0u, in_use_resources_.size()); while (!busy_resources_.empty()) { - DidFinishUsingResource(busy_resources_.take_front()); + DidFinishUsingResource(busy_resources_.take_back()); } SetResourceUsageLimits(0, 0); @@ -91,6 +91,9 @@ Resource* ResourcePool::AcquireResource(const gfx::Size& size, ResourceFormat format) { + // Finding resources in |unused_resources_| from MRU to LRU direction, touches + // LRU resources only if needed, which increases possibility of expiring more + // LRU resources within kResourceExpirationDelayMs. for (ResourceDeque::iterator it = unused_resources_.begin(); it != unused_resources_.end(); ++it) { ScopedResource* resource = *it; @@ -160,7 +163,7 @@ pool_resource->set_last_usage(base::TimeTicks::Now()); // Transfer resource to |busy_resources_|. - busy_resources_.push_back(in_use_resources_.take_and_erase(it)); + busy_resources_.push_front(in_use_resources_.take_and_erase(it)); in_use_memory_usage_bytes_ -= ResourceUtil::UncheckedSizeInBytes<size_t>( pool_resource->size(), pool_resource->format()); @@ -189,7 +192,7 @@ // can't be locked for write might also not be truly free-able. // We can free the resource here but it doesn't mean that the // memory is necessarily returned to the OS. - DeleteResource(unused_resources_.take_front()); + DeleteResource(unused_resources_.take_back()); } } @@ -225,7 +228,7 @@ } void ResourcePool::DidFinishUsingResource(scoped_ptr<PoolResource> resource) { - unused_resources_.push_back(resource.Pass()); + unused_resources_.push_front(resource.Pass()); } void ResourcePool::ScheduleEvictExpiredResourcesIn( @@ -264,10 +267,10 @@ // as this may not exactly line up with the time a resource became non-busy. // However, this should be roughly ordered, and will only introduce slight // delays in freeing expired resources. - if (unused_resources_.front()->last_usage() > time_limit) + if (unused_resources_.back()->last_usage() > time_limit) return; - DeleteResource(unused_resources_.take_front()); + DeleteResource(unused_resources_.take_back()); } // Also free busy resources older than the delay. With a sufficiently large @@ -275,21 +278,21 @@ // expired are not likely to be busy. Additionally, freeing a "busy" resource // has no downside other than incorrect accounting. while (!busy_resources_.empty()) { - if (busy_resources_.front()->last_usage() > time_limit) + if (busy_resources_.back()->last_usage() > time_limit) return; - DeleteResource(busy_resources_.take_front()); + DeleteResource(busy_resources_.take_back()); } } base::TimeTicks ResourcePool::GetUsageTimeForLRUResource() const { if (!unused_resources_.empty()) { - return unused_resources_.front()->last_usage(); + return unused_resources_.back()->last_usage(); } // This is only called when we have at least one evictable resource. DCHECK(!busy_resources_.empty()); - return busy_resources_.front()->last_usage(); + return busy_resources_.back()->last_usage(); } bool ResourcePool::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
diff --git a/cc/resources/resource_pool.h b/cc/resources/resource_pool.h index b926c41..ef99d26 100644 --- a/cc/resources/resource_pool.h +++ b/cc/resources/resource_pool.h
@@ -116,6 +116,7 @@ size_t total_memory_usage_bytes_; size_t total_resource_count_; + // Holds most recently used resources at the front of the queue. using ResourceDeque = ScopedPtrDeque<PoolResource>; ResourceDeque unused_resources_; ResourceDeque busy_resources_;
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc index 2f5b0a9d..9ea7b6dd 100644 --- a/cc/resources/resource_provider.cc +++ b/cc/resources/resource_provider.cc
@@ -312,8 +312,7 @@ gpu_memory_buffer(NULL) {} ResourceProvider::Child::Child() - : marked_for_deletion(false), needs_sync_points(true) { -} + : marked_for_deletion(false), needs_sync_tokens(true) {} ResourceProvider::Child::~Child() {} @@ -324,11 +323,13 @@ BlockingTaskRunner* blocking_main_thread_task_runner, int highp_threshold_min, size_t id_allocation_chunk_size, + bool use_gpu_memory_buffer_resources, const std::vector<unsigned>& use_image_texture_targets) { scoped_ptr<ResourceProvider> resource_provider(new ResourceProvider( output_surface, shared_bitmap_manager, gpu_memory_buffer_manager, blocking_main_thread_task_runner, highp_threshold_min, - id_allocation_chunk_size, use_image_texture_targets)); + id_allocation_chunk_size, use_gpu_memory_buffer_resources, + use_image_texture_targets)); resource_provider->Initialize(); return resource_provider; } @@ -386,10 +387,10 @@ DCHECK(!size.IsEmpty()); switch (default_resource_type_) { case RESOURCE_TYPE_GL_TEXTURE: - return CreateGLTexture(size, - GL_TEXTURE_2D, - hint, - format); + return CreateGLTexture(size, use_gpu_memory_buffer_resources_ + ? GetImageTextureTarget(format) + : GL_TEXTURE_2D, + hint, format); case RESOURCE_TYPE_BITMAP: DCHECK_EQ(RGBA_8888, format); return CreateBitmap(size); @@ -562,7 +563,7 @@ } if (resource->origin == Resource::EXTERNAL) { DCHECK(resource->mailbox.IsValid()); - GLuint sync_point = resource->mailbox.sync_point(); + gpu::SyncToken sync_token = resource->mailbox.sync_token(); if (resource->type == RESOURCE_TYPE_GL_TEXTURE) { DCHECK(resource->mailbox.IsTexture()); lost_resource |= lost_output_surface_; @@ -572,15 +573,15 @@ gl->DeleteTextures(1, &resource->gl_id); resource->gl_id = 0; if (!lost_resource) - sync_point = gl->InsertSyncPointCHROMIUM(); + sync_token = gpu::SyncToken(gl->InsertSyncPointCHROMIUM()); } } else { DCHECK(resource->mailbox.IsSharedMemory()); resource->shared_bitmap = nullptr; resource->pixels = nullptr; } - resource->release_callback_impl.Run( - sync_point, lost_resource, blocking_main_thread_task_runner_); + resource->release_callback_impl.Run(sync_token, lost_resource, + blocking_main_thread_task_runner_); } if (resource->gl_id) { GLES2Interface* gl = ContextGL(); @@ -687,9 +688,9 @@ DCHECK(resource->origin != Resource::INTERNAL); DCHECK(resource->mailbox.IsTexture()); - // Mailbox sync_points must be processed by a call to - // WaitSyncPointIfNeeded() prior to calling LockForRead(). - DCHECK(!resource->mailbox.sync_point()); + // Mailbox sync_tokens must be processed by a call to + // WaitSyncTokenIfNeeded() prior to calling LockForRead(). + DCHECK(!resource->mailbox.sync_token().HasData()); GLES2Interface* gl = ContextGL(); DCHECK(gl); @@ -816,6 +817,8 @@ resource_provider_->LazyAllocate(resource_); texture_id_ = resource_->gl_id; DCHECK(texture_id_); + if (resource_->dirty_image) + resource_provider_->BindImageForSampling(resource_); } ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() { @@ -860,13 +863,10 @@ ScopedWriteLockGpuMemoryBuffer(ResourceProvider* resource_provider, ResourceId resource_id) : resource_provider_(resource_provider), - resource_(resource_provider->LockForWrite(resource_id)), - gpu_memory_buffer_manager_(resource_provider->gpu_memory_buffer_manager_), - gpu_memory_buffer_(nullptr), - size_(resource_->size), - format_(resource_->format) { + resource_(resource_provider->LockForWrite(resource_id)) { DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource_->type); - std::swap(gpu_memory_buffer_, resource_->gpu_memory_buffer); + gpu_memory_buffer_.reset(resource_->gpu_memory_buffer); + resource_->gpu_memory_buffer = nullptr; } ResourceProvider::ScopedWriteLockGpuMemoryBuffer:: @@ -876,27 +876,13 @@ if (!gpu_memory_buffer_) return; + DCHECK(!resource_->gpu_memory_buffer); resource_provider_->LazyCreate(resource_); - - if (!resource_->image_id) { - GLES2Interface* gl = resource_provider_->ContextGL(); - DCHECK(gl); - -#if defined(OS_CHROMEOS) - // TODO(reveman): GL_COMMANDS_ISSUED_CHROMIUM is used for synchronization - // on ChromeOS to avoid some performance issues. This only works with - // shared memory backed buffers. crbug.com/436314 - DCHECK_EQ(gpu_memory_buffer_->GetHandle().type, gfx::SHARED_MEMORY_BUFFER); -#endif - - resource_->image_id = gl->CreateImageCHROMIUM( - gpu_memory_buffer_->AsClientBuffer(), size_.width(), size_.height(), - GLInternalFormat(resource_->format)); - } - - std::swap(resource_->gpu_memory_buffer, gpu_memory_buffer_); + resource_->gpu_memory_buffer = gpu_memory_buffer_.release(); resource_->allocated = true; + resource_provider_->LazyCreateImage(resource_); resource_->dirty_image = true; + resource_->is_overlay_candidate = true; // GpuMemoryBuffer provides direct access to the memory used by the GPU. // Read lock fences are required to ensure that we're not trying to map a @@ -906,14 +892,13 @@ gfx::GpuMemoryBuffer* ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() { - if (gpu_memory_buffer_) - return gpu_memory_buffer_; - scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer = - gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer( - size_, BufferFormat(format_), - gfx::BufferUsage::GPU_READ_CPU_READ_WRITE); - gpu_memory_buffer_ = gpu_memory_buffer.release(); - return gpu_memory_buffer_; + if (!gpu_memory_buffer_) { + gpu_memory_buffer_ = + resource_provider_->gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer( + resource_->size, BufferFormat(resource_->format), + gfx::BufferUsage::GPU_READ_CPU_READ_WRITE); + } + return gpu_memory_buffer_.get(); } ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr( @@ -1002,6 +987,7 @@ BlockingTaskRunner* blocking_main_thread_task_runner, int highp_threshold_min, size_t id_allocation_chunk_size, + bool use_gpu_memory_buffer_resources, const std::vector<unsigned>& use_image_texture_targets) : output_surface_(output_surface), shared_bitmap_manager_(shared_bitmap_manager), @@ -1012,6 +998,7 @@ next_id_(1), next_child_(1), default_resource_type_(RESOURCE_TYPE_BITMAP), + use_gpu_memory_buffer_resources_(use_gpu_memory_buffer_resources), use_texture_storage_ext_(false), use_texture_format_bgra_(false), use_texture_usage_hint_(false), @@ -1087,10 +1074,10 @@ return child; } -void ResourceProvider::SetChildNeedsSyncPoints(int child_id, bool needs) { +void ResourceProvider::SetChildNeedsSyncTokens(int child_id, bool needs) { ChildMap::iterator it = children_.find(child_id); DCHECK(it != children_.end()); - it->second.needs_sync_points = needs; + it->second.needs_sync_tokens = needs; } void ResourceProvider::DestroyChild(int child_id) { @@ -1133,25 +1120,25 @@ TransferableResourceArray* list) { DCHECK(thread_checker_.CalledOnValidThread()); GLES2Interface* gl = ContextGL(); - bool need_sync_point = false; + bool need_sync_token = false; for (ResourceIdArray::const_iterator it = resources.begin(); it != resources.end(); ++it) { TransferableResource resource; TransferResource(gl, *it, &resource); - if (!resource.mailbox_holder.sync_point && !resource.is_software) - need_sync_point = true; + need_sync_token |= (!resource.mailbox_holder.sync_token.HasData() && + !resource.is_software); ++resources_.find(*it)->second.exported_count; list->push_back(resource); } - if (need_sync_point && + if (need_sync_token && output_surface_->capabilities().delegated_sync_points_required) { - GLuint sync_point = gl->InsertSyncPointCHROMIUM(); + gpu::SyncToken sync_token(gl->InsertSyncPointCHROMIUM()); for (TransferableResourceArray::iterator it = list->begin(); it != list->end(); ++it) { - if (!it->mailbox_holder.sync_point) - it->mailbox_holder.sync_point = sync_point; + if (!it->mailbox_holder.sync_token.HasData()) + it->mailbox_holder.sync_token = sync_token; } } } @@ -1196,8 +1183,8 @@ it->mailbox_holder.texture_target, it->filter, TEXTURE_HINT_IMMUTABLE, it->format)); resource->mailbox = TextureMailbox(it->mailbox_holder.mailbox, - it->mailbox_holder.texture_target, - it->mailbox_holder.sync_point); + it->mailbox_holder.sync_token, + it->mailbox_holder.texture_target); resource->read_lock_fences_enabled = it->read_lock_fences_enabled; resource->is_overlay_candidate = it->is_overlay_candidate; } @@ -1255,14 +1242,14 @@ if (resource->exported_count) continue; - if (returned.sync_point) { + if (returned.sync_token.HasData()) { DCHECK(!resource->has_shared_bitmap_id); if (resource->origin == Resource::INTERNAL) { DCHECK(resource->gl_id); - gl->WaitSyncPointCHROMIUM(returned.sync_point); + gl->WaitSyncTokenCHROMIUM(returned.sync_token.GetConstData()); } else { DCHECK(!resource->gl_id); - resource->mailbox.set_sync_point(returned.sync_point); + resource->mailbox.set_sync_token(returned.sync_token); } } @@ -1309,11 +1296,8 @@ LazyCreate(source); DCHECK(source->gl_id); DCHECK(source->origin == Resource::INTERNAL); - if (source->image_id) { - DCHECK(source->dirty_image); - gl->BindTexture(resource->mailbox_holder.texture_target, source->gl_id); + if (source->image_id && source->dirty_image) BindImageForSampling(source); - } // This is a resource allocated by the compositor, we need to produce it. // Don't set a sync point, the caller will do it. gl->GenMailboxCHROMIUM(resource->mailbox_holder.mailbox.name); @@ -1327,15 +1311,14 @@ if (source->image_id && source->dirty_image) { DCHECK(source->gl_id); DCHECK(source->origin == Resource::INTERNAL); - gl->BindTexture(resource->mailbox_holder.texture_target, source->gl_id); BindImageForSampling(source); } // This is either an external resource, or a compositor resource that we // already exported. Make sure to forward the sync point that we were given. resource->mailbox_holder.mailbox = source->mailbox.mailbox(); resource->mailbox_holder.texture_target = source->mailbox.target(); - resource->mailbox_holder.sync_point = source->mailbox.sync_point(); - source->mailbox.set_sync_point(0); + resource->mailbox_holder.sync_token = source->mailbox.sync_token(); + source->mailbox.set_sync_token(gpu::SyncToken()); } } @@ -1353,7 +1336,7 @@ ReturnedResourceArray to_return; GLES2Interface* gl = ContextGL(); - bool need_sync_point = false; + bool need_sync_token = false; for (size_t i = 0; i < unused.size(); ++i) { ResourceId local_id = unused[i]; @@ -1403,9 +1386,9 @@ ReturnedResource returned; returned.id = child_id; - returned.sync_point = resource.mailbox.sync_point(); - if (!returned.sync_point && resource.type == RESOURCE_TYPE_GL_TEXTURE) - need_sync_point = true; + returned.sync_token = resource.mailbox.sync_token(); + need_sync_token |= (!returned.sync_token.HasData() && + resource.type == RESOURCE_TYPE_GL_TEXTURE); returned.count = resource.imported_count; returned.lost = is_lost; to_return.push_back(returned); @@ -1415,12 +1398,12 @@ resource.imported_count = 0; DeleteResourceInternal(it, style); } - if (need_sync_point && child_info->needs_sync_points) { + if (need_sync_token && child_info->needs_sync_tokens) { DCHECK(gl); - GLuint sync_point = gl->InsertSyncPointCHROMIUM(); + gpu::SyncToken sync_token(gl->InsertSyncPointCHROMIUM()); for (size_t i = 0; i < to_return.size(); ++i) { - if (!to_return[i].sync_point) - to_return[i].sync_point = sync_point; + if (!to_return[i].sync_token.HasData()) + to_return[i].sync_token = sync_token; } } @@ -1515,9 +1498,18 @@ gfx::Size& size = resource->size; ResourceFormat format = resource->format; gl->BindTexture(resource->target, resource->gl_id); - if (use_texture_storage_ext_ && - IsFormatSupportedForStorage(format, use_texture_format_bgra_) && - (resource->hint & TEXTURE_HINT_IMMUTABLE)) { + if (use_gpu_memory_buffer_resources_) { + resource->gpu_memory_buffer = + gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer( + size, BufferFormat(format), + gfx::BufferUsage::SCANOUT) + .release(); + LazyCreateImage(resource); + resource->dirty_image = true; + resource->is_overlay_candidate = true; + } else if (use_texture_storage_ext_ && + IsFormatSupportedForStorage(format, use_texture_format_bgra_) && + (resource->hint & TEXTURE_HINT_IMMUTABLE)) { GLenum storage_format = TextureToStorageFormat(format); gl->TexStorage2DEXT(resource->target, 1, storage_format, size.width(), size.height()); @@ -1531,12 +1523,34 @@ } } +void ResourceProvider::LazyCreateImage(Resource* resource) { + DCHECK(resource->gpu_memory_buffer); + DCHECK(resource->gl_id); + DCHECK(resource->allocated); + if (!resource->image_id) { + GLES2Interface* gl = ContextGL(); + DCHECK(gl); + +#if defined(OS_CHROMEOS) + // TODO(reveman): GL_COMMANDS_ISSUED_CHROMIUM is used for synchronization + // on ChromeOS to avoid some performance issues. This only works with + // shared memory backed buffers. crbug.com/436314 + DCHECK_EQ(resource->gpu_memory_buffer->GetHandle().type, + gfx::SHARED_MEMORY_BUFFER); +#endif + resource->image_id = gl->CreateImageCHROMIUM( + resource->gpu_memory_buffer->AsClientBuffer(), resource->size.width(), + resource->size.height(), GLInternalFormat(resource->format)); + } +} + void ResourceProvider::BindImageForSampling(Resource* resource) { GLES2Interface* gl = ContextGL(); DCHECK(resource->gl_id); DCHECK(resource->image_id); // Release image currently bound to texture. + gl->BindTexture(resource->target, resource->gl_id); if (resource->bound_image_id) gl->ReleaseTexImage2DCHROMIUM(resource->target, resource->bound_image_id); gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id); @@ -1544,19 +1558,19 @@ resource->dirty_image = false; } -void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id) { +void ResourceProvider::WaitSyncTokenIfNeeded(ResourceId id) { Resource* resource = GetResource(id); DCHECK_EQ(resource->exported_count, 0); DCHECK(resource->allocated); if (resource->type != RESOURCE_TYPE_GL_TEXTURE || resource->gl_id) return; - if (!resource->mailbox.sync_point()) - return; - DCHECK(resource->mailbox.IsValid()); - GLES2Interface* gl = ContextGL(); - DCHECK(gl); - gl->WaitSyncPointCHROMIUM(resource->mailbox.sync_point()); - resource->mailbox.set_sync_point(0); + if (resource->mailbox.sync_token().HasData()) { + DCHECK(resource->mailbox.IsValid()); + GLES2Interface* gl = ContextGL(); + DCHECK(gl); + gl->WaitSyncTokenCHROMIUM(resource->mailbox.sync_token().GetConstData()); + resource->mailbox.set_sync_token(gpu::SyncToken()); + } } GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) {
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h index c336119..39240a1 100644 --- a/cc/resources/resource_provider.h +++ b/cc/resources/resource_provider.h
@@ -87,6 +87,7 @@ BlockingTaskRunner* blocking_main_thread_task_runner, int highp_threshold_min, size_t id_allocation_chunk_size, + bool use_gpu_memory_buffer_resources, const std::vector<unsigned>& use_image_texture_targets); ~ResourceProvider() override; @@ -162,7 +163,7 @@ // Sets whether resources need sync points set on them when returned to this // child. Defaults to true. - void SetChildNeedsSyncPoints(int child, bool needs_sync_points); + void SetChildNeedsSyncTokens(int child, bool needs_sync_tokens); // Gets the child->parent resource ID map. const ResourceIdMap& GetChildToParentMap(int child) const; @@ -181,7 +182,7 @@ // declaring which resources are in use. Use DeclareUsedResourcesFromChild // after calling this method to do that. All calls to ReceiveFromChild should // be followed by a DeclareUsedResourcesFromChild. - // NOTE: if the sync_point is set on any TransferableResource, this will + // NOTE: if the sync_token is set on any TransferableResource, this will // wait on it. void ReceiveFromChild( int child, const TransferableResourceArray& transferable_resources); @@ -194,7 +195,7 @@ // Receives resources from the parent, moving them from mailboxes. Resource // IDs passed are in the child namespace. - // NOTE: if the sync_point is set on any TransferableResource, this will + // NOTE: if the sync_token is set on any TransferableResource, this will // wait on it. void ReceiveReturnsFromParent( const ReturnedResourceArray& transferable_resources); @@ -309,10 +310,7 @@ private: ResourceProvider* resource_provider_; ResourceProvider::Resource* resource_; - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_; - gfx::GpuMemoryBuffer* gpu_memory_buffer_; - gfx::Size size_; - ResourceFormat format_; + scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_; base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGpuMemoryBuffer); @@ -412,7 +410,7 @@ // Indicates if this resource may be used for a hardware overlay plane. bool IsOverlayCandidate(ResourceId id); - void WaitSyncPointIfNeeded(ResourceId id); + void WaitSyncTokenIfNeeded(ResourceId id); static GLint GetActiveTextureUnit(gpu::gles2::GLES2Interface* gl); @@ -435,6 +433,7 @@ BlockingTaskRunner* blocking_main_thread_task_runner, int highp_threshold_min, size_t id_allocation_chunk_size, + bool use_gpu_memory_buffer_resources, const std::vector<unsigned>& use_image_texture_targets); void Initialize(); @@ -508,7 +507,7 @@ ResourceIdMap parent_to_child_map; ReturnCallback return_callback; bool marked_for_deletion; - bool needs_sync_points; + bool needs_sync_tokens; }; typedef base::hash_map<int, Child> ChildMap; @@ -546,6 +545,7 @@ void DestroyChildInternal(ChildMap::iterator it, DeleteStyle style); void LazyCreate(Resource* resource); void LazyAllocate(Resource* resource); + void LazyCreateImage(Resource* resource); void BindImageForSampling(Resource* resource); // Binds the given GL resource to a texture target for sampling using the @@ -569,6 +569,7 @@ ChildMap children_; ResourceType default_resource_type_; + bool use_gpu_memory_buffer_resources_; bool use_texture_storage_ext_; bool use_texture_format_bgra_; bool use_texture_usage_hint_;
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc index 874fd54..2c567f71 100644 --- a/cc/resources/resource_provider_unittest.cc +++ b/cc/resources/resource_provider_unittest.cc
@@ -43,40 +43,44 @@ namespace cc { namespace { -static void EmptyReleaseCallback(uint32 sync_point, - bool lost_resource, - BlockingTaskRunner* main_thread_task_runner) { +MATCHER_P(MatchesSyncToken, sync_token, "") { + gpu::SyncToken other; + memcpy(&other, arg, sizeof(other)); + return other == sync_token; } +static void EmptyReleaseCallback(const gpu::SyncToken& sync_token, + bool lost_resource, + BlockingTaskRunner* main_thread_task_runner) {} + static void ReleaseCallback( - uint32* release_sync_point, + gpu::SyncToken* release_sync_token, bool* release_lost_resource, BlockingTaskRunner** release_main_thread_task_runner, - uint32 sync_point, + const gpu::SyncToken& sync_token, bool lost_resource, BlockingTaskRunner* main_thread_task_runner) { - *release_sync_point = sync_point; + *release_sync_token = sync_token; *release_lost_resource = lost_resource; *release_main_thread_task_runner = main_thread_task_runner; } static void SharedBitmapReleaseCallback( scoped_ptr<SharedBitmap> bitmap, - uint32 sync_point, + const gpu::SyncToken& sync_token, bool lost_resource, - BlockingTaskRunner* main_thread_task_runner) { -} + BlockingTaskRunner* main_thread_task_runner) {} static void ReleaseSharedBitmapCallback( scoped_ptr<SharedBitmap> shared_bitmap, bool* release_called, - uint32* release_sync_point, + gpu::SyncToken* release_sync_token, bool* lost_resource_result, - uint32 sync_point, + const gpu::SyncToken& sync_token, bool lost_resource, BlockingTaskRunner* main_thread_task_runner) { *release_called = true; - *release_sync_point = sync_point; + *release_sync_token = sync_token; *lost_resource_result = lost_resource; } @@ -96,7 +100,7 @@ public: MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture)); MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param)); - MOCK_METHOD1(waitSyncPoint, void(GLuint sync_point)); + MOCK_METHOD1(waitSyncToken, void(const GLbyte* sync_token)); MOCK_METHOD0(insertSyncPoint, GLuint(void)); MOCK_METHOD3(produceTextureDirectCHROMIUM, void(GLuint texture, GLenum target, const GLbyte* mailbox)); @@ -129,8 +133,10 @@ } void ProduceTexture(const GLbyte* mailbox_name, - uint32 sync_point, + const gpu::SyncToken& sync_token, scoped_refptr<TestTexture> texture) { + uint32_t sync_point = static_cast<uint32_t>(sync_token.release_count()); + unsigned mailbox = 0; memcpy(&mailbox, mailbox_name, sizeof(mailbox)); ASSERT_TRUE(mailbox && mailbox < next_mailbox_); @@ -140,7 +146,7 @@ } scoped_refptr<TestTexture> ConsumeTexture(const GLbyte* mailbox_name, - uint32 sync_point) { + const gpu::SyncToken& sync_token) { unsigned mailbox = 0; memcpy(&mailbox, mailbox_name, sizeof(mailbox)); DCHECK(mailbox && mailbox < next_mailbox_); @@ -148,7 +154,7 @@ // If the latest sync point the context has waited on is before the sync // point for when the mailbox was set, pretend we never saw that // ProduceTexture. - if (sync_point_for_mailbox_[mailbox] > sync_point) { + if (sync_point_for_mailbox_[mailbox] > sync_token.release_count()) { NOTREACHED(); return scoped_refptr<TestTexture>(); } @@ -180,18 +186,27 @@ pending_produce_textures_.begin(); it != pending_produce_textures_.end(); ++it) { - shared_data_->ProduceTexture( - (*it)->mailbox, sync_point, (*it)->texture); + shared_data_->ProduceTexture((*it)->mailbox, gpu::SyncToken(sync_point), + (*it)->texture); } pending_produce_textures_.clear(); return sync_point; } - void waitSyncPoint(GLuint sync_point) override { - last_waited_sync_point_ = std::max(sync_point, last_waited_sync_point_); + void waitSyncToken(const GLbyte* sync_token) override { + gpu::SyncToken sync_token_data; + if (sync_token) + memcpy(&sync_token_data, sync_token, sizeof(sync_token_data)); + + if (sync_token_data.release_count() > + last_waited_sync_token_.release_count()) { + last_waited_sync_token_ = sync_token_data; + } } - unsigned last_waited_sync_point() const { return last_waited_sync_point_; } + const gpu::SyncToken& last_waited_sync_token() const { + return last_waited_sync_token_; + } void texStorage2DEXT(GLenum target, GLint levels, @@ -277,7 +292,7 @@ GLuint texture_id = createTexture(); base::AutoLock lock_for_texture_access(namespace_->lock); scoped_refptr<TestTexture> texture = - shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_); + shared_data_->ConsumeTexture(mailbox, last_waited_sync_token_); namespace_->textures.Replace(texture_id, texture); return texture_id; } @@ -295,8 +310,7 @@ protected: explicit ResourceProviderContext(ContextSharedData* shared_data) - : shared_data_(shared_data), - last_waited_sync_point_(0) {} + : shared_data_(shared_data) {} private: void AllocateTexture(const gfx::Size& size, GLenum format) { @@ -345,7 +359,7 @@ }; typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList; ContextSharedData* shared_data_; - GLuint last_waited_sync_point_; + gpu::SyncToken last_waited_sync_token_; PendingProduceTextureList pending_produce_textures_; }; @@ -355,7 +369,7 @@ const gfx::Size& size, ResourceFormat format, uint8_t* pixels) { - resource_provider->WaitSyncPointIfNeeded(id); + resource_provider->WaitSyncTokenIfNeeded(id); switch (resource_provider->default_resource_type()) { case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: { ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id); @@ -378,7 +392,7 @@ class ResourceProviderTest : public testing::TestWithParam<ResourceProvider::ResourceType> { public: - explicit ResourceProviderTest(bool child_needs_sync_point) + explicit ResourceProviderTest(bool child_needs_sync_token) : shared_data_(ContextSharedData::Create()), context3d_(NULL), child_context_(NULL), @@ -397,7 +411,7 @@ scoped_ptr<ResourceProviderContext> child_context_owned = ResourceProviderContext::Create(shared_data_.get()); child_context_ = child_context_owned.get(); - if (child_needs_sync_point) { + if (child_needs_sync_token) { child_output_surface_ = FakeOutputSurface::Create3d(child_context_owned.Pass()); } else { @@ -422,11 +436,11 @@ resource_provider_ = ResourceProvider::Create( output_surface_.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, 1, - use_image_texture_targets_); + use_gpu_memory_buffer_resources_, use_image_texture_targets_); child_resource_provider_ = ResourceProvider::Create( child_output_surface_.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, 1, - use_image_texture_targets_); + use_gpu_memory_buffer_resources_, use_image_texture_targets_); } ResourceProviderTest() : ResourceProviderTest(true) {} @@ -450,26 +464,26 @@ ResourceProviderContext* context() { return context3d_; } - ResourceId CreateChildMailbox(uint32* release_sync_point, + ResourceId CreateChildMailbox(gpu::SyncToken* release_sync_token, bool* lost_resource, bool* release_called, - uint32* sync_point) { + gpu::SyncToken* sync_token) { if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { unsigned texture = child_context_->createTexture(); gpu::Mailbox gpu_mailbox; child_context_->genMailboxCHROMIUM(gpu_mailbox.name); child_context_->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, gpu_mailbox.name); - *sync_point = child_context_->insertSyncPoint(); - EXPECT_LT(0u, *sync_point); + *sync_token = gpu::SyncToken(child_context_->insertSyncPoint()); + EXPECT_TRUE(sync_token->HasData()); scoped_ptr<SharedBitmap> shared_bitmap; scoped_ptr<SingleReleaseCallbackImpl> callback = SingleReleaseCallbackImpl::Create(base::Bind( ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap), - release_called, release_sync_point, lost_resource)); + release_called, release_sync_token, lost_resource)); return child_resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point), + TextureMailbox(gpu_mailbox, *sync_token, GL_TEXTURE_2D), callback.Pass()); } else { gfx::Size size(64, 64); @@ -480,18 +494,22 @@ scoped_ptr<SingleReleaseCallbackImpl> callback = SingleReleaseCallbackImpl::Create(base::Bind( ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap), - release_called, release_sync_point, lost_resource)); + release_called, release_sync_token, lost_resource)); return child_resource_provider_->CreateResourceFromTextureMailbox( TextureMailbox(shared_bitmap_ptr, size), callback.Pass()); } } public: + static bool use_gpu_memory_buffer_resources() { + return use_gpu_memory_buffer_resources_; + } static std::vector<unsigned> use_image_texture_targets() { return use_image_texture_targets_; } protected: + static bool use_gpu_memory_buffer_resources_; static std::vector<unsigned> use_image_texture_targets_; scoped_ptr<ContextSharedData> shared_data_; ResourceProviderContext* context3d_; @@ -507,6 +525,8 @@ scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_; }; +bool ResourceProviderTest::use_gpu_memory_buffer_resources_ = false; + std::vector<unsigned> ResourceProviderTest::use_image_texture_targets_ = std::vector<unsigned>(static_cast<size_t>(gfx::BufferFormat::LAST) + 1, GL_TEXTURE_2D); @@ -610,10 +630,10 @@ child_context_->genMailboxCHROMIUM(external_mailbox.name); child_context_->produceTextureDirectCHROMIUM( external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name); - const GLuint external_sync_point = child_context_->insertSyncPoint(); + const gpu::SyncToken external_sync_token(child_context_->insertSyncPoint()); ResourceId id4 = child_resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(external_mailbox, GL_TEXTURE_EXTERNAL_OES, - external_sync_point), + TextureMailbox(external_mailbox, external_sync_token, + GL_TEXTURE_EXTERNAL_OES), SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback))); ReturnedResourceArray returned_to_child; @@ -630,14 +650,14 @@ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); ASSERT_EQ(4u, list.size()); - EXPECT_NE(0u, list[0].mailbox_holder.sync_point); - EXPECT_NE(0u, list[1].mailbox_holder.sync_point); - EXPECT_EQ(list[0].mailbox_holder.sync_point, - list[1].mailbox_holder.sync_point); - EXPECT_NE(0u, list[2].mailbox_holder.sync_point); - EXPECT_EQ(list[0].mailbox_holder.sync_point, - list[2].mailbox_holder.sync_point); - EXPECT_EQ(external_sync_point, list[3].mailbox_holder.sync_point); + EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); + EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData()); + EXPECT_EQ(list[0].mailbox_holder.sync_token, + list[1].mailbox_holder.sync_token); + EXPECT_TRUE(list[2].mailbox_holder.sync_token.HasData()); + EXPECT_EQ(list[0].mailbox_holder.sync_token, + list[2].mailbox_holder.sync_token); + EXPECT_EQ(external_sync_token, list[3].mailbox_holder.sync_token); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].mailbox_holder.texture_target); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), @@ -651,15 +671,15 @@ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4)); resource_provider_->ReceiveFromChild(child_id, list); - EXPECT_NE(list[0].mailbox_holder.sync_point, - context3d_->last_waited_sync_point()); + EXPECT_NE(list[0].mailbox_holder.sync_token, + context3d_->last_waited_sync_token()); { - resource_provider_->WaitSyncPointIfNeeded(list[0].id); + resource_provider_->WaitSyncTokenIfNeeded(list[0].id); ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(), list[0].id); } - EXPECT_EQ(list[0].mailbox_holder.sync_point, - context3d_->last_waited_sync_point()); + EXPECT_EQ(list[0].mailbox_holder.sync_token, + context3d_->last_waited_sync_token()); ResourceProvider::ResourceIdSet resource_ids_to_receive; resource_ids_to_receive.insert(id1); resource_ids_to_receive.insert(id2); @@ -732,10 +752,10 @@ resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); ASSERT_EQ(4u, returned_to_child.size()); - EXPECT_NE(0u, returned_to_child[0].sync_point); - EXPECT_NE(0u, returned_to_child[1].sync_point); - EXPECT_NE(0u, returned_to_child[2].sync_point); - EXPECT_NE(0u, returned_to_child[3].sync_point); + EXPECT_TRUE(returned_to_child[0].sync_token.HasData()); + EXPECT_TRUE(returned_to_child[1].sync_token.HasData()); + EXPECT_TRUE(returned_to_child[2].sync_token.HasData()); + EXPECT_TRUE(returned_to_child[3].sync_token.HasData()); EXPECT_FALSE(returned_to_child[0].lost); EXPECT_FALSE(returned_to_child[1].lost); EXPECT_FALSE(returned_to_child[2].lost); @@ -749,7 +769,7 @@ EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4)); { - child_resource_provider_->WaitSyncPointIfNeeded(id1); + child_resource_provider_->WaitSyncTokenIfNeeded(id1); ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(), id1); ASSERT_NE(0U, lock.texture_id()); @@ -758,7 +778,7 @@ EXPECT_EQ(0, memcmp(data1, result, pixel_size)); } { - child_resource_provider_->WaitSyncPointIfNeeded(id2); + child_resource_provider_->WaitSyncTokenIfNeeded(id2); ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(), id2); ASSERT_NE(0U, lock.texture_id()); @@ -767,7 +787,7 @@ EXPECT_EQ(0, memcmp(data2, result, pixel_size)); } { - child_resource_provider_->WaitSyncPointIfNeeded(id3); + child_resource_provider_->WaitSyncTokenIfNeeded(id3); ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(), id3); ASSERT_NE(0U, lock.texture_id()); @@ -788,10 +808,10 @@ EXPECT_EQ(id2, list[1].id); EXPECT_EQ(id3, list[2].id); EXPECT_EQ(id4, list[3].id); - EXPECT_NE(0u, list[0].mailbox_holder.sync_point); - EXPECT_NE(0u, list[1].mailbox_holder.sync_point); - EXPECT_NE(0u, list[2].mailbox_holder.sync_point); - EXPECT_NE(0u, list[3].mailbox_holder.sync_point); + EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); + EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData()); + EXPECT_TRUE(list[2].mailbox_holder.sync_token.HasData()); + EXPECT_TRUE(list[3].mailbox_holder.sync_token.HasData()); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].mailbox_holder.texture_target); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), @@ -821,24 +841,24 @@ EXPECT_EQ(0u, resource_provider_->num_resources()); ASSERT_EQ(4u, returned_to_child.size()); - EXPECT_NE(0u, returned_to_child[0].sync_point); - EXPECT_NE(0u, returned_to_child[1].sync_point); - EXPECT_NE(0u, returned_to_child[2].sync_point); - EXPECT_NE(0u, returned_to_child[3].sync_point); + EXPECT_TRUE(returned_to_child[0].sync_token.HasData()); + EXPECT_TRUE(returned_to_child[1].sync_token.HasData()); + EXPECT_TRUE(returned_to_child[2].sync_token.HasData()); + EXPECT_TRUE(returned_to_child[3].sync_token.HasData()); EXPECT_FALSE(returned_to_child[0].lost); EXPECT_FALSE(returned_to_child[1].lost); EXPECT_FALSE(returned_to_child[2].lost); EXPECT_FALSE(returned_to_child[3].lost); } -class ResourceProviderTestNoSyncPoint : public ResourceProviderTest { +class ResourceProviderTestNoSyncToken : public ResourceProviderTest { public: - ResourceProviderTestNoSyncPoint() : ResourceProviderTest(false) { + ResourceProviderTestNoSyncToken() : ResourceProviderTest(false) { EXPECT_EQ(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE, GetParam()); } }; -TEST_P(ResourceProviderTestNoSyncPoint, TransferGLResources) { +TEST_P(ResourceProviderTestNoSyncToken, TransferGLResources) { gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; size_t pixel_size = TextureSizeBytes(size, format); @@ -866,16 +886,16 @@ child_context_->genMailboxCHROMIUM(external_mailbox.name); child_context_->produceTextureDirectCHROMIUM( external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name); - const GLuint external_sync_point = child_context_->insertSyncPoint(); + const gpu::SyncToken external_sync_token(child_context_->insertSyncPoint()); ResourceId id3 = child_resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(external_mailbox, GL_TEXTURE_EXTERNAL_OES, - external_sync_point), + TextureMailbox(external_mailbox, external_sync_token, + GL_TEXTURE_EXTERNAL_OES), SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback))); ReturnedResourceArray returned_to_child; int child_id = resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); - resource_provider_->SetChildNeedsSyncPoints(child_id, false); + resource_provider_->SetChildNeedsSyncTokens(child_id, false); { // Transfer some resources to the parent. ResourceProvider::ResourceIdArray resource_ids_to_transfer; @@ -887,10 +907,10 @@ &list); ASSERT_EQ(3u, list.size()); // Standard resources shouldn't require creating and sending a sync point. - EXPECT_EQ(0u, list[0].mailbox_holder.sync_point); - EXPECT_EQ(0u, list[1].mailbox_holder.sync_point); + EXPECT_FALSE(list[0].mailbox_holder.sync_token.HasData()); + EXPECT_FALSE(list[1].mailbox_holder.sync_token.HasData()); // A given sync point should be passed through. - EXPECT_EQ(external_sync_point, list[2].mailbox_holder.sync_point); + EXPECT_EQ(external_sync_token, list[2].mailbox_holder.sync_token); resource_provider_->ReceiveFromChild(child_id, list); ResourceProvider::ResourceIdSet resource_ids_to_receive; @@ -910,19 +930,19 @@ resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); ASSERT_EQ(3u, returned_to_child.size()); - std::map<ResourceId, unsigned int> returned_sync_points; + std::map<ResourceId, gpu::SyncToken> returned_sync_tokens; for (const auto& returned : returned_to_child) - returned_sync_points[returned.id] = returned.sync_point; + returned_sync_tokens[returned.id] = returned.sync_token; - EXPECT_TRUE(returned_sync_points.find(id1) != returned_sync_points.end()); + ASSERT_TRUE(returned_sync_tokens.find(id1) != returned_sync_tokens.end()); // No new sync point should be created transferring back. - EXPECT_TRUE(returned_sync_points.find(id1) != returned_sync_points.end()); - EXPECT_EQ(0u, returned_sync_points[id1]); - EXPECT_TRUE(returned_sync_points.find(id2) != returned_sync_points.end()); - EXPECT_EQ(0u, returned_sync_points[id2]); + ASSERT_TRUE(returned_sync_tokens.find(id1) != returned_sync_tokens.end()); + EXPECT_FALSE(returned_sync_tokens[id1].HasData()); + ASSERT_TRUE(returned_sync_tokens.find(id2) != returned_sync_tokens.end()); + EXPECT_FALSE(returned_sync_tokens[id2].HasData()); // Original sync point given should be returned. - EXPECT_TRUE(returned_sync_points.find(id3) != returned_sync_points.end()); - EXPECT_EQ(external_sync_point, returned_sync_points[id3]); + ASSERT_TRUE(returned_sync_tokens.find(id3) != returned_sync_tokens.end()); + EXPECT_EQ(external_sync_token, returned_sync_tokens[id3]); EXPECT_FALSE(returned_to_child[0].lost); EXPECT_FALSE(returned_to_child[1].lost); EXPECT_FALSE(returned_to_child[2].lost); @@ -935,7 +955,7 @@ INSTANTIATE_TEST_CASE_P( ResourceProviderTests, - ResourceProviderTestNoSyncPoint, + ResourceProviderTestNoSyncToken, ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)); TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) { @@ -964,7 +984,7 @@ resource_provider_->ReceiveFromChild(child_id, list); - resource_provider_->WaitSyncPointIfNeeded(list[0].id); + resource_provider_->WaitSyncTokenIfNeeded(list[0].id); ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(), list[0].id); @@ -977,7 +997,7 @@ child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); { - child_resource_provider_->WaitSyncPointIfNeeded(id1); + child_resource_provider_->WaitSyncTokenIfNeeded(id1); ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(), id1); child_resource_provider_->DeleteResource(id1); @@ -1034,7 +1054,7 @@ resource_provider_->SetReadLockFence(fence.get()); { unsigned parent_id = list.front().id; - resource_provider_->WaitSyncPointIfNeeded(parent_id); + resource_provider_->WaitSyncTokenIfNeeded(parent_id); ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(), parent_id); } @@ -1094,7 +1114,7 @@ { for (size_t i = 0; i < list.size(); i++) { unsigned parent_id = list[i].id; - resource_provider_->WaitSyncPointIfNeeded(parent_id); + resource_provider_->WaitSyncTokenIfNeeded(parent_id); ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(), parent_id); } @@ -1156,7 +1176,7 @@ { for (size_t i = 0; i < list.size(); i++) { unsigned parent_id = list[i].id; - resource_provider_->WaitSyncPointIfNeeded(parent_id); + resource_provider_->WaitSyncTokenIfNeeded(parent_id); ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(), parent_id); } @@ -1213,9 +1233,9 @@ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); ASSERT_EQ(3u, list.size()); - EXPECT_EQ(0u, list[0].mailbox_holder.sync_point); - EXPECT_EQ(0u, list[1].mailbox_holder.sync_point); - EXPECT_EQ(0u, list[2].mailbox_holder.sync_point); + EXPECT_FALSE(list[0].mailbox_holder.sync_token.HasData()); + EXPECT_FALSE(list[1].mailbox_holder.sync_token.HasData()); + EXPECT_FALSE(list[2].mailbox_holder.sync_token.HasData()); EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); @@ -1279,9 +1299,9 @@ resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); ASSERT_EQ(3u, returned_to_child.size()); - EXPECT_EQ(0u, returned_to_child[0].sync_point); - EXPECT_EQ(0u, returned_to_child[1].sync_point); - EXPECT_EQ(0u, returned_to_child[2].sync_point); + EXPECT_FALSE(returned_to_child[0].sync_token.HasData()); + EXPECT_FALSE(returned_to_child[1].sync_token.HasData()); + EXPECT_FALSE(returned_to_child[2].sync_token.HasData()); std::set<ResourceId> expected_ids; expected_ids.insert(id1); expected_ids.insert(id2); @@ -1348,9 +1368,9 @@ EXPECT_EQ(0u, resource_provider_->num_resources()); ASSERT_EQ(3u, returned_to_child.size()); - EXPECT_EQ(0u, returned_to_child[0].sync_point); - EXPECT_EQ(0u, returned_to_child[1].sync_point); - EXPECT_EQ(0u, returned_to_child[2].sync_point); + EXPECT_FALSE(returned_to_child[0].sync_token.HasData()); + EXPECT_FALSE(returned_to_child[1].sync_token.HasData()); + EXPECT_FALSE(returned_to_child[2].sync_token.HasData()); std::set<ResourceId> expected_ids; expected_ids.insert(id1); expected_ids.insert(id2); @@ -1379,7 +1399,7 @@ scoped_ptr<ResourceProvider> child_resource_provider(ResourceProvider::Create( child_output_surface.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), NULL, 0, 1, - use_image_texture_targets_)); + use_gpu_memory_buffer_resources_, use_image_texture_targets_)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; @@ -1401,7 +1421,7 @@ child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, &list); ASSERT_EQ(1u, list.size()); - EXPECT_NE(0u, list[0].mailbox_holder.sync_point); + EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].mailbox_holder.texture_target); EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1)); @@ -1502,8 +1522,8 @@ &list); ASSERT_EQ(2u, list.size()); if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { - EXPECT_NE(0u, list[0].mailbox_holder.sync_point); - EXPECT_NE(0u, list[1].mailbox_holder.sync_point); + EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); + EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData()); } EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); @@ -1535,8 +1555,8 @@ ASSERT_EQ(2u, list.size()); if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { - EXPECT_NE(0u, list[0].mailbox_holder.sync_point); - EXPECT_NE(0u, list[1].mailbox_holder.sync_point); + EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); + EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData()); } EXPECT_TRUE(resource_provider_->InUseByConsumer(id1)); EXPECT_TRUE(resource_provider_->InUseByConsumer(id2)); @@ -1561,8 +1581,8 @@ EXPECT_EQ(0u, resource_provider_->num_resources()); ASSERT_EQ(2u, returned_to_child.size()); if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { - EXPECT_NE(0u, returned_to_child[0].sync_point); - EXPECT_NE(0u, returned_to_child[1].sync_point); + EXPECT_TRUE(returned_to_child[0].sync_token.HasData()); + EXPECT_TRUE(returned_to_child[1].sync_token.HasData()); } EXPECT_FALSE(returned_to_child[0].lost); EXPECT_FALSE(returned_to_child[1].lost); @@ -1598,8 +1618,8 @@ &list); ASSERT_EQ(2u, list.size()); if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { - EXPECT_NE(0u, list[0].mailbox_holder.sync_point); - EXPECT_NE(0u, list[1].mailbox_holder.sync_point); + EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); + EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData()); } EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); @@ -1631,8 +1651,8 @@ ASSERT_EQ(2u, list.size()); if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { - EXPECT_NE(0u, list[0].mailbox_holder.sync_point); - EXPECT_NE(0u, list[1].mailbox_holder.sync_point); + EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); + EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData()); } EXPECT_TRUE(resource_provider_->InUseByConsumer(id1)); EXPECT_TRUE(resource_provider_->InUseByConsumer(id2)); @@ -1666,7 +1686,7 @@ EXPECT_EQ(1u, resource_provider_->num_resources()); ASSERT_EQ(1u, returned_to_child.size()); if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { - EXPECT_NE(0u, returned_to_child[0].sync_point); + EXPECT_TRUE(returned_to_child[0].sync_token.HasData()); } EXPECT_FALSE(returned_to_child[0].lost); returned_to_child.clear(); @@ -1676,7 +1696,7 @@ resource_provider_ = nullptr; ASSERT_EQ(1u, returned_to_child.size()); if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { - EXPECT_NE(0u, returned_to_child[0].sync_point); + EXPECT_TRUE(returned_to_child[0].sync_token.HasData()); } EXPECT_TRUE(returned_to_child[0].lost); } @@ -1705,7 +1725,7 @@ &list); ASSERT_EQ(1u, list.size()); if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) - EXPECT_NE(0u, list[0].mailbox_holder.sync_point); + EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id)); resource_provider_->ReceiveFromChild(child_id, list); ResourceProvider::ResourceIdSet resource_ids_to_receive; @@ -1727,7 +1747,7 @@ ASSERT_EQ(1u, returned_to_child.size()); if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) - EXPECT_NE(0u, returned_to_child[0].sync_point); + EXPECT_TRUE(returned_to_child[0].sync_token.HasData()); child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); } EXPECT_EQ(0u, child_resource_provider_->num_resources()); @@ -1863,6 +1883,7 @@ scoped_ptr<ResourceProvider> child_resource_provider( ResourceProvider::Create(child_output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, 1, + use_gpu_memory_buffer_resources_, use_image_texture_targets_)); scoped_ptr<TextureStateTrackingContext> parent_context_owned( @@ -1877,6 +1898,7 @@ scoped_ptr<ResourceProvider> parent_resource_provider( ResourceProvider::Create(parent_output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, 1, + use_gpu_memory_buffer_resources_, use_image_texture_targets_)); gfx::Size size(1, 1); @@ -1950,7 +1972,7 @@ parent_resource_provider->ReceiveFromChild(child_id, list); { - parent_resource_provider->WaitSyncPointIfNeeded(list[0].id); + parent_resource_provider->WaitSyncTokenIfNeeded(list[0].id); ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(), list[0].id); } @@ -2034,23 +2056,22 @@ gpu::Mailbox mailbox; context()->genMailboxCHROMIUM(mailbox.name); context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name); - uint32 sync_point = context()->insertSyncPoint(); + gpu::SyncToken sync_token(context()->insertSyncPoint()); - // All the logic below assumes that the sync points are all positive. - EXPECT_LT(0u, sync_point); + // All the logic below assumes that the sync token releases are all positive. + EXPECT_LT(0u, sync_token.release_count()); - uint32 release_sync_point = 0; + gpu::SyncToken release_sync_token; bool lost_resource = false; BlockingTaskRunner* main_thread_task_runner = NULL; - ReleaseCallbackImpl callback = base::Bind(ReleaseCallback, - &release_sync_point, - &lost_resource, - &main_thread_task_runner); + ReleaseCallbackImpl callback = + base::Bind(ReleaseCallback, &release_sync_token, &lost_resource, + &main_thread_task_runner); ResourceId resource = resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), + TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D), SingleReleaseCallbackImpl::Create(callback)); EXPECT_EQ(1u, context()->NumTextures()); - EXPECT_EQ(0u, release_sync_point); + EXPECT_FALSE(release_sync_token.HasData()); { // Transfer the resource, expect the sync points to be consistent. ResourceProvider::ResourceIdArray resource_ids_to_transfer; @@ -2058,14 +2079,15 @@ TransferableResourceArray list; resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); ASSERT_EQ(1u, list.size()); - EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point); + EXPECT_LE(sync_token.release_count(), + list[0].mailbox_holder.sync_token.release_count()); EXPECT_EQ(0, memcmp(mailbox.name, list[0].mailbox_holder.mailbox.name, sizeof(mailbox.name))); - EXPECT_EQ(0u, release_sync_point); + EXPECT_FALSE(release_sync_token.HasData()); - context()->waitSyncPoint(list[0].mailbox_holder.sync_point); + context()->waitSyncToken(list[0].mailbox_holder.sync_token.GetConstData()); unsigned other_texture = context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); uint8_t test_data[4] = { 0 }; @@ -2076,8 +2098,8 @@ context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D, mailbox.name); context()->deleteTexture(other_texture); - list[0].mailbox_holder.sync_point = context()->insertSyncPoint(); - EXPECT_LT(0u, list[0].mailbox_holder.sync_point); + list[0].mailbox_holder.sync_token = + gpu::SyncToken(context()->insertSyncPoint()); // Receive the resource, then delete it, expect the sync points to be // consistent. @@ -2085,24 +2107,25 @@ TransferableResource::ReturnResources(list, &returned); resource_provider_->ReceiveReturnsFromParent(returned); EXPECT_EQ(1u, context()->NumTextures()); - EXPECT_EQ(0u, release_sync_point); + EXPECT_FALSE(release_sync_token.HasData()); resource_provider_->DeleteResource(resource); - EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point); + EXPECT_LE(list[0].mailbox_holder.sync_token.release_count(), + release_sync_token.release_count()); EXPECT_FALSE(lost_resource); EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner); } // We're going to do the same thing as above, but testing the case where we // delete the resource before we receive it back. - sync_point = release_sync_point; - EXPECT_LT(0u, sync_point); - release_sync_point = 0; + sync_token = release_sync_token; + EXPECT_LT(0u, sync_token.release_count()); + release_sync_token.Clear(); resource = resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), + TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D), SingleReleaseCallbackImpl::Create(callback)); EXPECT_EQ(1u, context()->NumTextures()); - EXPECT_EQ(0u, release_sync_point); + EXPECT_FALSE(release_sync_token.HasData()); { // Transfer the resource, expect the sync points to be consistent. ResourceProvider::ResourceIdArray resource_ids_to_transfer; @@ -2110,14 +2133,15 @@ TransferableResourceArray list; resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); ASSERT_EQ(1u, list.size()); - EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point); + EXPECT_LE(sync_token.release_count(), + list[0].mailbox_holder.sync_token.release_count()); EXPECT_EQ(0, memcmp(mailbox.name, list[0].mailbox_holder.mailbox.name, sizeof(mailbox.name))); - EXPECT_EQ(0u, release_sync_point); + EXPECT_FALSE(release_sync_token.HasData()); - context()->waitSyncPoint(list[0].mailbox_holder.sync_point); + context()->waitSyncToken(list[0].mailbox_holder.sync_token.GetConstData()); unsigned other_texture = context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); uint8_t test_data[4] = { 0 }; @@ -2128,25 +2152,27 @@ context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D, mailbox.name); context()->deleteTexture(other_texture); - list[0].mailbox_holder.sync_point = context()->insertSyncPoint(); - EXPECT_LT(0u, list[0].mailbox_holder.sync_point); + list[0].mailbox_holder.sync_token = + gpu::SyncToken(context()->insertSyncPoint()); + EXPECT_LT(0u, list[0].mailbox_holder.sync_token.release_count()); // Delete the resource, which shouldn't do anything. resource_provider_->DeleteResource(resource); EXPECT_EQ(1u, context()->NumTextures()); - EXPECT_EQ(0u, release_sync_point); + EXPECT_FALSE(release_sync_token.HasData()); // Then receive the resource which should release the mailbox, expect the // sync points to be consistent. ReturnedResourceArray returned; TransferableResource::ReturnResources(list, &returned); resource_provider_->ReceiveReturnsFromParent(returned); - EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point); + EXPECT_LE(list[0].mailbox_holder.sync_token.release_count(), + release_sync_token.release_count()); EXPECT_FALSE(lost_resource); EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner); } - context()->waitSyncPoint(release_sync_point); + context()->waitSyncToken(release_sync_token.GetConstData()); texture = context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); context()->deleteTexture(texture); @@ -2285,12 +2311,12 @@ } TEST_P(ResourceProviderTest, LostMailboxInParent) { - uint32 release_sync_point = 0; + gpu::SyncToken release_sync_token; bool lost_resource = false; bool release_called = false; - uint32 sync_point = 0; - ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource, - &release_called, &sync_point); + gpu::SyncToken sync_token; + ResourceId resource = CreateChildMailbox(&release_sync_token, &lost_resource, + &release_called, &sync_token); ReturnedResourceArray returned_to_child; int child_id = @@ -2338,12 +2364,12 @@ } TEST_P(ResourceProviderTest, LostMailboxInGrandParent) { - uint32 release_sync_point = 0; + gpu::SyncToken release_sync_token; bool lost_resource = false; bool release_called = false; - uint32 sync_point = 0; - ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource, - &release_called, &sync_point); + gpu::SyncToken sync_token; + ResourceId resource = CreateChildMailbox(&release_sync_token, &lost_resource, + &release_called, &sync_token); ReturnedResourceArray returned_to_child; int child_id = @@ -2408,32 +2434,32 @@ } TEST_P(ResourceProviderTest, Shutdown) { - uint32 release_sync_point = 0; + gpu::SyncToken release_sync_token; bool lost_resource = false; bool release_called = false; - uint32 sync_point = 0; - CreateChildMailbox( - &release_sync_point, &lost_resource, &release_called, &sync_point); + gpu::SyncToken sync_token; + CreateChildMailbox(&release_sync_token, &lost_resource, &release_called, + &sync_token); - EXPECT_EQ(0u, release_sync_point); + EXPECT_FALSE(release_sync_token.HasData()); EXPECT_FALSE(lost_resource); child_resource_provider_ = nullptr; if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { - EXPECT_LE(sync_point, release_sync_point); + EXPECT_LE(sync_token.release_count(), release_sync_token.release_count()); } EXPECT_TRUE(release_called); EXPECT_FALSE(lost_resource); } TEST_P(ResourceProviderTest, ShutdownWithExportedResource) { - uint32 release_sync_point = 0; + gpu::SyncToken release_sync_token; bool lost_resource = false; bool release_called = false; - uint32 sync_point = 0; - ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource, - &release_called, &sync_point); + gpu::SyncToken sync_token; + ResourceId resource = CreateChildMailbox(&release_sync_token, &lost_resource, + &release_called, &sync_token); // Transfer the resource, so we can't release it properly on shutdown. ResourceProvider::ResourceIdArray resource_ids_to_transfer; @@ -2442,13 +2468,13 @@ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); - EXPECT_EQ(0u, release_sync_point); + EXPECT_FALSE(release_sync_token.HasData()); EXPECT_FALSE(lost_resource); child_resource_provider_ = nullptr; // Since the resource is in the parent, the child considers it lost. - EXPECT_EQ(0u, release_sync_point); + EXPECT_FALSE(release_sync_token.HasData()); EXPECT_TRUE(lost_resource); } @@ -2461,29 +2487,28 @@ gpu::Mailbox mailbox; context()->genMailboxCHROMIUM(mailbox.name); context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name); - uint32 sync_point = context()->insertSyncPoint(); + gpu::SyncToken sync_token(context()->insertSyncPoint()); - EXPECT_LT(0u, sync_point); + EXPECT_TRUE(sync_token.HasData()); - uint32 release_sync_point = 0; + gpu::SyncToken release_sync_token; bool lost_resource = false; BlockingTaskRunner* main_thread_task_runner = NULL; scoped_ptr<SingleReleaseCallbackImpl> callback = - SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback, - &release_sync_point, - &lost_resource, - &main_thread_task_runner)); + SingleReleaseCallbackImpl::Create( + base::Bind(ReleaseCallback, &release_sync_token, &lost_resource, + &main_thread_task_runner)); resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), callback.Pass()); + TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D), callback.Pass()); - EXPECT_EQ(0u, release_sync_point); + EXPECT_FALSE(release_sync_token.HasData()); EXPECT_FALSE(lost_resource); EXPECT_EQ(NULL, main_thread_task_runner); resource_provider_->DidLoseOutputSurface(); resource_provider_ = nullptr; - EXPECT_LE(sync_point, release_sync_point); + EXPECT_LE(sync_token.release_count(), release_sync_token.release_count()); EXPECT_TRUE(lost_resource); EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner); } @@ -2505,7 +2530,7 @@ scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), NULL, 0, 1, - use_image_texture_targets_)); + use_gpu_memory_buffer_resources_, use_image_texture_targets_)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; @@ -2584,7 +2609,7 @@ scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), NULL, 0, 1, - use_image_texture_targets_)); + use_gpu_memory_buffer_resources_, use_image_texture_targets_)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; @@ -2627,7 +2652,7 @@ scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), NULL, 0, 1, - use_image_texture_targets_)); + use_gpu_memory_buffer_resources_, use_image_texture_targets_)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; @@ -2671,7 +2696,7 @@ scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), NULL, 0, 1, - use_image_texture_targets_)); + use_gpu_memory_buffer_resources_, use_image_texture_targets_)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; @@ -2730,16 +2755,15 @@ scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, 1, - use_image_texture_targets_)); + use_gpu_memory_buffer_resources_, use_image_texture_targets_)); - uint32 release_sync_point = 0; + gpu::SyncToken release_sync_token; bool lost_resource = false; BlockingTaskRunner* main_thread_task_runner = NULL; scoped_ptr<SingleReleaseCallbackImpl> callback = - SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback, - &release_sync_point, - &lost_resource, - &main_thread_task_runner)); + SingleReleaseCallbackImpl::Create( + base::Bind(&ReleaseCallback, &release_sync_token, &lost_resource, + &main_thread_task_runner)); TextureMailbox mailbox(shared_bitmap.get(), size); ResourceId id = resource_provider->CreateResourceFromTextureMailbox( @@ -2755,7 +2779,7 @@ } resource_provider->DeleteResource(id); - EXPECT_EQ(0u, release_sync_point); + EXPECT_FALSE(release_sync_token.HasData()); EXPECT_FALSE(lost_resource); EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner); } @@ -2779,30 +2803,30 @@ scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager, gpu_memory_buffer_manager, - main_thread_task_runner, 0, 1, use_image_texture_targets_)); + main_thread_task_runner, 0, 1, use_gpu_memory_buffer_resources_, + use_image_texture_targets_)); unsigned texture_id = 1; - uint32 sync_point = 30; + gpu::SyncToken sync_token(30); unsigned target = GL_TEXTURE_2D; EXPECT_CALL(*context, bindTexture(_, _)).Times(0); - EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); + EXPECT_CALL(*context, waitSyncToken(_)).Times(0); EXPECT_CALL(*context, insertSyncPoint()).Times(0); EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); gpu::Mailbox gpu_mailbox; memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); - uint32 release_sync_point = 0; + gpu::SyncToken release_sync_token; bool lost_resource = false; BlockingTaskRunner* mailbox_task_runner = NULL; scoped_ptr<SingleReleaseCallbackImpl> callback = - SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback, - &release_sync_point, - &lost_resource, - &mailbox_task_runner)); + SingleReleaseCallbackImpl::Create( + base::Bind(&ReleaseCallback, &release_sync_token, &lost_resource, + &mailbox_task_runner)); - TextureMailbox mailbox(gpu_mailbox, target, sync_point); + TextureMailbox mailbox(gpu_mailbox, sync_token, target); mailbox.set_nearest_neighbor(mailbox_nearest_neighbor); ResourceId id = resource_provider->CreateResourceFromTextureMailbox( @@ -2812,9 +2836,9 @@ Mock::VerifyAndClearExpectations(context); { - // Mailbox sync point WaitSyncPoint before using the texture. - EXPECT_CALL(*context, waitSyncPoint(sync_point)); - resource_provider->WaitSyncPointIfNeeded(id); + // Mailbox sync point WaitSyncToken before using the texture. + EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(sync_token))); + resource_provider->WaitSyncTokenIfNeeded(id); Mock::VerifyAndClearExpectations(context); EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _)) @@ -2843,12 +2867,12 @@ EXPECT_CALL(*context, insertSyncPoint()); EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); - EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); + EXPECT_CALL(*context, waitSyncToken(_)).Times(0); EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); } resource_provider->DeleteResource(id); - EXPECT_EQ(0u, release_sync_point); + EXPECT_FALSE(release_sync_token.HasData()); EXPECT_FALSE(lost_resource); EXPECT_EQ(main_thread_task_runner, mailbox_task_runner); } @@ -2923,13 +2947,13 @@ scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), NULL, 0, 1, - use_image_texture_targets_)); + use_gpu_memory_buffer_resources_, use_image_texture_targets_)); - uint32 sync_point = 30; + gpu::SyncToken sync_token(30); unsigned target = GL_TEXTURE_EXTERNAL_OES; EXPECT_CALL(*context, bindTexture(_, _)).Times(0); - EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); + EXPECT_CALL(*context, waitSyncToken(_)).Times(0); EXPECT_CALL(*context, insertSyncPoint()).Times(0); EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); @@ -2939,7 +2963,7 @@ scoped_ptr<SingleReleaseCallbackImpl> callback = SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)); - TextureMailbox mailbox(gpu_mailbox, target, sync_point); + TextureMailbox mailbox(gpu_mailbox, sync_token, target); ResourceId id = resource_provider->CreateResourceFromTextureMailbox( mailbox, callback.Pass()); @@ -2948,9 +2972,9 @@ Mock::VerifyAndClearExpectations(context); { - // Mailbox sync point WaitSyncPoint before using the texture. - EXPECT_CALL(*context, waitSyncPoint(sync_point)); - resource_provider->WaitSyncPointIfNeeded(id); + // Mailbox sync point WaitSyncToken before using the texture. + EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(sync_token))); + resource_provider->WaitSyncTokenIfNeeded(id); Mock::VerifyAndClearExpectations(context); unsigned texture_id = 1; @@ -2970,13 +2994,13 @@ EXPECT_CALL(*context, insertSyncPoint()); EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); - EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); + EXPECT_CALL(*context, waitSyncToken(_)).Times(0); EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); } } TEST_P(ResourceProviderTest, - TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint) { + TextureMailbox_WaitSyncTokenIfNeeded_WithSyncToken) { // Mailboxing is only supported for GL textures. if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) return; @@ -2993,13 +3017,13 @@ scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), NULL, 0, 1, - use_image_texture_targets_)); + use_gpu_memory_buffer_resources_, use_image_texture_targets_)); - uint32 sync_point = 30; + gpu::SyncToken sync_token(30); unsigned target = GL_TEXTURE_2D; EXPECT_CALL(*context, bindTexture(_, _)).Times(0); - EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); + EXPECT_CALL(*context, waitSyncToken(_)).Times(0); EXPECT_CALL(*context, insertSyncPoint()).Times(0); EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); @@ -3009,7 +3033,7 @@ scoped_ptr<SingleReleaseCallbackImpl> callback = SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)); - TextureMailbox mailbox(gpu_mailbox, target, sync_point); + TextureMailbox mailbox(gpu_mailbox, sync_token, target); ResourceId id = resource_provider->CreateResourceFromTextureMailbox( mailbox, callback.Pass()); @@ -3018,19 +3042,19 @@ Mock::VerifyAndClearExpectations(context); { - // First call to WaitSyncPointIfNeeded should call waitSyncPoint. - EXPECT_CALL(*context, waitSyncPoint(sync_point)); - resource_provider->WaitSyncPointIfNeeded(id); + // First call to WaitSyncTokenIfNeeded should call waitSyncToken. + EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(sync_token))); + resource_provider->WaitSyncTokenIfNeeded(id); Mock::VerifyAndClearExpectations(context); - // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint. - EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); - resource_provider->WaitSyncPointIfNeeded(id); + // Subsequent calls to WaitSyncTokenIfNeeded shouldn't call waitSyncToken. + EXPECT_CALL(*context, waitSyncToken(_)).Times(0); + resource_provider->WaitSyncTokenIfNeeded(id); Mock::VerifyAndClearExpectations(context); } } -TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) { +TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncTokenIfNeeded_NoSyncToken) { // Mailboxing is only supported for GL textures. if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) return; @@ -3047,13 +3071,13 @@ scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), NULL, 0, 1, - use_image_texture_targets_)); + use_gpu_memory_buffer_resources_, use_image_texture_targets_)); - uint32 sync_point = 0; + gpu::SyncToken sync_token; unsigned target = GL_TEXTURE_2D; EXPECT_CALL(*context, bindTexture(_, _)).Times(0); - EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); + EXPECT_CALL(*context, waitSyncToken(_)).Times(0); EXPECT_CALL(*context, insertSyncPoint()).Times(0); EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); @@ -3063,7 +3087,7 @@ scoped_ptr<SingleReleaseCallbackImpl> callback = SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)); - TextureMailbox mailbox(gpu_mailbox, target, sync_point); + TextureMailbox mailbox(gpu_mailbox, sync_token, target); ResourceId id = resource_provider->CreateResourceFromTextureMailbox( mailbox, callback.Pass()); @@ -3072,9 +3096,9 @@ Mock::VerifyAndClearExpectations(context); { - // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint. - EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); - resource_provider->WaitSyncPointIfNeeded(id); + // WaitSyncTokenIfNeeded with empty sync_token shouldn't call waitSyncToken. + EXPECT_CALL(*context, waitSyncToken(_)).Times(0); + resource_provider->WaitSyncTokenIfNeeded(id); Mock::VerifyAndClearExpectations(context); } } @@ -3168,7 +3192,7 @@ scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), NULL, 0, 1, - use_image_texture_targets_)); + use_gpu_memory_buffer_resources_, use_image_texture_targets_)); gfx::Size size(2, 2); gfx::Vector2d offset(0, 0); @@ -3224,7 +3248,7 @@ scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), NULL, 0, 1, - use_image_texture_targets_)); + use_gpu_memory_buffer_resources_, use_image_texture_targets_)); gfx::Size size(2, 2); @@ -3280,7 +3304,7 @@ scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), NULL, 0, 1, - use_image_texture_targets_)); + use_gpu_memory_buffer_resources_, use_image_texture_targets_)); gfx::Size size(2, 2); const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888}; @@ -3339,7 +3363,7 @@ scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), NULL, 0, 1, - use_image_texture_targets_)); + use_gpu_memory_buffer_resources_, use_image_texture_targets_)); id = resource_provider->CreateResource( size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); @@ -3348,7 +3372,7 @@ .WillOnce(Return(kTextureId)) .RetiresOnSaturation(); EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)) - .Times(1) + .Times(3) .RetiresOnSaturation(); EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA)) .WillOnce(Return(kImageId)) @@ -3417,7 +3441,7 @@ scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), NULL, 0, 1, - use_image_texture_targets_)); + use_gpu_memory_buffer_resources_, use_image_texture_targets_)); int texture_id = 123; ResourceId id = resource_provider->CreateResource( @@ -3449,7 +3473,7 @@ scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), NULL, 0, 1, - use_image_texture_targets_)); + use_gpu_memory_buffer_resources_, use_image_texture_targets_)); int texture_id = 123; uint8_t pixels[8]; @@ -3506,6 +3530,7 @@ scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, kTextureAllocationChunkSize, + ResourceProviderTest::use_gpu_memory_buffer_resources(), ResourceProviderTest::use_image_texture_targets())); ResourceId id = resource_provider->CreateResource( @@ -3522,6 +3547,7 @@ scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, kTextureAllocationChunkSize, + ResourceProviderTest::use_gpu_memory_buffer_resources(), ResourceProviderTest::use_image_texture_targets())); ResourceId id = resource_provider->CreateResource(
diff --git a/cc/resources/returned_resource.h b/cc/resources/returned_resource.h index 94a574e9..92e57ad 100644 --- a/cc/resources/returned_resource.h +++ b/cc/resources/returned_resource.h
@@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "cc/base/cc_export.h" #include "cc/base/resource_id.h" +#include "gpu/command_buffer/common/sync_token.h" namespace cc { @@ -17,17 +18,17 @@ // parent compositor that corresponds to a TransferableResource that was // first passed to the parent compositor. struct CC_EXPORT ReturnedResource { - ReturnedResource() : id(0), sync_point(0), count(0), lost(false) {} + ReturnedResource() : id(0), count(0), lost(false) {} // |id| is an identifier generated by the child compositor that uniquely // identifies a resource. This is the same ID space as TransferableResource. ResourceId id; - // A |sync_point| is an identifier for a point in the parent compositor's + // A |sync_token| is an identifier for a point in the parent compositor's // command buffer. The child compositor then issues a WaitSyncPointCHROMIUM - // command with this |sync_point| as a parameter into its own command buffer. + // command with this |sync_token| as a parameter into its own command buffer. // This ensures that uses of the resource submitted by the parent compositor // are executed before commands submitted by the child. - unsigned sync_point; + gpu::SyncToken sync_token; // |count| is a reference count for this resource. A resource may be used // by mulitple compositor frames submitted to the parent compositor. |count|
diff --git a/cc/resources/single_release_callback.cc b/cc/resources/single_release_callback.cc index ff94223..4c199dc 100644 --- a/cc/resources/single_release_callback.cc +++ b/cc/resources/single_release_callback.cc
@@ -19,10 +19,11 @@ DCHECK(callback_.is_null()) << "SingleReleaseCallback was never run."; } -void SingleReleaseCallback::Run(uint32 sync_point, bool is_lost) { +void SingleReleaseCallback::Run(const gpu::SyncToken& sync_token, + bool is_lost) { DCHECK(!callback_.is_null()) << "SingleReleaseCallback was run more than once."; - base::ResetAndReturn(&callback_).Run(sync_point, is_lost); + base::ResetAndReturn(&callback_).Run(sync_token, is_lost); } } // namespace cc
diff --git a/cc/resources/single_release_callback.h b/cc/resources/single_release_callback.h index b51c4e60..2118ad7 100644 --- a/cc/resources/single_release_callback.h +++ b/cc/resources/single_release_callback.h
@@ -19,7 +19,7 @@ ~SingleReleaseCallback(); - void Run(uint32 sync_point, bool is_lost); + void Run(const gpu::SyncToken& sync_token, bool is_lost); private: explicit SingleReleaseCallback(const ReleaseCallback& callback);
diff --git a/cc/resources/single_release_callback_impl.cc b/cc/resources/single_release_callback_impl.cc index c19e14e..bab9dd4 100644 --- a/cc/resources/single_release_callback_impl.cc +++ b/cc/resources/single_release_callback_impl.cc
@@ -22,13 +22,13 @@ } void SingleReleaseCallbackImpl::Run( - uint32 sync_point, + const gpu::SyncToken& sync_token, bool is_lost, BlockingTaskRunner* main_thread_task_runner) { DCHECK(!callback_.is_null()) << "SingleReleaseCallbackImpl was run more than once."; base::ResetAndReturn(&callback_) - .Run(sync_point, is_lost, main_thread_task_runner); + .Run(sync_token, is_lost, main_thread_task_runner); } } // namespace cc
diff --git a/cc/resources/single_release_callback_impl.h b/cc/resources/single_release_callback_impl.h index e9d4293..50c0210b 100644 --- a/cc/resources/single_release_callback_impl.h +++ b/cc/resources/single_release_callback_impl.h
@@ -20,7 +20,7 @@ ~SingleReleaseCallbackImpl(); - void Run(uint32 sync_point, + void Run(const gpu::SyncToken& sync_token, bool is_lost, BlockingTaskRunner* main_thread_task_runner);
diff --git a/cc/resources/texture_mailbox.cc b/cc/resources/texture_mailbox.cc index ad008b82..3045671 100644 --- a/cc/resources/texture_mailbox.cc +++ b/cc/resources/texture_mailbox.cc
@@ -19,19 +19,19 @@ nearest_neighbor_(false) {} TextureMailbox::TextureMailbox(const gpu::Mailbox& mailbox, - uint32 target, - uint32 sync_point) - : mailbox_holder_(mailbox, target, sync_point), + const gpu::SyncToken& sync_token, + uint32 target) + : mailbox_holder_(mailbox, sync_token, target), shared_bitmap_(NULL), is_overlay_candidate_(false), nearest_neighbor_(false) {} TextureMailbox::TextureMailbox(const gpu::Mailbox& mailbox, + const gpu::SyncToken& sync_token, uint32 target, - uint32 sync_point, const gfx::Size& size_in_pixels, bool is_overlay_candidate) - : mailbox_holder_(mailbox, target, sync_point), + : mailbox_holder_(mailbox, sync_token, target), shared_bitmap_(nullptr), size_in_pixels_(size_in_pixels), is_overlay_candidate_(is_overlay_candidate),
diff --git a/cc/resources/texture_mailbox.h b/cc/resources/texture_mailbox.h index 9fc0fb8..01cc660 100644 --- a/cc/resources/texture_mailbox.h +++ b/cc/resources/texture_mailbox.h
@@ -21,10 +21,12 @@ public: TextureMailbox(); explicit TextureMailbox(const gpu::MailboxHolder& mailbox_holder); - TextureMailbox(const gpu::Mailbox& mailbox, uint32 target, uint32 sync_point); TextureMailbox(const gpu::Mailbox& mailbox, + const gpu::SyncToken& sync_token, + uint32 target); + TextureMailbox(const gpu::Mailbox& mailbox, + const gpu::SyncToken& sync_token, uint32 target, - uint32 sync_point, const gfx::Size& size_in_pixels, bool is_overlay_candidate); TextureMailbox(SharedBitmap* shared_bitmap, const gfx::Size& size_in_pixels); @@ -40,9 +42,11 @@ const gpu::Mailbox& mailbox() const { return mailbox_holder_.mailbox; } const int8* name() const { return mailbox().name; } uint32 target() const { return mailbox_holder_.texture_target; } - uint32 sync_point() const { return mailbox_holder_.sync_point; } - void set_sync_point(int32 sync_point) { - mailbox_holder_.sync_point = sync_point; + const gpu::SyncToken& sync_token() const { + return mailbox_holder_.sync_token; + } + void set_sync_token(const gpu::SyncToken& sync_token) { + mailbox_holder_.sync_token = sync_token; } bool is_overlay_candidate() const { return is_overlay_candidate_; }
diff --git a/cc/resources/transferable_resource.cc b/cc/resources/transferable_resource.cc index 738de63a..af65ff6 100644 --- a/cc/resources/transferable_resource.cc +++ b/cc/resources/transferable_resource.cc
@@ -21,7 +21,7 @@ ReturnedResource TransferableResource::ToReturnedResource() const { ReturnedResource returned; returned.id = id; - returned.sync_point = mailbox_holder.sync_point; + returned.sync_token = mailbox_holder.sync_token; returned.count = 1; return returned; }
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc index b2f86294..fd322125 100644 --- a/cc/resources/video_resource_updater.cc +++ b/cc/resources/video_resource_updater.cc
@@ -69,30 +69,33 @@ return VideoFrameExternalResources::NONE; } -class SyncPointClientImpl : public media::VideoFrame::SyncPointClient { +class SyncTokenClientImpl : public media::VideoFrame::SyncTokenClient { public: - explicit SyncPointClientImpl(gpu::gles2::GLES2Interface* gl, - uint32 sync_point) - : gl_(gl), sync_point_(sync_point) {} - ~SyncPointClientImpl() override {} + SyncTokenClientImpl(gpu::gles2::GLES2Interface* gl, + const gpu::SyncToken& sync_token) + : gl_(gl), sync_token_(sync_token) {} + ~SyncTokenClientImpl() override {} uint32 InsertSyncPoint() override { - if (sync_point_) - return sync_point_; + if (sync_token_.HasData()) { + DCHECK_EQ(gpu::CommandBufferNamespace::OLD_SYNC_POINTS, + sync_token_.namespace_id()); + return static_cast<uint32>(sync_token_.release_count()); + } return gl_->InsertSyncPointCHROMIUM(); } - void WaitSyncPoint(uint32 sync_point) override { - if (!sync_point) - return; - gl_->WaitSyncPointCHROMIUM(sync_point); - if (sync_point_) { - gl_->WaitSyncPointCHROMIUM(sync_point_); - sync_point_ = 0; + void WaitSyncToken(const gpu::SyncToken& sync_token) override { + if (sync_token.HasData()) { + gl_->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); + if (sync_token_.HasData()) { + gl_->WaitSyncTokenCHROMIUM(sync_token_.GetConstData()); + sync_token_.Clear(); + } } } private: gpu::gles2::GLES2Interface* gl_; - uint32 sync_point_; + gpu::SyncToken sync_token_; }; } // namespace @@ -381,8 +384,8 @@ SetPlaneResourceUniqueId(video_frame.get(), i, &plane_resource); } - external_resources.mailboxes.push_back( - TextureMailbox(plane_resource.mailbox, GL_TEXTURE_2D, 0)); + external_resources.mailboxes.push_back(TextureMailbox( + plane_resource.mailbox, gpu::SyncToken(), GL_TEXTURE_2D)); external_resources.release_callbacks.push_back( base::Bind(&RecycleResource, AsWeakPtr(), plane_resource.resource_id)); } @@ -395,19 +398,19 @@ void VideoResourceUpdater::ReturnTexture( base::WeakPtr<VideoResourceUpdater> updater, const scoped_refptr<media::VideoFrame>& video_frame, - uint32 sync_point, + const gpu::SyncToken& sync_token, bool lost_resource, BlockingTaskRunner* main_thread_task_runner) { // TODO(dshwang) this case should be forwarded to the decoder as lost // resource. if (lost_resource || !updater.get()) return; - // Update the release sync point in |video_frame| with |sync_point| - // returned by the compositor and emit a WaitSyncPointCHROMIUM on + // Update the release sync point in |video_frame| with |sync_token| + // returned by the compositor and emit a WaitSyncTokenCHROMIUM on // |video_frame|'s previous sync point using the current GL context. - SyncPointClientImpl client(updater->context_provider_->ContextGL(), - sync_point); - video_frame->UpdateReleaseSyncPoint(&client); + SyncTokenClientImpl client(updater->context_provider_->ContextGL(), + sync_token); + video_frame->UpdateReleaseSyncToken(&client); } VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( @@ -433,8 +436,8 @@ if (mailbox_holder.mailbox.IsZero()) break; external_resources.mailboxes.push_back( - TextureMailbox(mailbox_holder.mailbox, mailbox_holder.texture_target, - mailbox_holder.sync_point, video_frame->coded_size(), + TextureMailbox(mailbox_holder.mailbox, mailbox_holder.sync_token, + mailbox_holder.texture_target, video_frame->coded_size(), video_frame->metadata()->IsTrue( media::VideoFrameMetadata::ALLOW_OVERLAY))); external_resources.release_callbacks.push_back( @@ -447,7 +450,7 @@ void VideoResourceUpdater::RecycleResource( base::WeakPtr<VideoResourceUpdater> updater, ResourceId resource_id, - uint32 sync_point, + const gpu::SyncToken& sync_token, bool lost_resource, BlockingTaskRunner* main_thread_task_runner) { if (!updater.get()) { @@ -464,8 +467,9 @@ return; ContextProvider* context_provider = updater->context_provider_; - if (context_provider && sync_point) { - context_provider->ContextGL()->WaitSyncPointCHROMIUM(sync_point); + if (context_provider && sync_token.HasData()) { + context_provider->ContextGL()->WaitSyncTokenCHROMIUM( + sync_token.GetConstData()); } if (lost_resource) {
diff --git a/cc/resources/video_resource_updater.h b/cc/resources/video_resource_updater.h index ad3d1ab..3da2023f 100644 --- a/cc/resources/video_resource_updater.h +++ b/cc/resources/video_resource_updater.h
@@ -121,12 +121,12 @@ static void RecycleResource(base::WeakPtr<VideoResourceUpdater> updater, unsigned resource_id, - uint32 sync_point, + const gpu::SyncToken& sync_token, bool lost_resource, BlockingTaskRunner* main_thread_task_runner); static void ReturnTexture(base::WeakPtr<VideoResourceUpdater> updater, const scoped_refptr<media::VideoFrame>& video_frame, - uint32 sync_point, + const gpu::SyncToken& sync_token, bool lost_resource, BlockingTaskRunner* main_thread_task_runner);
diff --git a/cc/resources/video_resource_updater_unittest.cc b/cc/resources/video_resource_updater_unittest.cc index 3d4bf17..10e81f6 100644 --- a/cc/resources/video_resource_updater_unittest.cc +++ b/cc/resources/video_resource_updater_unittest.cc
@@ -99,7 +99,7 @@ base::TimeDelta()); // timestamp } - static void ReleaseMailboxCB(unsigned sync_point) {} + static void ReleaseMailboxCB(const gpu::SyncToken& sync_token) {} scoped_refptr<media::VideoFrame> CreateTestRGBAHardwareVideoFrame() { const int kDimension = 10; @@ -108,11 +108,11 @@ gpu::Mailbox mailbox; mailbox.name[0] = 51; - const unsigned sync_point = 7; + const gpu::SyncToken sync_token(7); const unsigned target = GL_TEXTURE_2D; return media::VideoFrame::WrapNativeTexture( media::PIXEL_FORMAT_ARGB, - gpu::MailboxHolder(mailbox, target, sync_point), + gpu::MailboxHolder(mailbox, sync_token, target), base::Bind(&ReleaseMailboxCB), size, // coded_size gfx::Rect(size), // visible_rect @@ -129,15 +129,15 @@ for (int i = 0; i < kPlanesNum; ++i) { mailbox[i].name[0] = 50 + 1; } - const unsigned sync_point = 7; + const gpu::SyncToken sync_token(7); const unsigned target = GL_TEXTURE_RECTANGLE_ARB; return media::VideoFrame::WrapYUV420NativeTextures( - gpu::MailboxHolder(mailbox[media::VideoFrame::kYPlane], target, - sync_point), - gpu::MailboxHolder(mailbox[media::VideoFrame::kUPlane], target, - sync_point), - gpu::MailboxHolder(mailbox[media::VideoFrame::kVPlane], target, - sync_point), + gpu::MailboxHolder(mailbox[media::VideoFrame::kYPlane], sync_token, + target), + gpu::MailboxHolder(mailbox[media::VideoFrame::kUPlane], sync_token, + target), + gpu::MailboxHolder(mailbox[media::VideoFrame::kVPlane], sync_token, + target), base::Bind(&ReleaseMailboxCB), size, // coded_size gfx::Rect(size), // visible_rect @@ -184,7 +184,7 @@ // Simulate the ResourceProvider releasing the resources back to the video // updater. for (ReleaseCallbackImpl& release_callback : resources.release_callbacks) - release_callback.Run(0, false, nullptr); + release_callback.Run(gpu::SyncToken(), false, nullptr); // Allocate resources for the same frame. context3d_->ResetUploadCount(); @@ -250,7 +250,7 @@ // Simulate the ResourceProvider releasing the resource back to the video // updater. - resources.software_release_callback.Run(0, false, nullptr); + resources.software_release_callback.Run(gpu::SyncToken(), false, nullptr); // Allocate resources for the same frame. shared_bitmap_manager_->ResetAllocationCount();
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc index 28f99ed..69e45cd 100644 --- a/cc/scheduler/scheduler.cc +++ b/cc/scheduler/scheduler.cc
@@ -172,6 +172,11 @@ ProcessScheduledActions(); } +void Scheduler::SetNeedsOneBeginImplFrame() { + state_machine_.SetNeedsOneBeginImplFrame(); + ProcessScheduledActions(); +} + void Scheduler::SetNeedsRedraw() { state_machine_.SetNeedsRedraw(); ProcessScheduledActions();
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h index 58ad8000..26bc13a 100644 --- a/cc/scheduler/scheduler.h +++ b/cc/scheduler/scheduler.h
@@ -84,6 +84,9 @@ void SetThrottleFrameProduction(bool throttle); void SetNeedsBeginMainFrame(); + // Requests a single impl frame (after the current frame if there is one + // active). + void SetNeedsOneBeginImplFrame(); void SetNeedsRedraw();
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc index aeda6dd..7e91471 100644 --- a/cc/scheduler/scheduler_state_machine.cc +++ b/cc/scheduler/scheduler_state_machine.cc
@@ -39,6 +39,7 @@ needs_animate_(false), needs_prepare_tiles_(false), needs_begin_main_frame_(false), + needs_one_begin_impl_frame_(false), visible_(false), resourceless_draw_(false), can_draw_(false), @@ -224,6 +225,7 @@ state->SetBoolean("needs_animate_", needs_animate_); state->SetBoolean("needs_prepare_tiles", needs_prepare_tiles_); state->SetBoolean("needs_begin_main_frame", needs_begin_main_frame_); + state->SetBoolean("needs_one_begin_impl_frame", needs_one_begin_impl_frame_); state->SetBoolean("visible", visible_); state->SetBoolean("can_draw", can_draw_); state->SetBoolean("resourceless_draw", resourceless_draw_); @@ -743,7 +745,7 @@ if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) return true; - return needs_animate_ || needs_redraw_ || + return needs_animate_ || needs_redraw_ || needs_one_begin_impl_frame_ || (needs_begin_main_frame_ && !defer_commits_); } @@ -799,6 +801,7 @@ last_commit_had_no_updates_ = false; did_request_swap_in_last_frame_ = false; + needs_one_begin_impl_frame_ = false; // Clear funnels for any actions we perform during the frame. animate_funnel_ = false; @@ -939,7 +942,8 @@ } bool SchedulerStateMachine::OnlyImplSideUpdatesExpected() const { - bool has_impl_updates = needs_redraw_ || needs_animate_; + bool has_impl_updates = + needs_redraw_ || needs_animate_ || needs_one_begin_impl_frame_; bool main_updates_expected = needs_begin_main_frame_ || begin_main_frame_state_ != BEGIN_MAIN_FRAME_STATE_IDLE || @@ -1024,6 +1028,10 @@ needs_begin_main_frame_ = true; } +void SchedulerStateMachine::SetNeedsOneBeginImplFrame() { + needs_one_begin_impl_frame_ = true; +} + void SchedulerStateMachine::NotifyReadyToCommit() { DCHECK(begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_STARTED) << AsValue()->ToString();
diff --git a/cc/scheduler/scheduler_state_machine.h b/cc/scheduler/scheduler_state_machine.h index e6a7222..17fdf98 100644 --- a/cc/scheduler/scheduler_state_machine.h +++ b/cc/scheduler/scheduler_state_machine.h
@@ -207,6 +207,10 @@ void SetNeedsBeginMainFrame(); bool needs_begin_main_frame() const { return needs_begin_main_frame_; } + // Requests a single impl frame (after the current frame if there is one + // active). + void SetNeedsOneBeginImplFrame(); + // Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME // from NextAction. // Indicates that all painting is complete. @@ -321,6 +325,7 @@ bool needs_animate_; bool needs_prepare_tiles_; bool needs_begin_main_frame_; + bool needs_one_begin_impl_frame_; bool visible_; bool resourceless_draw_; bool can_draw_;
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc index 0846e954..70f6dec9 100644 --- a/cc/scheduler/scheduler_unittest.cc +++ b/cc/scheduler/scheduler_unittest.cc
@@ -58,6 +58,7 @@ states_.clear(); animate_causes_redraw_ = false; animate_causes_animate_ = false; + will_begin_impl_frame_requests_one_begin_impl_frame_ = false; draw_will_happen_ = true; swap_will_happen_if_draw_happens_ = true; num_draws_ = 0; @@ -88,6 +89,9 @@ return ActionIndex(action) >= 0; } + void SetWillBeginImplFrameRequestsOneBeginImplFrame(bool request) { + will_begin_impl_frame_requests_one_begin_impl_frame_ = request; + } void SetAnimateCausesRedraw(bool animate_causes_redraw) { animate_causes_redraw_ = animate_causes_redraw; } @@ -106,6 +110,8 @@ // SchedulerClient implementation. void WillBeginImplFrame(const BeginFrameArgs& args) override { PushAction("WillBeginImplFrame"); + if (will_begin_impl_frame_requests_one_begin_impl_frame_) + scheduler_->SetNeedsOneBeginImplFrame(); } void DidFinishImplFrame() override {} @@ -192,6 +198,7 @@ bool animate_causes_redraw_; bool animate_causes_animate_; + bool will_begin_impl_frame_requests_one_begin_impl_frame_; bool draw_will_happen_; bool swap_will_happen_if_draw_happens_; bool automatic_swap_ack_; @@ -3165,6 +3172,44 @@ client_->Reset(); } +TEST_F(SchedulerTest, SetNeedsOneBeginImplFrame) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + + EXPECT_FALSE(client_->needs_begin_frames()); + + // Request a frame, should kick the source. + scheduler_->SetNeedsOneBeginImplFrame(); + EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + client_->Reset(); + + // The incoming WillBeginImplFrame will request another one. + client_->SetWillBeginImplFrameRequestsOneBeginImplFrame(true); + + // Next vsync, the first requested frame happens. + EXPECT_SCOPED(AdvanceFrame()); + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); + EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + client_->Reset(); + + // We don't request another frame here. + + // Next vsync, the second requested frame happens (the one requested inside + // the previous frame's begin impl frame step). + EXPECT_SCOPED(AdvanceFrame()); + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); + EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + client_->Reset(); + + // End that frame's deadline. + task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + + // Scheduler shuts down the source now that no begin frame is requested. + EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); + EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); +} + TEST_F(SchedulerTest, SynchronousCompositorCommit) { scheduler_settings_.using_synchronous_renderer_compositor = true; scheduler_settings_.use_external_begin_frame_source = true;
diff --git a/cc/surfaces/display.cc b/cc/surfaces/display.cc index 7cd9d6d..31335ae 100644 --- a/cc/surfaces/display.cc +++ b/cc/surfaces/display.cc
@@ -106,6 +106,7 @@ output_surface_.get(), bitmap_manager_, gpu_memory_buffer_manager_, nullptr, settings_.highp_threshold_min, settings_.texture_id_allocation_chunk_size, + settings_.use_gpu_memory_buffer_resources, std::vector<unsigned>(static_cast<size_t>(gfx::BufferFormat::LAST) + 1, GL_TEXTURE_2D)); if (!resource_provider)
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc index 25c2584..a0108b7d 100644 --- a/cc/surfaces/surface_aggregator.cc +++ b/cc/surfaces/surface_aggregator.cc
@@ -132,7 +132,7 @@ int child_id = provider_->CreateChild(base::Bind(&UnrefHelper, surface->factory())); if (surface->factory()) { - provider_->SetChildNeedsSyncPoints( + provider_->SetChildNeedsSyncTokens( child_id, surface->factory()->needs_sync_points()); } surface_id_to_resource_child_id_[surface->surface_id()] = child_id;
diff --git a/cc/test/fake_resource_provider.h b/cc/test/fake_resource_provider.h index 7b54072..4ad254f 100644 --- a/cc/test/fake_resource_provider.h +++ b/cc/test/fake_resource_provider.h
@@ -16,7 +16,7 @@ OutputSurface* output_surface, SharedBitmapManager* shared_bitmap_manager) { scoped_ptr<FakeResourceProvider> provider(new FakeResourceProvider( - output_surface, shared_bitmap_manager, nullptr, nullptr, 0, 1, + output_surface, shared_bitmap_manager, nullptr, nullptr, 0, 1, false, std::vector<unsigned>(static_cast<size_t>(gfx::BufferFormat::LAST) + 1, GL_TEXTURE_2D))); provider->Initialize(); @@ -29,7 +29,7 @@ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) { scoped_ptr<FakeResourceProvider> provider(new FakeResourceProvider( output_surface, shared_bitmap_manager, gpu_memory_buffer_manager, - nullptr, 0, 1, + nullptr, 0, 1, false, std::vector<unsigned>(static_cast<size_t>(gfx::BufferFormat::LAST) + 1, GL_TEXTURE_2D))); provider->Initialize(); @@ -43,6 +43,7 @@ BlockingTaskRunner* blocking_main_thread_task_runner, int highp_threshold_min, size_t id_allocation_chunk_size, + bool use_gpu_memory_buffer_resources, const std::vector<unsigned>& use_image_texture_targets) : ResourceProvider(output_surface, shared_bitmap_manager, @@ -50,6 +51,7 @@ blocking_main_thread_task_runner, highp_threshold_min, id_allocation_chunk_size, + use_gpu_memory_buffer_resources, use_image_texture_targets) {} };
diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc index a08211b0..b4fafd2 100644 --- a/cc/test/layer_tree_pixel_test.cc +++ b/cc/test/layer_tree_pixel_test.cc
@@ -228,8 +228,8 @@ scoped_ptr<gpu::GLInProcessContext> context = CreateTestInProcessContext(); GLES2Interface* gl = context->GetImplementation(); - if (texture_mailbox.sync_point()) - gl->WaitSyncPointCHROMIUM(texture_mailbox.sync_point()); + if (texture_mailbox.sync_token().HasData()) + gl->WaitSyncTokenCHROMIUM(texture_mailbox.sync_token().GetConstData()); GLuint texture_id = 0; gl->GenTextures(1, &texture_id);
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc index 55c0b033..9f03a8c74 100644 --- a/cc/test/layer_tree_test.cc +++ b/cc/test/layer_tree_test.cc
@@ -181,6 +181,11 @@ test_hooks_->SendBeginMainFrameNotExpectedSoon(); } + void DidActivateSyncTree() override { + ThreadProxy::DidActivateSyncTree(); + test_hooks_->DidActivateSyncTree(); + } + void SetThrottleFrameProductionOnImpl(bool throttle) override { ThreadProxy::SetThrottleFrameProductionOnImpl(throttle); test_hooks_->SetThrottleFrameProductionOnImpl(throttle); @@ -248,11 +253,25 @@ test_hooks_->FinishGLOnImpl(); } - void StartCommitOnImpl(CompletionEvent* completion) override { - ThreadProxy::StartCommitOnImpl(completion); + void StartCommitOnImpl(CompletionEvent* completion, + LayerTreeHost* layer_tree_host, + bool hold_commit_for_activation) override { + ThreadProxy::StartCommitOnImpl(completion, layer_tree_host, + hold_commit_for_activation); test_hooks_->StartCommitOnImpl(); } + void InitializeImplOnImpl(CompletionEvent* completion, + LayerTreeHost* layer_tree_host) override { + ThreadProxy::InitializeImplOnImpl(completion, layer_tree_host); + test_hooks_->InitializeImplOnImpl(); + } + + void LayerTreeHostClosedOnImpl(CompletionEvent* completion) override { + test_hooks_->WillCloseLayerTreeHostOnImpl(); + ThreadProxy::LayerTreeHostClosedOnImpl(completion); + } + void DidCompleteSwapBuffers() override { ThreadProxy::DidCompleteSwapBuffers(); test_hooks_->ReceivedDidCompleteSwapBuffers();
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h index 85f4021..33593aa 100644 --- a/cc/test/layer_tree_test.h +++ b/cc/test/layer_tree_test.h
@@ -108,6 +108,7 @@ bool visible) {} virtual void ScheduleComposite() {} virtual void DidSetNeedsUpdateLayers() {} + virtual void DidActivateSyncTree() {} // Hooks for SchedulerClient. virtual void ScheduledActionWillSendBeginMainFrame() {} @@ -138,6 +139,8 @@ virtual void ReleaseOutputSurfaceOnImpl() {} virtual void FinishGLOnImpl() {} virtual void StartCommitOnImpl() {} + virtual void InitializeImplOnImpl() {} + virtual void WillCloseLayerTreeHostOnImpl() {} // Hooks for ProxyMain virtual void ReceivedDidCompleteSwapBuffers() {}
diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc index 75e4ea1..36a113f 100644 --- a/cc/test/pixel_test.cc +++ b/cc/test/pixel_test.cc
@@ -136,6 +136,7 @@ resource_provider_ = ResourceProvider::Create( output_surface_.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, 1, + settings_.renderer_settings.use_gpu_memory_buffer_resources, settings_.use_image_texture_targets); texture_mailbox_deleter_ = make_scoped_ptr( @@ -177,6 +178,7 @@ resource_provider_ = ResourceProvider::Create( output_surface_.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, 1, + settings_.renderer_settings.use_gpu_memory_buffer_resources, settings_.use_image_texture_targets); renderer_ = SoftwareRenderer::Create(this, &settings_.renderer_settings,
diff --git a/cc/test/render_pass_test_utils.cc b/cc/test/render_pass_test_utils.cc index 5a120ed..f65ff07 100644 --- a/cc/test/render_pass_test_utils.cc +++ b/cc/test/render_pass_test_utils.cc
@@ -143,21 +143,21 @@ FilterOperations()); } -static void EmptyReleaseCallback(uint32 sync_point, +static void EmptyReleaseCallback(const gpu::SyncToken& sync_token, bool lost_resource, BlockingTaskRunner* main_thread_task_runner) {} void AddOneOfEveryQuadType(RenderPass* to_pass, ResourceProvider* resource_provider, RenderPassId child_pass, - uint32_t* sync_point_for_mailbox_texture_quad) { + uint32_t* sync_point_for_mailbox_texture) { gfx::Rect rect(0, 0, 100, 100); gfx::Rect opaque_rect(10, 10, 80, 80); gfx::Rect visible_rect(0, 0, 100, 100); const float vertex_opacity[] = {1.0f, 1.0f, 1.0f, 1.0f}; - static const uint32_t kSyncPointForMailboxTextureQuad = 30; - *sync_point_for_mailbox_texture_quad = kSyncPointForMailboxTextureQuad; + static const uint32_t kSyncTokenForMailboxTextureQuad = 30; + *sync_point_for_mailbox_texture = kSyncTokenForMailboxTextureQuad; ResourceId resource1 = resource_provider->CreateResource( gfx::Size(45, 5), ResourceProvider::TEXTURE_HINT_IMMUTABLE, @@ -194,8 +194,8 @@ memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); scoped_ptr<SingleReleaseCallbackImpl> callback = SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)); - TextureMailbox mailbox(gpu_mailbox, target, - *sync_point_for_mailbox_texture_quad); + TextureMailbox mailbox( + gpu_mailbox, gpu::SyncToken(*sync_point_for_mailbox_texture), target); ResourceId resource8 = resource_provider->CreateResourceFromTextureMailbox( mailbox, callback.Pass()); resource_provider->AllocateForTesting(resource8);
diff --git a/cc/test/render_pass_test_utils.h b/cc/test/render_pass_test_utils.h index 0f63643..b28bb04 100644 --- a/cc/test/render_pass_test_utils.h +++ b/cc/test/render_pass_test_utils.h
@@ -58,7 +58,7 @@ void AddOneOfEveryQuadType(RenderPass* to_pass, ResourceProvider* resource_provider, RenderPassId child_pass, - uint32_t* sync_point_for_mailbox_texture_quad); + uint32_t* sync_point_for_mailbox_texture); } // namespace cc
diff --git a/cc/test/test_gles2_interface.cc b/cc/test/test_gles2_interface.cc index 4b03ac84..4ebdfd3 100644 --- a/cc/test/test_gles2_interface.cc +++ b/cc/test/test_gles2_interface.cc
@@ -323,14 +323,14 @@ test_context_->bufferData(target, size, data, usage); } -void TestGLES2Interface::WaitSyncPointCHROMIUM(GLuint sync_point) { - test_context_->waitSyncPoint(sync_point); -} - GLuint TestGLES2Interface::InsertSyncPointCHROMIUM() { return test_context_->insertSyncPoint(); } +void TestGLES2Interface::WaitSyncTokenCHROMIUM(const GLbyte* sync_token) { + test_context_->waitSyncToken(sync_token); +} + void TestGLES2Interface::BeginQueryEXT(GLenum target, GLuint id) { test_context_->beginQueryEXT(target, id); }
diff --git a/cc/test/test_gles2_interface.h b/cc/test/test_gles2_interface.h index 5a36b5c8..20ab0079 100644 --- a/cc/test/test_gles2_interface.h +++ b/cc/test/test_gles2_interface.h
@@ -137,9 +137,10 @@ const void* data, GLenum usage) override; - void WaitSyncPointCHROMIUM(GLuint sync_point) override; GLuint InsertSyncPointCHROMIUM() override; + void WaitSyncTokenCHROMIUM(const GLbyte* sync_token) override; + void BeginQueryEXT(GLenum target, GLuint id) override; void EndQueryEXT(GLenum target) override; void GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint* params) override;
diff --git a/cc/test/test_web_graphics_context_3d.cc b/cc/test/test_web_graphics_context_3d.cc index 1e69bcb..d974ca9 100644 --- a/cc/test/test_web_graphics_context_3d.cc +++ b/cc/test/test_web_graphics_context_3d.cc
@@ -67,7 +67,6 @@ test_support_(NULL), last_update_type_(NO_UPDATE), next_insert_sync_point_(1), - last_waited_sync_point_(0), unpack_alignment_(4), bound_buffer_(0), weak_ptr_factory_(this) { @@ -651,9 +650,13 @@ return next_insert_sync_point_++; } -void TestWebGraphicsContext3D::waitSyncPoint(unsigned sync_point) { - if (sync_point) - last_waited_sync_point_ = sync_point; +void TestWebGraphicsContext3D::waitSyncToken(const GLbyte* sync_token) { + if (sync_token) { + gpu::SyncToken sync_token_data; + memcpy(sync_token_data.GetData(), sync_token, sizeof(sync_token_data)); + if (sync_token_data.HasData()) + last_waited_sync_token_ = sync_token_data; + } } size_t TestWebGraphicsContext3D::NumTextures() const {
diff --git a/cc/test/test_web_graphics_context_3d.h b/cc/test/test_web_graphics_context_3d.h index 9aabf0d..8fa44968 100644 --- a/cc/test/test_web_graphics_context_3d.h +++ b/cc/test/test_web_graphics_context_3d.h
@@ -19,6 +19,7 @@ #include "cc/output/context_provider.h" #include "cc/test/ordered_texture_map.h" #include "cc/test/test_texture.h" +#include "gpu/command_buffer/common/sync_token.h" #include "third_party/khronos/GLES2/gl2.h" #include "ui/gfx/geometry/rect.h" @@ -271,9 +272,11 @@ GLuint plane) {} virtual unsigned insertSyncPoint(); - virtual void waitSyncPoint(unsigned sync_point); + virtual void waitSyncToken(const GLbyte* sync_token); - unsigned last_waited_sync_point() const { return last_waited_sync_point_; } + const gpu::SyncToken& last_waited_sync_token() const { + return last_waited_sync_token_; + } const ContextProvider::Capabilities& test_capabilities() const { return test_capabilities_; @@ -473,7 +476,7 @@ gfx::Rect update_rect_; UpdateType last_update_type_; unsigned next_insert_sync_point_; - unsigned last_waited_sync_point_; + gpu::SyncToken last_waited_sync_token_; int unpack_alignment_; unsigned bound_buffer_;
diff --git a/cc/trees/channel_main.h b/cc/trees/channel_main.h index e41bebac..9c6689c1 100644 --- a/cc/trees/channel_main.h +++ b/cc/trees/channel_main.h
@@ -44,7 +44,12 @@ virtual void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) = 0; virtual void SetNeedsCommitOnImpl() = 0; virtual void BeginMainFrameAbortedOnImpl(CommitEarlyOutReason reason) = 0; - virtual void StartCommitOnImpl(CompletionEvent* completion) = 0; + virtual void StartCommitOnImpl(CompletionEvent* completion, + LayerTreeHost* layer_tree_host, + bool hold_commit_for_activation) = 0; + virtual void InitializeImplOnImpl(CompletionEvent* completion, + LayerTreeHost* layer_tree_host) = 0; + virtual void LayerTreeHostClosedOnImpl(CompletionEvent* completion) = 0; virtual ~ChannelMain() {} };
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 0590b35..bb63c28 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -2273,6 +2273,7 @@ task_runner_provider_->blocking_main_thread_task_runner(), settings_.renderer_settings.highp_threshold_min, settings_.renderer_settings.texture_id_allocation_chunk_size, + settings_.renderer_settings.use_gpu_memory_buffer_resources, settings_.use_image_texture_targets); CreateAndSetRenderer();
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 2f98767..dc94e6e 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -2385,6 +2385,40 @@ RunTest(LayerTreeSettings::THINNING); } +TEST_F(LayerTreeHostImplTest, ScrollbarInnerLargerThanOuter) { + LayerTreeSettings settings; + CreateHostImpl(settings, CreateOutputSurface()); + + gfx::Size inner_viewport_size(315, 200); + gfx::Size outer_viewport_size(300, 200); + gfx::Size content_size(1000, 1000); + + const int horiz_id = 11; + const int child_clip_id = 14; + const int child_scroll_id = 15; + + CreateScrollAndContentsLayers(host_impl_->active_tree(), content_size); + host_impl_->active_tree()->InnerViewportContainerLayer()->SetBounds( + inner_viewport_size); + host_impl_->active_tree()->OuterViewportContainerLayer()->SetBounds( + outer_viewport_size); + LayerImpl* root_scroll = + host_impl_->active_tree()->OuterViewportScrollLayer(); + scoped_ptr<SolidColorScrollbarLayerImpl> horiz_scrollbar = + SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), horiz_id, + HORIZONTAL, 5, 5, true, true); + scoped_ptr<LayerImpl> child = + LayerImpl::Create(host_impl_->active_tree(), child_scroll_id); + child->SetBounds(content_size); + scoped_ptr<LayerImpl> child_clip = + LayerImpl::Create(host_impl_->active_tree(), child_clip_id); + child->SetBounds(inner_viewport_size); + + horiz_scrollbar->SetScrollLayerId(root_scroll->id()); + + EXPECT_EQ(300, horiz_scrollbar->clip_layer_length()); +} + TEST_F(LayerTreeHostImplTest, ScrollbarRegistration) { LayerTreeSettings settings; settings.scrollbar_animator = LayerTreeSettings::LINEAR_FADE;
diff --git a/cc/trees/layer_tree_host_perftest.cc b/cc/trees/layer_tree_host_perftest.cc index 053f52a..ef4e3eb 100644 --- a/cc/trees/layer_tree_host_perftest.cc +++ b/cc/trees/layer_tree_host_perftest.cc
@@ -260,7 +260,8 @@ set_verify_property_trees(old_verify_property_trees); } -static void EmptyReleaseCallback(uint32 sync_point, bool lost_resource) {} +static void EmptyReleaseCallback(const gpu::SyncToken& sync_token, + bool lost_resource) {} // Simulates main-thread scrolling on each frame. class BrowserCompositorInvalidateLayerTreePerfTest @@ -292,7 +293,8 @@ reinterpret_cast<const int8*>(name_stream.str().c_str())); scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( base::Bind(&EmptyReleaseCallback)); - TextureMailbox mailbox(gpu_mailbox, GL_TEXTURE_2D, next_sync_point_); + TextureMailbox mailbox(gpu_mailbox, gpu::SyncToken(next_sync_point_), + GL_TEXTURE_2D); next_sync_point_++; tab_contents_->SetTextureMailbox(mailbox, callback.Pass());
diff --git a/cc/trees/layer_tree_host_pixeltest_readback.cc b/cc/trees/layer_tree_host_pixeltest_readback.cc index b65feccda..c35d66b7 100644 --- a/cc/trees/layer_tree_host_pixeltest_readback.cc +++ b/cc/trees/layer_tree_host_pixeltest_readback.cc
@@ -123,7 +123,7 @@ scoped_ptr<SkBitmap> bitmap = CopyTextureMailboxToBitmap(result->size(), texture_mailbox); - release_callback->Run(0, false); + release_callback->Run(gpu::SyncToken(), false); ReadbackResultAsBitmap(CopyOutputResult::CreateBitmapResult(bitmap.Pass())); }
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc index 624009d..51472759 100644 --- a/cc/trees/layer_tree_host_unittest_context.cc +++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -910,7 +910,8 @@ child_output_surface_.get(), shared_bitmap_manager_.get()); } - static void EmptyReleaseCallback(unsigned sync_point, bool lost) {} + static void EmptyReleaseCallback(const gpu::SyncToken& sync_token, + bool lost) {} void SetupTree() override { gpu::gles2::GLES2Interface* gl = @@ -949,7 +950,7 @@ gpu::Mailbox mailbox; gl->GenMailboxCHROMIUM(mailbox.name); - GLuint sync_point = gl->InsertSyncPointCHROMIUM(); + gpu::SyncToken sync_token(gl->InsertSyncPointCHROMIUM()); scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(10, 10)); @@ -973,10 +974,10 @@ texture->SetBounds(gfx::Size(10, 10)); texture->SetIsDrawable(true); texture->SetTextureMailbox( - TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), + TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D), SingleReleaseCallback::Create( base::Bind(&LayerTreeHostContextTestDontUseLostResources:: - EmptyReleaseCallback))); + EmptyReleaseCallback))); root->AddChild(texture); scoped_refptr<PictureLayer> mask = @@ -1012,12 +1013,12 @@ gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta()); hw_video_frame_ = VideoFrame::WrapNativeTexture( media::PIXEL_FORMAT_ARGB, - gpu::MailboxHolder(mailbox, GL_TEXTURE_2D, sync_point), + gpu::MailboxHolder(mailbox, sync_token, GL_TEXTURE_2D), media::VideoFrame::ReleaseMailboxCB(), gfx::Size(4, 4), gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4), base::TimeDelta()); scaled_hw_video_frame_ = VideoFrame::WrapNativeTexture( media::PIXEL_FORMAT_ARGB, - gpu::MailboxHolder(mailbox, GL_TEXTURE_2D, sync_point), + gpu::MailboxHolder(mailbox, sync_token, GL_TEXTURE_2D), media::VideoFrame::ReleaseMailboxCB(), gfx::Size(4, 4), gfx::Rect(0, 0, 3, 2), gfx::Size(4, 4), base::TimeDelta());
diff --git a/cc/trees/layer_tree_host_unittest_copyrequest.cc b/cc/trees/layer_tree_host_unittest_copyrequest.cc index 9ca6256f..802a014 100644 --- a/cc/trees/layer_tree_host_unittest_copyrequest.cc +++ b/cc/trees/layer_tree_host_unittest_copyrequest.cc
@@ -728,7 +728,7 @@ void BeginTest() override { num_textures_without_readback_ = 0; num_textures_with_readback_ = 0; - waited_sync_point_after_readback_ = 0; + waited_sync_token_after_readback_.Clear(); PostSetNeedsCommitToMainThread(); } @@ -755,8 +755,8 @@ // We did a readback, so there will be a readback texture around now. num_textures_with_readback_ = context_provider_->TestContext3d()->NumTextures(); - waited_sync_point_after_readback_ = - context_provider_->TestContext3d()->last_waited_sync_point(); + waited_sync_token_after_readback_ = + context_provider_->TestContext3d()->last_waited_sync_token(); MainThreadTaskRunner()->PostTask( FROM_HERE, @@ -771,7 +771,7 @@ scoped_refptr<TestContextProvider> context_provider_; size_t num_textures_without_readback_; size_t num_textures_with_readback_; - unsigned waited_sync_point_after_readback_; + gpu::SyncToken waited_sync_token_after_readback_; FakeContentLayerClient client_; scoped_refptr<FakePictureLayer> root_; scoped_refptr<FakePictureLayer> copy_layer_; @@ -797,12 +797,12 @@ result->TakeTexture(&mailbox, &release); EXPECT_TRUE(release); - release->Run(0, false); + release->Run(gpu::SyncToken(), false); } void AfterTest() override { // No sync point was needed. - EXPECT_EQ(0u, waited_sync_point_after_readback_); + EXPECT_FALSE(waited_sync_token_after_readback_.HasData()); // Except the copy to have made another texture. EXPECT_EQ(num_textures_without_readback_ + 1, num_textures_with_readback_); } @@ -841,9 +841,9 @@ gpu::gles2::GLES2Interface* gl = external_context_provider_->ContextGL(); gpu::Mailbox mailbox; gl->GenMailboxCHROMIUM(mailbox.name); - sync_point_ = gl->InsertSyncPointCHROMIUM(); + sync_token_ = gpu::SyncToken(gl->InsertSyncPointCHROMIUM()); request->SetTextureMailbox( - TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point_)); + TextureMailbox(mailbox, sync_token_, GL_TEXTURE_2D)); EXPECT_TRUE(request->has_texture_mailbox()); copy_layer_->RequestCopyOfOutput(request.Pass()); @@ -852,13 +852,13 @@ void AfterTest() override { // Expect the compositor to have waited for the sync point in the provided // TextureMailbox. - EXPECT_EQ(sync_point_, waited_sync_point_after_readback_); + EXPECT_EQ(sync_token_, waited_sync_token_after_readback_); // Except the copy to have *not* made another texture. EXPECT_EQ(num_textures_without_readback_, num_textures_with_readback_); } scoped_refptr<TestContextProvider> external_context_provider_; - unsigned sync_point_; + gpu::SyncToken sync_token_; }; SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
diff --git a/cc/trees/layer_tree_host_unittest_proxy.cc b/cc/trees/layer_tree_host_unittest_proxy.cc index d4057cf..370760e0 100644 --- a/cc/trees/layer_tree_host_unittest_proxy.cc +++ b/cc/trees/layer_tree_host_unittest_proxy.cc
@@ -287,4 +287,66 @@ THREAD_PROXY_TEST_F(ThreadProxyTestSetNeedsCommitWhileAnimating); +class ThreadProxyTestCommitWaitsForActivation : public ThreadProxyTest { + protected: + ThreadProxyTestCommitWaitsForActivation() : commits_completed_(0) {} + ~ThreadProxyTestCommitWaitsForActivation() override {} + + void BeginTest() override { proxy()->SetNeedsCommit(); } + + void ScheduledActionCommit() override { + switch (commits_completed_) { + case 0: + // The first commit does not wait for activation. Verify that the + // completion event is cleared. + EXPECT_FALSE(ThreadProxyImplOnly().commit_completion_event); + EXPECT_FALSE(ThreadProxyImplOnly().next_commit_waits_for_activation); + break; + case 1: + // The second commit should be held until activation. + EXPECT_TRUE(ThreadProxyImplOnly().commit_completion_event); + EXPECT_TRUE(ThreadProxyImplOnly().next_commit_waits_for_activation); + break; + case 2: + // The third commit should not wait for activation. + EXPECT_FALSE(ThreadProxyImplOnly().commit_completion_event); + EXPECT_FALSE(ThreadProxyImplOnly().next_commit_waits_for_activation); + } + } + + void DidActivateSyncTree() override { + // The next_commit_waits_for_activation should have been cleared after the + // sync tree is activated. + EXPECT_FALSE(ThreadProxyImplOnly().next_commit_waits_for_activation); + } + + void DidCommit() override { + switch (commits_completed_) { + case 0: + // The first commit has been completed. Set next commit waits for + // activation and start another commit. + commits_completed_++; + proxy()->SetNextCommitWaitsForActivation(); + proxy()->SetNeedsCommit(); + case 1: + // Start another commit to verify that this is not held until + // activation. + commits_completed_++; + proxy()->SetNeedsCommit(); + case 2: + commits_completed_++; + EndTest(); + } + } + + void AfterTest() override { EXPECT_EQ(3, commits_completed_); } + + private: + int commits_completed_; + + DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestCommitWaitsForActivation); +}; + +THREAD_PROXY_TEST_F(ThreadProxyTestCommitWaitsForActivation); + } // namespace cc
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 6ba1153b..c9b4dbc5a 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -177,6 +177,8 @@ gfx::ScrollOffset current_offset = scroll_layer->CurrentScrollOffset(); if (IsViewportLayerId(scroll_layer_id)) { current_offset += InnerViewportScrollLayer()->CurrentScrollOffset(); + if (OuterViewportContainerLayer()) + clip_size.SetToMin(OuterViewportContainerLayer()->BoundsForScrolling()); clip_size.Scale(1 / current_page_scale_factor()); }
diff --git a/cc/trees/proxy_impl.h b/cc/trees/proxy_impl.h index e33ca157..b2f4cd1 100644 --- a/cc/trees/proxy_impl.h +++ b/cc/trees/proxy_impl.h
@@ -43,7 +43,12 @@ virtual void MainFrameWillHappenOnImplForTesting( CompletionEvent* completion, bool* main_frame_will_happen) = 0; - virtual void StartCommitOnImpl(CompletionEvent* completion) = 0; + virtual void StartCommitOnImpl(CompletionEvent* completion, + LayerTreeHost* layer_tree_host, + bool hold_commit_for_activation) = 0; + virtual void InitializeImplOnImpl(CompletionEvent* completion, + LayerTreeHost* layer_tree_host) = 0; + virtual void LayerTreeHostClosedOnImpl(CompletionEvent* completion) = 0; // TODO(khushalsagar): Rename as GetWeakPtr() once ThreadProxy is split. virtual base::WeakPtr<ProxyImpl> GetImplWeakPtr() = 0;
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc index 1abb4c5..c50736a 100644 --- a/cc/trees/thread_proxy.cc +++ b/cc/trees/thread_proxy.cc
@@ -62,8 +62,7 @@ scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner, scoped_ptr<BeginFrameSource> external_begin_frame_source) : Proxy(main_task_runner, impl_task_runner), - main_thread_only_vars_unsafe_(this, layer_tree_host->id()), - main_thread_or_blocked_vars_unsafe_(layer_tree_host), + main_thread_only_vars_unsafe_(this, layer_tree_host), compositor_thread_vars_unsafe_( this, layer_tree_host->id(), @@ -71,7 +70,7 @@ external_begin_frame_source.Pass()) { TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy"); DCHECK(IsMainThread()); - DCHECK(this->layer_tree_host()); + DCHECK(this->main().layer_tree_host); // TODO(khushalsagar): Move this to LayerTreeHost#InitializeThreaded once // ThreadProxy is split. LayerTreeHost creates the channel and passes it to // ProxyMain#SetChannel. @@ -79,11 +78,13 @@ } ThreadProxy::MainThreadOnly::MainThreadOnly(ThreadProxy* proxy, - int layer_tree_host_id) - : layer_tree_host_id(layer_tree_host_id), + LayerTreeHost* layer_tree_host) + : layer_tree_host_id(layer_tree_host->id()), + layer_tree_host(layer_tree_host), max_requested_pipeline_stage(NO_PIPELINE_STAGE), current_pipeline_stage(NO_PIPELINE_STAGE), final_pipeline_stage(NO_PIPELINE_STAGE), + commit_waits_for_activation(false), started(false), prepare_tiles_pending(false), defer_commits(false), @@ -91,13 +92,10 @@ ThreadProxy::MainThreadOnly::~MainThreadOnly() {} -ThreadProxy::MainThreadOrBlockedMainThread::MainThreadOrBlockedMainThread( - LayerTreeHost* host) - : layer_tree_host(host), - commit_waits_for_activation(false), - main_thread_inside_commit(false) {} +ThreadProxy::BlockedMainCommitOnly::BlockedMainCommitOnly() + : layer_tree_host(nullptr) {} -ThreadProxy::MainThreadOrBlockedMainThread::~MainThreadOrBlockedMainThread() {} +ThreadProxy::BlockedMainCommitOnly::~BlockedMainCommitOnly() {} ThreadProxy::CompositorThreadOnly::CompositorThreadOnly( ThreadProxy* proxy, @@ -105,8 +103,8 @@ RenderingStatsInstrumentation* rendering_stats_instrumentation, scoped_ptr<BeginFrameSource> external_begin_frame_source) : layer_tree_host_id(layer_tree_host_id), + next_commit_waits_for_activation(false), commit_completion_event(nullptr), - completion_event_for_commit_held_on_tree_activation(nullptr), next_frame_is_newly_committed_frame(false), inside_draw(false), input_throttled_until_commit(false), @@ -180,12 +178,12 @@ void ThreadProxy::DidLoseOutputSurface() { TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurface"); DCHECK(IsMainThread()); - layer_tree_host()->DidLoseOutputSurface(); + main().layer_tree_host->DidLoseOutputSurface(); } void ThreadProxy::RequestNewOutputSurface() { DCHECK(IsMainThread()); - layer_tree_host()->RequestNewOutputSurface(); + main().layer_tree_host->RequestNewOutputSurface(); } void ThreadProxy::SetOutputSurface(OutputSurface* output_surface) { @@ -194,7 +192,7 @@ void ThreadProxy::ReleaseOutputSurface() { DCHECK(IsMainThread()); - DCHECK(layer_tree_host()->output_surface_lost()); + DCHECK(main().layer_tree_host->output_surface_lost()); DebugScopedSetMainThreadBlocked main_thread_blocked(this); CompletionEvent completion; @@ -209,11 +207,11 @@ DCHECK(IsMainThread()); if (!success) { - layer_tree_host()->DidFailToInitializeOutputSurface(); + main().layer_tree_host->DidFailToInitializeOutputSurface(); return; } main().renderer_capabilities_main_thread_copy = capabilities; - layer_tree_host()->DidInitializeOutputSurface(); + main().layer_tree_host->DidInitializeOutputSurface(); } void ThreadProxy::SetRendererCapabilitiesMainCopy( @@ -241,12 +239,12 @@ void ThreadProxy::DidCompletePageScaleAnimation() { DCHECK(IsMainThread()); - layer_tree_host()->DidCompletePageScaleAnimation(); + main().layer_tree_host->DidCompletePageScaleAnimation(); } const RendererCapabilities& ThreadProxy::GetRendererCapabilities() const { DCHECK(IsMainThread()); - DCHECK(!layer_tree_host()->output_surface_lost()); + DCHECK(!main().layer_tree_host->output_surface_lost()); return main().renderer_capabilities_main_thread_copy; } @@ -403,8 +401,7 @@ void ThreadProxy::SetNextCommitWaitsForActivation() { DCHECK(IsMainThread()); - DCHECK(!blocked_main().main_thread_inside_commit); - blocked_main().commit_waits_for_activation = true; + main().commit_waits_for_activation = true; } void ThreadProxy::SetDeferCommits(bool defer_commits) { @@ -485,14 +482,6 @@ RenewTreePriority(); } -LayerTreeHost* ThreadProxy::layer_tree_host() { - return blocked_main().layer_tree_host; -} - -const LayerTreeHost* ThreadProxy::layer_tree_host() const { - return blocked_main().layer_tree_host; -} - ThreadProxy::MainThreadOnly& ThreadProxy::main() { DCHECK(IsMainThread()); return main_thread_only_vars_unsafe_; @@ -502,15 +491,10 @@ return main_thread_only_vars_unsafe_; } -ThreadProxy::MainThreadOrBlockedMainThread& ThreadProxy::blocked_main() { - DCHECK(IsMainThread() || IsMainThreadBlocked()); - return main_thread_or_blocked_vars_unsafe_; -} - -const ThreadProxy::MainThreadOrBlockedMainThread& ThreadProxy::blocked_main() - const { - DCHECK(IsMainThread() || IsMainThreadBlocked()); - return main_thread_or_blocked_vars_unsafe_; +ThreadProxy::BlockedMainCommitOnly& ThreadProxy::blocked_main_commit() { + DCHECK(IsMainThreadBlocked()); + DCHECK(impl().commit_completion_event); + return main_thread_blocked_commit_vars_unsafe_; } ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() { @@ -530,11 +514,8 @@ // Create LayerTreeHostImpl. DebugScopedSetMainThreadBlocked main_thread_blocked(this); CompletionEvent completion; - Proxy::ImplThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ThreadProxy::InitializeImplOnImplThread, - base::Unretained(this), - &completion)); + main().channel_main->InitializeImplOnImpl(&completion, + main().layer_tree_host); completion.Wait(); main_thread_weak_ptr_ = main().weak_factory.GetWeakPtr(); @@ -561,16 +542,12 @@ DebugScopedSetMainThreadBlocked main_thread_blocked(this); CompletionEvent completion; - Proxy::ImplThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ThreadProxy::LayerTreeHostClosedOnImplThread, - impl_thread_weak_ptr_, - &completion)); + main().channel_main->LayerTreeHostClosedOnImpl(&completion); completion.Wait(); } main().weak_factory.InvalidateWeakPtrs(); - blocked_main().layer_tree_host = NULL; + main().layer_tree_host = nullptr; main().started = false; } @@ -633,19 +610,19 @@ // If the commit finishes, LayerTreeHost will transfer its swap promises to // LayerTreeImpl. The destructor of ScopedSwapPromiseChecker aborts the // remaining swap promises. - ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host()); + ScopedAbortRemainingSwapPromises swap_promise_checker(main().layer_tree_host); main().final_pipeline_stage = main().max_requested_pipeline_stage; main().max_requested_pipeline_stage = NO_PIPELINE_STAGE; - if (!layer_tree_host()->visible()) { + if (!main().layer_tree_host->visible()) { TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD); main().channel_main->BeginMainFrameAbortedOnImpl( CommitEarlyOutReason::ABORTED_NOT_VISIBLE); return; } - if (layer_tree_host()->output_surface_lost()) { + if (main().layer_tree_host->output_surface_lost()) { TRACE_EVENT_INSTANT0( "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD); main().channel_main->BeginMainFrameAbortedOnImpl( @@ -655,21 +632,22 @@ main().current_pipeline_stage = ANIMATE_PIPELINE_STAGE; - layer_tree_host()->ApplyScrollAndScale( + main().layer_tree_host->ApplyScrollAndScale( begin_main_frame_state->scroll_info.get()); - layer_tree_host()->WillBeginMainFrame(); + main().layer_tree_host->WillBeginMainFrame(); - layer_tree_host()->BeginMainFrame(begin_main_frame_state->begin_frame_args); - layer_tree_host()->AnimateLayers( + main().layer_tree_host->BeginMainFrame( + begin_main_frame_state->begin_frame_args); + main().layer_tree_host->AnimateLayers( begin_main_frame_state->begin_frame_args.frame_time); // Recreate all UI resources if there were evicted UI resources when the impl // thread initiated the commit. if (begin_main_frame_state->evicted_ui_resources) - layer_tree_host()->RecreateUIResources(); + main().layer_tree_host->RecreateUIResources(); - layer_tree_host()->RequestMainFrameUpdate(); + main().layer_tree_host->RequestMainFrameUpdate(); TRACE_EVENT_SYNTHETIC_DELAY_END("cc.BeginMainFrame"); bool can_cancel_this_commit = @@ -679,11 +657,11 @@ main().current_pipeline_stage = UPDATE_LAYERS_PIPELINE_STAGE; bool should_update_layers = main().final_pipeline_stage >= UPDATE_LAYERS_PIPELINE_STAGE; - bool updated = should_update_layers && layer_tree_host()->UpdateLayers(); + bool updated = should_update_layers && main().layer_tree_host->UpdateLayers(); - layer_tree_host()->WillCommit(); + main().layer_tree_host->WillCommit(); devtools_instrumentation::ScopedCommitTrace commit_task( - layer_tree_host()->id()); + main().layer_tree_host->id()); main().current_pipeline_stage = COMMIT_PIPELINE_STAGE; if (!updated && can_cancel_this_commit) { @@ -695,9 +673,9 @@ // detected to be a no-op. From the perspective of an embedder, this commit // went through, and input should no longer be throttled, etc. main().current_pipeline_stage = NO_PIPELINE_STAGE; - layer_tree_host()->CommitComplete(); - layer_tree_host()->DidBeginMainFrame(); - layer_tree_host()->BreakSwapPromises(SwapPromise::COMMIT_NO_UPDATE); + main().layer_tree_host->CommitComplete(); + main().layer_tree_host->DidBeginMainFrame(); + main().layer_tree_host->BreakSwapPromises(SwapPromise::COMMIT_NO_UPDATE); return; } @@ -717,28 +695,39 @@ blocking_main_thread_task_runner()); CompletionEvent completion; - main().channel_main->StartCommitOnImpl(&completion); + main().channel_main->StartCommitOnImpl(&completion, main().layer_tree_host, + main().commit_waits_for_activation); completion.Wait(); + main().commit_waits_for_activation = false; } main().current_pipeline_stage = NO_PIPELINE_STAGE; - layer_tree_host()->CommitComplete(); - layer_tree_host()->DidBeginMainFrame(); + main().layer_tree_host->CommitComplete(); + main().layer_tree_host->DidBeginMainFrame(); } void ThreadProxy::BeginMainFrameNotExpectedSoon() { TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrameNotExpectedSoon"); DCHECK(IsMainThread()); - layer_tree_host()->BeginMainFrameNotExpectedSoon(); + main().layer_tree_host->BeginMainFrameNotExpectedSoon(); } -void ThreadProxy::StartCommitOnImpl(CompletionEvent* completion) { +void ThreadProxy::StartCommitOnImpl(CompletionEvent* completion, + LayerTreeHost* layer_tree_host, + bool hold_commit_for_activation) { TRACE_EVENT0("cc", "ThreadProxy::StartCommitOnImplThread"); DCHECK(!impl().commit_completion_event); DCHECK(IsImplThread() && IsMainThreadBlocked()); DCHECK(impl().scheduler); DCHECK(impl().scheduler->CommitPending()); + if (hold_commit_for_activation) { + // This commit may be aborted. Store the value for + // hold_commit_for_activation so that whenever the next commit is started, + // the main thread will be unblocked only after pending tree activation. + impl().next_commit_waits_for_activation = hold_commit_for_activation; + } + if (!impl().layer_tree_host_impl) { TRACE_EVENT_INSTANT0( "cc", "EarlyOut_NoLayerTree", TRACE_EVENT_SCOPE_THREAD); @@ -750,6 +739,8 @@ // But, we can avoid a PostTask in here. impl().scheduler->NotifyBeginMainFrameStarted(); impl().commit_completion_event = completion; + DCHECK(!blocked_main_commit().layer_tree_host); + blocked_main_commit().layer_tree_host = layer_tree_host; impl().scheduler->NotifyReadyToCommit(); } @@ -782,24 +773,23 @@ DCHECK(IsImplThread()); DCHECK(IsMainThreadBlocked()); DCHECK(impl().commit_completion_event); + DCHECK(blocked_main_commit().layer_tree_host); - blocked_main().main_thread_inside_commit = true; impl().layer_tree_host_impl->BeginCommit(); - layer_tree_host()->FinishCommitOnImplThread( + blocked_main_commit().layer_tree_host->FinishCommitOnImplThread( impl().layer_tree_host_impl.get()); - blocked_main().main_thread_inside_commit = false; - bool hold_commit = blocked_main().commit_waits_for_activation; - blocked_main().commit_waits_for_activation = false; + // Remove the LayerTreeHost reference before the completion event is signaled + // and cleared. This is necessary since blocked_main_commit() allows access + // only while we have the completion event to ensure the main thread is + // blocked for a commit. + blocked_main_commit().layer_tree_host = nullptr; - if (hold_commit) { + if (impl().next_commit_waits_for_activation) { // For some layer types in impl-side painting, the commit is held until // the sync tree is activated. It's also possible that the // sync tree has already activated if there was no work to be done. TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD); - impl().completion_event_for_commit_held_on_tree_activation = - impl().commit_completion_event; - impl().commit_completion_event = nullptr; } else { impl().commit_completion_event->Signal(); impl().commit_completion_event = nullptr; @@ -932,33 +922,35 @@ void ThreadProxy::DidCommitAndDrawFrame() { DCHECK(IsMainThread()); - layer_tree_host()->DidCommitAndDrawFrame(); + main().layer_tree_host->DidCommitAndDrawFrame(); } void ThreadProxy::DidCompleteSwapBuffers() { DCHECK(IsMainThread()); - layer_tree_host()->DidCompleteSwapBuffers(); + main().layer_tree_host->DidCompleteSwapBuffers(); } void ThreadProxy::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) { TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents"); DCHECK(IsMainThread()); - layer_tree_host()->SetAnimationEvents(events.Pass()); + main().layer_tree_host->SetAnimationEvents(events.Pass()); } -void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) { +void ThreadProxy::InitializeImplOnImpl(CompletionEvent* completion, + LayerTreeHost* layer_tree_host) { TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread"); DCHECK(IsImplThread()); + DCHECK(IsMainThreadBlocked()); + DCHECK(layer_tree_host); // TODO(khushalsagar): ThreadedChannel will create ProxyImpl here and pass a // reference to itself. impl().channel_impl = threaded_channel_.get(); - impl().layer_tree_host_impl = - layer_tree_host()->CreateLayerTreeHostImpl(this); + impl().layer_tree_host_impl = layer_tree_host->CreateLayerTreeHostImpl(this); SchedulerSettings scheduler_settings( - layer_tree_host()->settings().ToSchedulerSettings()); + layer_tree_host->settings().ToSchedulerSettings()); scoped_ptr<CompositorTimingHistory> compositor_timing_history( new CompositorTimingHistory(CompositorTimingHistory::RENDERER_UMA, @@ -1015,7 +1007,7 @@ completion->Signal(); } -void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent* completion) { +void ThreadProxy::LayerTreeHostClosedOnImpl(CompletionEvent* completion) { TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread"); DCHECK(IsImplThread()); DCHECK(IsMainThreadBlocked()); @@ -1119,11 +1111,13 @@ TRACE_EVENT0("cc", "ThreadProxy::DidActivateSyncTreeOnImplThread"); DCHECK(IsImplThread()); - if (impl().completion_event_for_commit_held_on_tree_activation) { + if (impl().next_commit_waits_for_activation) { TRACE_EVENT_INSTANT0( "cc", "ReleaseCommitbyActivation", TRACE_EVENT_SCOPE_THREAD); - impl().completion_event_for_commit_held_on_tree_activation->Signal(); - impl().completion_event_for_commit_held_on_tree_activation = nullptr; + DCHECK(impl().commit_completion_event); + impl().commit_completion_event->Signal(); + impl().commit_completion_event = nullptr; + impl().next_commit_waits_for_activation = false; } impl().last_processed_begin_main_frame_args = @@ -1177,8 +1171,8 @@ scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events, scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) { DCHECK(IsMainThread()); - layer_tree_host()->RecordFrameTimingEvents(composite_events.Pass(), - main_frame_events.Pass()); + main().layer_tree_host->RecordFrameTimingEvents(composite_events.Pass(), + main_frame_events.Pass()); } base::WeakPtr<ProxyMain> ThreadProxy::GetMainWeakPtr() {
diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h index 5138c3a..0b954bd 100644 --- a/cc/trees/thread_proxy.h +++ b/cc/trees/thread_proxy.h
@@ -62,11 +62,13 @@ }; struct MainThreadOnly { - MainThreadOnly(ThreadProxy* proxy, int layer_tree_host_id); + MainThreadOnly(ThreadProxy* proxy, LayerTreeHost* layer_tree_host); ~MainThreadOnly(); const int layer_tree_host_id; + LayerTreeHost* layer_tree_host; + // The furthest pipeline stage which has been requested for the next // commit. CommitPipelineStage max_requested_pipeline_stage; @@ -77,6 +79,8 @@ // |current_pipeline_stage| is set to a pipeline stage). CommitPipelineStage final_pipeline_stage; + bool commit_waits_for_activation; + bool started; bool prepare_tiles_pending; bool defer_commits; @@ -90,14 +94,11 @@ base::WeakPtrFactory<ThreadProxy> weak_factory; }; - // Accessed on the main thread, or when main thread is blocked. - struct MainThreadOrBlockedMainThread { - explicit MainThreadOrBlockedMainThread(LayerTreeHost* host); - ~MainThreadOrBlockedMainThread(); - + // Accessed on the impl thread when the main thread is blocked for a commit. + struct BlockedMainCommitOnly { + BlockedMainCommitOnly(); + ~BlockedMainCommitOnly(); LayerTreeHost* layer_tree_host; - bool commit_waits_for_activation; - bool main_thread_inside_commit; }; struct CompositorThreadOnly { @@ -112,15 +113,12 @@ scoped_ptr<Scheduler> scheduler; - // Set when the main thread is waiting on a - // ScheduledActionSendBeginMainFrame to be issued. - CompletionEvent* begin_main_frame_sent_completion_event; - - // Set when the main thread is waiting on a commit to complete. - CompletionEvent* commit_completion_event; - // Set when the main thread is waiting on a pending tree activation. - CompletionEvent* completion_event_for_commit_held_on_tree_activation; + bool next_commit_waits_for_activation; + + // Set when the main thread is waiting on a commit to complete or on a + // pending tree activation. + CompletionEvent* commit_completion_event; // Set when the next draw should post DidCommitAndDrawFrame to the main // thread. @@ -152,7 +150,6 @@ }; const MainThreadOnly& main() const; - const MainThreadOrBlockedMainThread& blocked_main() const; const CompositorThreadOnly& impl() const; // Proxy implementation @@ -292,7 +289,12 @@ void SetNeedsCommitOnImpl() override; void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) override; void BeginMainFrameAbortedOnImpl(CommitEarlyOutReason reason) override; - void StartCommitOnImpl(CompletionEvent* completion) override; + void StartCommitOnImpl(CompletionEvent* completion, + LayerTreeHost* layer_tree_host, + bool hold_commit_for_activation) override; + void InitializeImplOnImpl(CompletionEvent* completion, + LayerTreeHost* layer_tree_host) override; + void LayerTreeHostClosedOnImpl(CompletionEvent* completion) override; // Returns |true| if the request was actually sent, |false| if one was // already outstanding. @@ -302,20 +304,15 @@ // Called on impl thread. struct SchedulerStateRequest; - void InitializeImplOnImplThread(CompletionEvent* completion); - void LayerTreeHostClosedOnImplThread(CompletionEvent* completion); DrawResult DrawSwapInternal(bool forced_draw); - LayerTreeHost* layer_tree_host(); - const LayerTreeHost* layer_tree_host() const; - // Use accessors instead of this variable directly. MainThreadOnly main_thread_only_vars_unsafe_; MainThreadOnly& main(); // Use accessors instead of this variable directly. - MainThreadOrBlockedMainThread main_thread_or_blocked_vars_unsafe_; - MainThreadOrBlockedMainThread& blocked_main(); + BlockedMainCommitOnly main_thread_blocked_commit_vars_unsafe_; + BlockedMainCommitOnly& blocked_main_commit(); // Use accessors instead of this variable directly. CompositorThreadOnly compositor_thread_vars_unsafe_;
diff --git a/cc/trees/threaded_channel.cc b/cc/trees/threaded_channel.cc index 40c5ef2f..b723f8c 100644 --- a/cc/trees/threaded_channel.cc +++ b/cc/trees/threaded_channel.cc
@@ -92,10 +92,28 @@ proxy_impl_->GetImplWeakPtr(), damage_rect)); } -void ThreadedChannel::StartCommitOnImpl(CompletionEvent* completion) { +void ThreadedChannel::StartCommitOnImpl(CompletionEvent* completion, + LayerTreeHost* layer_tree_host, + bool hold_commit_for_activation) { ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::StartCommitOnImpl, + FROM_HERE, + base::Bind(&ProxyImpl::StartCommitOnImpl, proxy_impl_->GetImplWeakPtr(), + completion, layer_tree_host, hold_commit_for_activation)); +} + +void ThreadedChannel::InitializeImplOnImpl(CompletionEvent* completion, + LayerTreeHost* layer_tree_host) { + ImplThreadTaskRunner()->PostTask( + FROM_HERE, + base::Bind(&ProxyImpl::InitializeImplOnImpl, + base::Unretained(proxy_impl_), completion, layer_tree_host)); +} + +void ThreadedChannel::LayerTreeHostClosedOnImpl(CompletionEvent* completion) { + ImplThreadTaskRunner()->PostTask( + FROM_HERE, base::Bind(&ProxyImpl::LayerTreeHostClosedOnImpl, proxy_impl_->GetImplWeakPtr(), completion)); + proxy_impl_ = nullptr; } void ThreadedChannel::SetVisibleOnImpl(bool visible) {
diff --git a/cc/trees/threaded_channel.h b/cc/trees/threaded_channel.h index 76c75161..1a4b8b7 100644 --- a/cc/trees/threaded_channel.h +++ b/cc/trees/threaded_channel.h
@@ -96,7 +96,12 @@ void MainFrameWillHappenOnImplForTesting( CompletionEvent* completion, bool* main_frame_will_happen) override; - void StartCommitOnImpl(CompletionEvent* completion) override; + void StartCommitOnImpl(CompletionEvent* completion, + LayerTreeHost* layer_tree_host, + bool hold_commit_for_activation) override; + void InitializeImplOnImpl(CompletionEvent* completion, + LayerTreeHost* layer_tree_host) override; + void LayerTreeHostClosedOnImpl(CompletionEvent* completion) override; // ChannelImpl Implementation void DidCompleteSwapBuffers() override;
diff --git a/cc/trees/threaded_channel_unittest.cc b/cc/trees/threaded_channel_unittest.cc index 09c2322..6371f78 100644 --- a/cc/trees/threaded_channel_unittest.cc +++ b/cc/trees/threaded_channel_unittest.cc
@@ -45,6 +45,8 @@ class ThreadedChannelTestInitializationAndShutdown : public ThreadedChannelTest { + void InitializeImplOnImpl() override { calls_received_++; } + void SetVisibleOnImpl(bool visible) override { calls_received_++; } void ReceivedRequestNewOutputSurface() override { calls_received_++; } @@ -65,9 +67,10 @@ EndTest(); } + void WillCloseLayerTreeHostOnImpl() override { calls_received_++; } void FinishGLOnImpl() override { calls_received_++; } - void AfterTest() override { EXPECT_EQ(6, calls_received_); } + void AfterTest() override { EXPECT_EQ(8, calls_received_); } }; MULTI_THREAD_DIRECT_RENDERER_TEST_F(
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 4f3cd21..9ec7c75 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -110,10 +110,10 @@ "app/chrome_watcher_client_win.h", "app/chrome_watcher_command_line_win.cc", "app/chrome_watcher_command_line_win.h", - "app/client_util.cc", - "app/client_util.h", "app/kasko_client.cc", "app/kasko_client.h", + "app/main_dll_loader_win.cc", + "app/main_dll_loader_win.h", "app/signature_validator_win.cc", "app/signature_validator_win.h", "common/crash_keys.cc", @@ -123,7 +123,7 @@ deps += [ ":chrome_dll", ":chrome_exe_version", - ":image_pre_reader", + ":file_pre_reader", # 'chrome_nacl_win64" TODO(GYP) bug 512869 # '../win8/delegate_execute/delegate_execute.gyp:*', TODO(GYP) bug 512867 @@ -185,7 +185,7 @@ "//chrome/installer/util", "//content/public/app:both", ] - if (enable_plugins) { + if (enable_plugins && enable_pdf) { deps += [ "//pdf" ] } @@ -220,7 +220,7 @@ ":packed_resources", ] deps += [ - "//components/startup_metric_utils", + "//components/startup_metric_utils/browser", # Precompiled plugins that need to get copied to the output directory. # On Mac, internal plugins go inside the framework, so these @@ -370,7 +370,7 @@ ] } - if (enable_plugins && !is_multi_dll_chrome) { + if (enable_plugins && enable_pdf && !is_multi_dll_chrome) { deps += [ "//pdf" ] } } @@ -423,7 +423,7 @@ # }, # }], } - if (enable_plugins) { + if (enable_plugins && enable_pdf) { deps += [ "//pdf" ] } } @@ -517,10 +517,10 @@ output = "$target_gen_dir/other_version.rc" } - source_set("image_pre_reader") { + source_set("file_pre_reader") { sources = [ - "app/image_pre_reader_win.cc", - "app/image_pre_reader_win.h", + "app/file_pre_reader_win.cc", + "app/file_pre_reader_win.h", ] deps = [ "//base",
diff --git a/chrome/VERSION b/chrome/VERSION index 7e91d21..0035e287 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=48 MINOR=0 -BUILD=2554 +BUILD=2555 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 0152226..787582b 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -5,6 +5,7 @@ import("//build/config/android/config.gni") import("//build/config/android/rules.gni") import("//build_overrides/v8.gni") +import("//chrome/android/chrome_public_apk_tmpl.gni") import("//chrome/version.gni") import("//testing/test.gni") import("//third_party/icu/config.gni") @@ -161,6 +162,7 @@ srcjar_deps = [ ":chrome_android_java_enums_srcjar", + ":chrome_android_java_google_api_keys_srcjar", ":chrome_version_srcjar", ":custom_tabs_service_aidl", ":resource_id_javagen", @@ -182,6 +184,19 @@ # GYP: //chrome/chrome_browser.gypi:connection_security_levels_java # GYP: //chrome/chrome_browser.gypi:tab_load_status_java # GYP: //chrome/chrome_browser.gypi:infobar_action_type_java + +action("chrome_android_java_google_api_keys_srcjar") { + script = "//build/android/gyp/java_google_api_keys.py" + _output_path = "$target_gen_dir/$target_name.srcjar" + outputs = [ + _output_path, + ] + args = [ + "--srcjar", + rebase_path(_output_path, root_build_dir), + ] +} + java_cpp_enum("chrome_android_java_enums_srcjar") { sources = [ "//chrome/browser/android/activity_type_ids.h", @@ -232,8 +247,7 @@ "junit/src/org/chromium/chrome/browser/externalauth/ExternalAuthUtilsTest.java", "junit/src/org/chromium/chrome/browser/gcore/GoogleApiClientConnectionHelperTest.java", - # TODO(mlamouri): add the requirements dependencies for this test. - #"junit/src/org/chromium/chrome/browser/invalidations/InvalidationControllerTest.java", + "junit/src/org/chromium/chrome/browser/invalidations/InvalidationControllerTest.java", "junit/src/org/chromium/chrome/browser/media/remote/AbstractMediaRouteControllerTest.java", "junit/src/org/chromium/chrome/browser/media/remote/MediaUrlResolverTest.java", "junit/src/org/chromium/chrome/browser/media/remote/RemoteVideoInfoTest.java", @@ -250,8 +264,10 @@ "//base:base_java", "//base:base_java_test_support", "//base:base_junit_test_support", + "//components/invalidation/impl:java", "//sync:sync_java_test_support", "//sync/android:sync_java", + "//third_party/cacheinvalidation:cacheinvalidation_javalib", "//third_party/junit:hamcrest", "//third_party/android_tools:android_support_v7_mediarouter_java", google_play_services_library, @@ -341,11 +357,9 @@ ] } -chrome_public_apk_assets_dir = "$root_build_dir/chrome_public_apk_assets" - copy_ex("chrome_public_apk_assets") { clear_dir = true - dest = chrome_public_apk_assets_dir + dest = "$root_build_dir/chrome_public_apk_assets" sources = chrome_android_paks_gypi.chrome_android_pak_input_resources if (icu_use_data_file) { sources += [ "$root_build_dir/icudtl.dat" ] @@ -357,10 +371,8 @@ ] if (v8_use_external_startup_data) { - sources += [ - "$root_out_dir/natives_blob.bin", - "$root_out_dir/snapshot_blob.bin", - ] + renaming_sources = v8_external_startup_data_renaming_sources + renaming_destinations = v8_external_startup_data_renaming_destinations deps += [ "//v8" ] } @@ -412,7 +424,7 @@ #], } -android_apk("chrome_public_apk") { +chrome_public_apk_tmpl("chrome_public_apk") { version_name = "Developer Build" version_code = "1" android_manifest = get_target_outputs(":chrome_public_apk_manifest") @@ -420,10 +432,6 @@ apk_name = "ChromePublic" native_libs = [ "$root_build_dir/lib.stripped/libchrome_public.so" ] native_lib_version_rule = "//build/util:chrome_version_json" - _native_lib_file = - rebase_path("$root_gen_dir/CHROME_VERSION.json", root_out_dir) - native_lib_version_arg = "@FileArg($_native_lib_file:full-quoted)" - asset_location = chrome_public_apk_assets_dir deps = [ ":chrome_java",
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni new file mode 100644 index 0000000..ce8b74c0 --- /dev/null +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -0,0 +1,32 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") + +# GYP: //chrome/android/chrome_apk.gypi +template("chrome_public_apk_tmpl") { + forward_variables_from(invoker, "*") + + android_apk(target_name) { + asset_location = "$root_build_dir/chrome_public_apk_assets" + _native_lib_file = + rebase_path("$root_gen_dir/CHROME_VERSION.json", root_out_dir) + native_lib_version_arg = "@FileArg($_native_lib_file:full-quoted)" + + # TODO(GYP): + #'proguard_enabled': 'true', + #'proguard_flags_paths': [ + # 'chrome/android/java/proguard.flags', + #] + + if (chromium_linker_supported) { + use_chromium_linker = true + + # TODO: Enable packed relocations for x64. See: b/20532404 + if (current_cpu != "x64") { + enable_relocation_packing = true + } + } + } +}
diff --git a/chrome/android/java/res/raw/google_icon_sprite.json b/chrome/android/java/res/raw/google_icon_sprite.json index 2b61a15..e4948a8 100644 --- a/chrome/android/java/res/raw/google_icon_sprite.json +++ b/chrome/android/java/res/raw/google_icon_sprite.json
@@ -1,5 +1,7 @@ { "apiVersion": "1.0", + "scaledSpriteWidthDp": 36, + "scaledSpriteHeightDp": 36, "densities": [ {
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml index 8d4fd46..fff9518 100644 --- a/chrome/android/java/res/values/dimens.xml +++ b/chrome/android/java/res/values/dimens.xml
@@ -77,9 +77,6 @@ <dimen name="contextual_search_text_size">18sp</dimen> <dimen name="contextual_search_peek_promo_height">48dp</dimen> <dimen name="contextual_search_peek_promo_padding">12dp</dimen> - <!-- TODO(twellington): Consider moving this to the JSON sprite metadata and - scaling the sprite in contextual_search_layer.cc --> - <dimen name="contextual_search_sprite_size">36dp</dimen> <!-- Password generation popup dimensions --> <dimen name="password_generation_divider_height">1dp</dimen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index 7af664fc..e71c16e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -46,7 +46,6 @@ import org.chromium.base.CommandLine; import org.chromium.base.Log; import org.chromium.base.SysUtils; -import org.chromium.base.ThreadUtils; import org.chromium.base.TraceEvent; import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.RecordHistogram; @@ -121,7 +120,6 @@ import org.chromium.chrome.browser.webapps.AddToHomescreenDialog; import org.chromium.chrome.browser.widget.ControlContainer; import org.chromium.content.browser.ContentReadbackHandler; -import org.chromium.content.browser.ContentReadbackHandler.GetBitmapCallback; import org.chromium.content.browser.ContentVideoView; import org.chromium.content.browser.ContentViewCore; import org.chromium.content.common.ContentSwitches; @@ -874,13 +872,12 @@ * This creates and shows a share intent picker dialog or starts a share intent directly. * * @param currentTab The {@link Tab} a user is watching. - * @param windowAndroid The {@link WindowAndroid} currentTab is linked to. * @param shareDirectly Whether it should share directly with the activity that was most * recently used to share. * @param isIncognito Whether currentTab is incognito. */ public void onShareMenuItemSelected(final Tab currentTab, - final WindowAndroid windowAndroid, final boolean shareDirectly, boolean isIncognito) { + final boolean shareDirectly, boolean isIncognito) { if (currentTab == null) return; final Activity mainActivity = this; @@ -898,8 +895,7 @@ } }; ContentReadbackHandler readbackHandler = getContentReadbackHandler(); - if (isIncognito || readbackHandler == null || windowAndroid == null - || currentTab.getContentViewCore() == null) { + if (isIncognito || readbackHandler == null || currentTab.getContentViewCore() == null) { bitmapCallback.onFinishGetBitmap(null, ReadbackResponse.SURFACE_UNAVAILABLE); } else { readbackHandler.getContentBitmapAsync(1, new Rect(), currentTab.getContentViewCore(), @@ -1174,24 +1170,6 @@ } /** - * Starts asynchronously taking the compositor activity screenshot. - * @param getBitmapCallback The callback to call once the screenshot is taken, or when failed. - */ - public void startTakingCompositorActivityScreenshot(final GetBitmapCallback getBitmapCallback) { - ContentReadbackHandler readbackHandler = getContentReadbackHandler(); - if (readbackHandler == null || getWindowAndroid() == null) { - ThreadUtils.postOnUiThread(new Runnable() { - @Override - public void run() { - getBitmapCallback.onFinishGetBitmap(null, ReadbackResponse.SURFACE_UNAVAILABLE); - } - }); - } else { - readbackHandler.getCompositorBitmapAsync(getWindowAndroid(), getBitmapCallback); - } - } - - /** * @return The {@code ContextualSearchManager} or {@code null} if none; */ public ContextualSearchManager getContextualSearchManager() { @@ -1397,8 +1375,8 @@ RecordUserAction.record("MobileMenuHistory"); StartupMetrics.getInstance().recordOpenedHistory(); } else if (id == R.id.share_menu_id || id == R.id.direct_share_menu_id) { - onShareMenuItemSelected(currentTab, getWindowAndroid(), - id == R.id.direct_share_menu_id, getCurrentTabModel().isIncognito()); + onShareMenuItemSelected(currentTab, id == R.id.direct_share_menu_id, + getCurrentTabModel().isIncognito()); } else if (id == R.id.print_id) { PrintingController printingController = getChromeApplication().getPrintingController(); if (printingController != null && !printingController.isBusy()
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OWNERS new file mode 100644 index 0000000..e05460d --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OWNERS
@@ -0,0 +1,3 @@ +aurimas@chromium.org +donnd@chromium.org +pedrosimonetti@chromium.org
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchIconSpriteControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchIconSpriteControl.java index 19206f61..3e9c3e7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchIconSpriteControl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchIconSpriteControl.java
@@ -6,7 +6,6 @@ import android.content.Context; -import org.chromium.chrome.R; import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation; /** @@ -38,11 +37,6 @@ private float mCompletionPercentage; /** - * The size to use for display of the search provider icon sprite in px. - */ - private float mSizePx; - - /** * The panel. */ private ContextualSearchPanel mPanel; @@ -54,7 +48,6 @@ */ public ContextualSearchIconSpriteControl( ContextualSearchPanel panel, Context context) { - mSizePx = context.getResources().getDimension(R.dimen.contextual_search_sprite_size); mPanel = panel; } @@ -81,13 +74,6 @@ } /** - * @return The size to use for display of the search provider icon sprite in px. - */ - public float getSizePx() { - return mSizePx; - } - - /** * @return Whether the appearance of the search provider icon sprite should be animated. */ public boolean shouldAnimateAppearance() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java index 250c6d6..a026308 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java
@@ -67,7 +67,6 @@ ContextualSearchIconSpriteControl spriteControl = panel.getIconSpriteControl(); boolean searchProviderIconSpriteVisible = spriteControl.isVisible(); float searchProviderIconCompletionPercentage = spriteControl.getCompletionPercentage(); - float searchProviderIconSpriteSize = spriteControl.getSizePx(); float arrowIconOpacity = panel.getArrowIconOpacity(); float arrowIconRotation = panel.getArrowIconRotation(); @@ -119,7 +118,6 @@ searchBarShadowOpacity, searchProviderIconSpriteVisible, searchProviderIconCompletionPercentage, - searchProviderIconSpriteSize, arrowIconOpacity, arrowIconRotation, closeIconOpacity, @@ -188,7 +186,6 @@ float searchBarShadowOpacity, boolean searchProviderIconSpriteVisible, float searchProviderIconCompletionPercentage, - float searchProviderIconSpriteSize, float arrowIconOpacity, float arrowIconRotation, float closeIconOpacity,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java index 7511037..bf4d33f5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
@@ -28,33 +28,35 @@ public static final int CUSTOM_TAB_MODE = 1; public static final int FULLSCREEN_TAB_MODE = 2; + // Items that are included in all context menus. + private static final int[] BASE_WHITELIST = { + R.id.contextmenu_copy_link_address, + R.id.contextmenu_copy_email_address, + R.id.contextmenu_copy_link_text, + R.id.contextmenu_save_image, + R.id.contextmenu_share_image, + R.id.contextmenu_save_video, + }; + + // Items that are included for normal Chrome browser mode. private static final int[] NORMAL_MODE_WHITELIST = { R.id.contextmenu_load_images, R.id.contextmenu_open_in_new_tab, R.id.contextmenu_open_in_incognito_tab, - R.id.contextmenu_copy_link_address, - R.id.contextmenu_copy_email_address, - R.id.contextmenu_copy_link_text, R.id.contextmenu_save_link_as, R.id.contextmenu_load_original_image, - R.id.contextmenu_save_image, R.id.contextmenu_open_image, R.id.contextmenu_search_by_image, - R.id.contextmenu_share_image, - R.id.contextmenu_save_video }; + // Additional items for custom tabs mode. private static final int[] CUSTOM_TAB_MODE_WHITELIST = { - R.id.contextmenu_copy_link_address, - R.id.contextmenu_copy_link_text, R.id.contextmenu_save_link_as, - R.id.contextmenu_save_image, R.id.contextmenu_open_image }; + // Additional items for fullscreen tabs mode. private static final int[] FULLSCREEN_TAB_MODE_WHITELIST = { - R.id.contextmenu_copy_link_address, - R.id.contextmenu_copy_link_text, R.id.menu_id_open_in_chrome }; @@ -214,10 +216,12 @@ } private void removeUnsupportedItems(ContextMenu menu, int[] whitelist) { + Arrays.sort(BASE_WHITELIST); Arrays.sort(whitelist); for (int i = 0; i < menu.size(); i++) { MenuItem item = menu.getItem(i); - if (Arrays.binarySearch(whitelist, item.getItemId()) < 0) { + if (Arrays.binarySearch(whitelist, item.getItemId()) < 0 + && Arrays.binarySearch(BASE_WHITELIST, item.getItemId()) < 0) { menu.removeItem(item.getItemId()); i--; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java index acefed5a..0c07e65 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
@@ -34,6 +34,8 @@ static final String PEEK_PROMO_MAX_SHOW_COUNT = "peek_promo_max_show_count"; static final int PEEK_PROMO_DEFAULT_MAX_SHOW_COUNT = 10; + static final String DISABLE_EXTRA_SEARCH_BAR_ANIMATIONS = "disable_extra_search_bar_animations"; + private static final int UNLIMITED_TAPS = -1; private static final int DEFAULT_TAP_RESOLVE_LIMIT_FOR_DECIDED = UNLIMITED_TAPS; private static final int DEFAULT_TAP_PREFETCH_LIMIT_FOR_DECIDED = UNLIMITED_TAPS; @@ -194,6 +196,13 @@ } /** + * @return Whether extra search bar animations are disabled. + */ + static boolean areExtraSearchBarAnimationsDisabled() { + return getBooleanParam(DISABLE_EXTRA_SEARCH_BAR_ANIMATIONS); + } + + /** * @return The maximum number of times the Peek Promo should be displayed. */ static int getPeekPromoMaxShowCount() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java index c406f66..10fcbdbe 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
@@ -314,7 +314,7 @@ * @return Whether the search provider icon should be animated. */ boolean shouldAnimateSearchProviderIcon(SelectionType selectionType, boolean isShowing) { - if (isShowing) { + if (isShowing || ContextualSearchFieldTrial.areExtraSearchBarAnimationsDisabled()) { return false; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/datausage/ExternalDataUseObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/datausage/ExternalDataUseObserver.java index 5149390..41161f2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/datausage/ExternalDataUseObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/datausage/ExternalDataUseObserver.java
@@ -44,14 +44,12 @@ } /** - * Fetches matching rules asynchronously. While an asynchronous fetch is underway, it is illegal - * to make calls to this method. - * @return true if {@link #nativeFetchMatchingRulesCallback} will eventually be called with - * matching rules, and false if matching rules cannot be retrieved. + * Fetches matching rules and returns them via {@link #fetchMatchingRulesCallback}. While the + * fetch is underway, it is illegal to make calls to this method. */ @CalledByNative - protected boolean fetchMatchingRules() { - return false; + protected void fetchMatchingRules() { + fetchMatchingRulesCallback(null, null, null); } /*
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkEditActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkEditActivity.java index 25dc139..65e4f42 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkEditActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkEditActivity.java
@@ -29,9 +29,8 @@ import org.chromium.chrome.browser.widget.EmptyAlertEditText; import org.chromium.chrome.browser.widget.TintedDrawable; import org.chromium.components.bookmarks.BookmarkId; -import org.chromium.components.offlinepages.DeletePageResult; -import org.chromium.components.offlinepages.SavePageResult; import org.chromium.content_public.browser.WebContents; +import org.chromium.ui.base.ActivityWindowAndroid; /** * The activity that enables the user to modify the title, url and parent folder of a bookmark. @@ -62,6 +61,7 @@ private OfflineButtonType mOfflineButtonType = OfflineButtonType.NONE; private OfflinePageModelObserver mOfflinePageModelObserver; + private ActivityWindowAndroid mActivityWindowAndroid; private BookmarkModelObserver mBookmarkModelObserver = new BookmarkModelObserver() { @Override @@ -146,6 +146,7 @@ findViewById(R.id.offline_page_group).setVisibility(View.VISIBLE); getIntent().setExtrasClassLoader(WebContents.class.getClassLoader()); mWebContents = getIntent().getParcelableExtra(INTENT_WEB_CONTENTS); + mActivityWindowAndroid = new ActivityWindowAndroid(this, false); updateOfflineSection(); } @@ -200,6 +201,19 @@ } @Override + public void onRequestPermissionsResult( + int requestCode, String[] permissions, int[] grantResults) { + if (mActivityWindowAndroid != null) { + if (mActivityWindowAndroid.onRequestPermissionsResult( + requestCode, permissions, grantResults)) { + return; + } + } + + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + + @Override protected void onStop() { if (mEnhancedBookmarksModel.doesBookmarkExist(mBookmarkId)) { final String title = mTitleEditText.getTrimmedText(); @@ -218,6 +232,7 @@ super.onStop(); } + @Override protected void onDestroy() { recordOfflineButtonAction(false); @@ -265,13 +280,12 @@ public void onClick(View v) { recordOfflineButtonAction(true); mEnhancedBookmarksModel.getOfflinePageBridge().deletePage( - mBookmarkId, new DeletePageCallback() { + mBookmarkId, mActivityWindowAndroid, new DeletePageCallback() { @Override public void onDeletePageDone(int deletePageResult) { - if (deletePageResult == DeletePageResult.SUCCESS) { - updateOfflineSection(); - } // TODO(fgorski): Add snackbar upon failure. + // Always update UI, as buttons might be disabled. + updateOfflineSection(); } }); button.setClickable(false); @@ -286,14 +300,13 @@ @Override public void onClick(View v) { recordOfflineButtonAction(true); - mEnhancedBookmarksModel.getOfflinePageBridge().savePage(mWebContents, mBookmarkId, - new SavePageCallback() { + mEnhancedBookmarksModel.getOfflinePageBridge().savePage( + mWebContents, mBookmarkId, mActivityWindowAndroid, new SavePageCallback() { @Override public void onSavePageDone(int savePageResult, String url) { - if (savePageResult == SavePageResult.SUCCESS) { - updateOfflineSection(); - } // TODO(fgorski): Add snackbar upon failure. + // Always update UI, as buttons might be disabled. + updateOfflineSection(); } }); button.setClickable(false); @@ -327,18 +340,28 @@ return; } - String actionName = "OfflinePages.Edit."; - if (mOfflineButtonType == OfflineButtonType.SAVE) { - actionName += clicked ? "SaveButtonClicked" : "SaveButtonNotClicked"; - } else if (mOfflineButtonType == OfflineButtonType.REMOVE) { - actionName += clicked ? "RemoveButtonClicked" : "RemoveButtonNotClicked"; - } else if (mOfflineButtonType == OfflineButtonType.VISIT) { - actionName += clicked ? "VisitButtonClicked" : "VisitButtonNotClicked"; + assert mOfflineButtonType == OfflineButtonType.SAVE + || mOfflineButtonType == OfflineButtonType.REMOVE + || mOfflineButtonType == OfflineButtonType.VISIT; + + if (clicked) { + if (mOfflineButtonType == OfflineButtonType.SAVE) { + RecordUserAction.record("OfflinePages.Edit.SaveButtonClicked"); + } else if (mOfflineButtonType == OfflineButtonType.REMOVE) { + RecordUserAction.record("OfflinePages.Edit.RemoveButtonClicked"); + } else if (mOfflineButtonType == OfflineButtonType.VISIT) { + RecordUserAction.record("OfflinePages.Edit.VisitButtonClicked"); + } } else { - assert false; + if (mOfflineButtonType == OfflineButtonType.SAVE) { + RecordUserAction.record("OfflinePages.Edit.SaveButtonNotClicked"); + } else if (mOfflineButtonType == OfflineButtonType.REMOVE) { + RecordUserAction.record("OfflinePages.Edit.RemoveButtonNotClicked"); + } else if (mOfflineButtonType == OfflineButtonType.VISIT) { + RecordUserAction.record("OfflinePages.Edit.VisitButtonNotClicked"); + } } - RecordUserAction.record(actionName); mOfflineButtonType = OfflineButtonType.NONE; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarksModel.java b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarksModel.java index 043533f..588ee2f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarksModel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarksModel.java
@@ -20,6 +20,7 @@ import org.chromium.components.bookmarks.BookmarkType; import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; import org.chromium.components.offlinepages.SavePageResult; +import org.chromium.content.browser.ContentViewCore; import org.chromium.content_public.browser.WebContents; import java.util.ArrayList; @@ -236,20 +237,22 @@ final AddBookmarkCallback callback) { assert bookmarkId.getId() != ChromeBrowserProviderClient.INVALID_BOOKMARK_ID; if (mOfflinePageBridge != null) { - mOfflinePageBridge.savePage(webContents, bookmarkId, new SavePageCallback() { - @Override - public void onSavePageDone(int savePageResult, String url) { - int saveResult; - if (savePageResult == SavePageResult.SUCCESS) { - saveResult = AddBookmarkCallback.SAVED; - } else if (savePageResult == SavePageResult.SKIPPED) { - saveResult = AddBookmarkCallback.SKIPPED; - } else { - saveResult = AddBookmarkCallback.ERROR; - } - callback.onBookmarkAdded(bookmarkId, saveResult); - } - }); + mOfflinePageBridge.savePage(webContents, bookmarkId, + ContentViewCore.fromWebContents(webContents).getWindowAndroid(), + new SavePageCallback() { + @Override + public void onSavePageDone(int savePageResult, String url) { + int saveResult; + if (savePageResult == SavePageResult.SUCCESS) { + saveResult = AddBookmarkCallback.SAVED; + } else if (savePageResult == SavePageResult.SKIPPED) { + saveResult = AddBookmarkCallback.SKIPPED; + } else { + saveResult = AddBookmarkCallback.ERROR; + } + callback.onBookmarkAdded(bookmarkId, saveResult); + } + }); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java b/chrome/android/java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java index 3cfb7ff..5d9f6c6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java
@@ -143,10 +143,10 @@ * {@link ScreenshotTask.ScreenshotTaskCallback} implementation. */ @Override - public void onGotBitmap(@Nullable Bitmap bitmap, boolean success) { + public void onGotBitmap(@Nullable Bitmap bitmap) { ThreadUtils.assertOnUiThread(); mScreenshotTaskFinished = true; - if (success) mScreenshot = bitmap; + mScreenshot = bitmap; maybePostResult(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feedback/ScreenshotTask.java b/chrome/android/java/src/org/chromium/chrome/browser/feedback/ScreenshotTask.java index db8dc25..6874142 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/feedback/ScreenshotTask.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/feedback/ScreenshotTask.java
@@ -6,18 +6,21 @@ import android.app.Activity; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import org.chromium.base.ThreadUtils; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; import org.chromium.chrome.browser.ChromeActivity; -import org.chromium.content.browser.ContentReadbackHandler; -import org.chromium.content_public.browser.readback_types.ReadbackResponse; import org.chromium.ui.UiUtils; +import org.chromium.ui.base.WindowAndroid; import javax.annotation.Nullable; /** * A utility class to take a feedback-formatted screenshot of an {@link Activity}. */ +@JNINamespace("chrome::android") public final class ScreenshotTask { /** * Maximum dimension for the screenshot to be sent to the feedback handler. This size @@ -32,9 +35,8 @@ /** * Called when collection of the bitmap has completed. * @param bitmap the bitmap or null. - * @param success whether the bitmap is valid. */ - void onGotBitmap(@Nullable Bitmap bitmap, boolean success); + void onGotBitmap(@Nullable Bitmap bitmap); } /** @@ -45,7 +47,7 @@ */ public static void create(Activity activity, final ScreenshotTaskCallback callback) { if (activity instanceof ChromeActivity) { - createCompositorActivityScreenshot((ChromeActivity) activity, callback); + createCompositorScreenshot(((ChromeActivity) activity).getWindowAndroid(), callback); return; } @@ -53,21 +55,32 @@ ThreadUtils.postOnUiThread(new Runnable() { @Override public void run() { - callback.onGotBitmap(bitmap, bitmap != null); + callback.onGotBitmap(bitmap); } }); } - private static void createCompositorActivityScreenshot(ChromeActivity activity, + /** + * A callback passed to the native snapshot API which returns the result in PNG format. + */ + private interface SnapshotResultCallback { + /** + * Called when collection of the bitmap has completed. + * @param pngBytes PNG-formatted bitmap in byte array if successful; otherwise null + */ + void onCompleted(@Nullable byte[] pngBytes); + } + + private static void createCompositorScreenshot(WindowAndroid windowAndroid, final ScreenshotTaskCallback callback) { - ContentReadbackHandler.GetBitmapCallback getBitmapCallback = - new ContentReadbackHandler.GetBitmapCallback() { + SnapshotResultCallback resultCallback = new SnapshotResultCallback() { @Override - public void onFinishGetBitmap(Bitmap bitmap, int response) { - callback.onGotBitmap(bitmap, response == ReadbackResponse.SUCCESS); + public void onCompleted(byte[] pngBytes) { + callback.onGotBitmap(pngBytes != null + ? BitmapFactory.decodeByteArray(pngBytes, 0, pngBytes.length) : null); } }; - activity.startTakingCompositorActivityScreenshot(getBitmapCallback); + nativeGrabWindowSnapshotAsync(resultCallback, windowAndroid.getNativePointer()); } /** @@ -94,6 +107,14 @@ return Bitmap.createScaledBitmap(bitmap, destWidth, destHeight, true); } + @CalledByNative + private static void notifySnapshotFinished(Object callback, byte[] pngBytes) { + ((SnapshotResultCallback) callback).onCompleted(pngBytes); + } + // This is a utility class, so it should never be created. private ScreenshotTask() {} + + private static native void nativeGrabWindowSnapshotAsync(SnapshotResultCallback callback, + long nativeWindowAndroid); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutoSigninFirstRunInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutoSigninFirstRunInfoBar.java new file mode 100644 index 0000000..6c56303 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutoSigninFirstRunInfoBar.java
@@ -0,0 +1,65 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.infobar; + +import android.text.Spannable; +import android.text.SpannableString; +import android.text.method.LinkMovementMethod; +import android.text.style.ClickableSpan; +import android.view.View; +import android.widget.TextView; + +import org.chromium.base.annotations.CalledByNative; +import org.chromium.chrome.R; + +/** + * The auto sign-in first run experience infobar is shown instead of usual auto sign-in snackbar + * when user first time faces the auto sign-in feature. It contains information about which account + * was used for signing in and text which explains the feature. + */ +public class AutoSigninFirstRunInfoBar extends ConfirmInfoBar { + private final String mExplanation; + private final int mExplanationLinkStart; + private final int mExplanationLinkEnd; + + @CalledByNative + private static InfoBar show(String message, String primaryButtonText, String explanation, + int explanationLinkStart, int explanationLinkEnd) { + return new AutoSigninFirstRunInfoBar( + message, primaryButtonText, explanation, explanationLinkStart, explanationLinkEnd); + } + + private AutoSigninFirstRunInfoBar(String message, String primaryButtonText, String explanation, + int explanationLinkStart, int explanationLinkEnd) { + super(null, R.drawable.account_management_no_picture, null, message, null, + primaryButtonText, null); + mExplanation = explanation; + mExplanationLinkStart = explanationLinkStart; + mExplanationLinkEnd = explanationLinkEnd; + } + + /** + * Adds text, which explains the auto sign-in feature. + */ + @Override + public void createContent(InfoBarLayout layout) { + super.createContent(layout); + SpannableString explanation = new SpannableString(mExplanation); + if (mExplanationLinkEnd != mExplanationLinkStart && mExplanationLinkEnd != 0) { + explanation.setSpan(new ClickableSpan() { + @Override + public void onClick(View view) { + onLinkClicked(); + } + }, mExplanationLinkStart, mExplanationLinkEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } + // TODO(melandory): Implement correct (as in mocks) margin for the first run + // experience text. + TextView firstRunExperienceMessageView = new TextView(getContext()); + firstRunExperienceMessageView.setText(explanation, TextView.BufferType.SPANNABLE); + firstRunExperienceMessageView.setMovementMethod(LinkMovementMethod.getInstance()); + layout.setCustomContent(firstRunExperienceMessageView); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastRouteController.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastRouteController.java index 64373dc2..166d997 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastRouteController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastRouteController.java
@@ -46,7 +46,8 @@ private static final String TAG = "cr_MediaRouter"; private static final String MEDIA_NAMESPACE = "urn:x-cast:com.google.cast.media"; - private static final String RECEIVER_NAMESPACE = "urn:x-cast:com.google.cast.receiver"; + private static final String GAMES_NAMESPACE = "urn:x-cast:com.google.cast.games"; + private static final String MEDIA_MESSAGE_TYPES[] = { "PLAY", "LOAD", @@ -72,9 +73,6 @@ // Sequence number used when no sequence number is required or was initially passed. private static final int INVALID_SEQUENCE_NUMBER = -1; - // Sequence number use instead of no sequence number when a sequence number was expected from - // the client. - private static final int OPTIONAL_SEQUENCE_NUMBER = 0; // Map associating types that have a different names outside of the media namespace and inside. // In other words, some types are sent as MEDIA_FOO or FOO_MEDIA by the client by the Cast @@ -100,22 +98,23 @@ Log.d(TAG, "Received message from Cast device: namespace=\"" + namespace + "\" message=\"" + message + "\""); - if (MEDIA_NAMESPACE.equals(namespace) || RECEIVER_NAMESPACE.equals(namespace)) { - int sequenceNumber = INVALID_SEQUENCE_NUMBER; - try { - JSONObject jsonMessage = new JSONObject(message); - int requestId = jsonMessage.getInt("requestId"); - if (mSession.mRequests.indexOfKey(requestId) >= 0) { - sequenceNumber = mSession.mRequests.get(requestId); - mSession.mRequests.delete(requestId); - } - } catch (JSONException e) { - } finally { - mSession.onMessage("v2_message", message, namespace, sequenceNumber); + int sequenceNumber = INVALID_SEQUENCE_NUMBER; + try { + JSONObject jsonMessage = new JSONObject(message); + int requestId = jsonMessage.getInt("requestId"); + if (mSession.mRequests.indexOfKey(requestId) >= 0) { + sequenceNumber = mSession.mRequests.get(requestId); + mSession.mRequests.delete(requestId); } - } else { - mSession.onAppMessage(namespace, message); + } catch (JSONException e) { } + + if (MEDIA_NAMESPACE.equals(namespace)) { + mSession.onMediaMessage(message, sequenceNumber); + return; + } + + mSession.onAppMessage(message, namespace, sequenceNumber); } } @@ -203,8 +202,8 @@ mHandler = new Handler(); mMessageChannel = new CastMessagingChannel(this); - addNamespace(RECEIVER_NAMESPACE); addNamespace(MEDIA_NAMESPACE); + addNamespace(GAMES_NAMESPACE); final Context context = ApplicationStatus.getApplicationContext(); @@ -351,31 +350,31 @@ /** - * Sends the internal Cast message to the Cast clients on the page via the media router. - * @param type The type of the message (e.g. "new_session" or "v2_message") - * @param message The message itself (encoded JSON). - * @param namespace The namespace for the message. + * Forwards the media message to the page via the media router. + * @param message The media that's being send by the receiver. + * @param sequenceNumber The sequence number of the message this one is responding to. */ - public void onMessage(String type, String message, String namespace, int sequenceNumber) { - if (MEDIA_NAMESPACE.equals(namespace) && mMediaPlayer != null) { - mMediaPlayer.onMessageReceived(mCastDevice, namespace, message); + public void onMediaMessage(String message, int sequenceNumber) { + if (mMediaPlayer != null) { + mMediaPlayer.onMessageReceived(mCastDevice, MEDIA_NAMESPACE, message); } - sendMessageToClients(type, message, sequenceNumber); + sendMessageToClients("v2_message", message, sequenceNumber); } /** * Forwards the application specific message to the page via the media router. - * @param namespace The application specific namespace this message belongs to. * @param message The message within the namespace that's being send by the receiver. + * @param namespace The application specific namespace this message belongs to. + * @param sequenceNumber The sequence number of the message this one is responding to. */ - public void onAppMessage(String namespace, String message) { + public void onAppMessage(String message, String namespace, int sequenceNumber) { try { JSONObject jsonMessage = new JSONObject(); jsonMessage.put("sessionId", mSessionId); jsonMessage.put("namespaceName", namespace); jsonMessage.put("message", message); - onMessage("app_message", jsonMessage.toString(), null, INVALID_SEQUENCE_NUMBER); + sendMessageToClients("app_message", jsonMessage.toString(), sequenceNumber); } catch (JSONException e) { Log.e(TAG, "Failed to create the message wrapper", e); } @@ -391,7 +390,7 @@ .setResultCallback(new ResultCallback<Status>() { @Override public void onResult(Status status) { - onMessage("remove_session", mSessionId, null, sequenceNumber); + sendMessageToClients("remove_session", mSessionId, sequenceNumber); // TODO(avayvod): handle a failure to stop the application. // https://crbug.com/535577 @@ -447,6 +446,7 @@ } private boolean handleInternalMessage(String message, int callbackId) { + Log.d(TAG, "Received message from client: %s", message); boolean success = true; try { JSONObject jsonMessage = new JSONObject(message); @@ -499,15 +499,12 @@ throws JSONException { assert "v2_message".equals(jsonMessage.getString("type")); - Log.d(TAG, "Received message from client: " + jsonMessage); - String clientId = jsonMessage.getString("clientId"); if (!mClients.contains(clientId)) return false; JSONObject jsonCastMessage = jsonMessage.getJSONObject("message"); String messageType = jsonCastMessage.getString("type"); - int sequenceNumber = jsonMessage.has("sequenceNumber") - ? jsonMessage.getInt("sequenceNumber") : OPTIONAL_SEQUENCE_NUMBER; + int sequenceNumber = jsonMessage.optInt("sequenceNumber", INVALID_SEQUENCE_NUMBER); if ("STOP".equals(messageType)) { stopApplication(sequenceNumber); @@ -611,33 +608,43 @@ if (!mClients.contains(clientId)) return false; JSONObject jsonAppMessageWrapper = jsonMessage.getJSONObject("message"); + + JSONObject actualMessage = jsonAppMessageWrapper.getJSONObject("message"); + if (actualMessage == null) return false; + if (!mSessionId.equals(jsonAppMessageWrapper.getString("sessionId"))) return false; String namespaceName = jsonAppMessageWrapper.getString("namespaceName"); if (namespaceName == null || namespaceName.isEmpty()) return false; if (!mNamespaces.contains(namespaceName)) addNamespace(namespaceName); - sendCastMessage(jsonAppMessageWrapper, namespaceName, INVALID_SEQUENCE_NUMBER); - return true; + int sequenceNumber = jsonMessage.optInt("sequenceNumber", INVALID_SEQUENCE_NUMBER); + return sendCastMessage(actualMessage, namespaceName, sequenceNumber); } - private boolean sendCastMessage(JSONObject message, String namespace, int sequenceNumber) - throws JSONException { + private boolean sendCastMessage( + JSONObject message, + final String namespace, + final int sequenceNumber) throws JSONException { if (isApiClientInvalid()) return false; removeNullFields(message); - // If for some reason, there is already a requestId different than 0, it - // is kept. Otherwise, one is generated and associated with the sequenceNumber - // passed by the client. - if (!message.has("requestId") || (message.getInt("requestId") == 0)) { - int requestId = CastRequestIdGenerator.getNextRequestId(); + // Map the request id to a valid sequence number only. + if (sequenceNumber != INVALID_SEQUENCE_NUMBER) { + // If for some reason, there is already a requestId other than 0, it + // is kept. Otherwise, one is generated. In all cases it's associated with the + // sequenceNumber passed by the client. + int requestId = message.optInt("requestId", 0); + if (requestId == 0) { + requestId = CastRequestIdGenerator.getNextRequestId(); + message.put("requestId", requestId); + } mRequests.append(requestId, sequenceNumber); - message.put("requestId", requestId); } - Log.d(TAG, "Sending message to Cast device: " + message); + Log.d(TAG, "Sending message to Cast device in namespace %s: %s", namespace, message); try { Cast.CastApi.sendMessage(mApiClient, namespace, message.toString()) @@ -649,7 +656,15 @@ // TODO(avayvod): should actually report back to the page. // See https://crbug.com/550445. Log.e(TAG, "Failed to send the message: " + result); + return; } + + // Media commands wait for the media status update as a result. + if (MEDIA_NAMESPACE.equals(namespace)) return; + + // App messages wait for the empty message with the sequence + // number. + sendMessageToClients("app_message", null, sequenceNumber); } }); } catch (Exception e) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java index aece15c..d01be4d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -41,6 +41,7 @@ import org.chromium.chrome.browser.ntp.LogoBridge.LogoObserver; import org.chromium.chrome.browser.ntp.MostVisitedItem.MostVisitedItemManager; import org.chromium.chrome.browser.ntp.NewTabPage.OnSearchBoxScrollListener; +import org.chromium.chrome.browser.preferences.DocumentModeManager; import org.chromium.chrome.browser.profiles.MostVisitedSites.MostVisitedURLsObserver; import org.chromium.chrome.browser.profiles.MostVisitedSites.ThumbnailCallback; import org.chromium.chrome.browser.util.ViewUtils; @@ -62,27 +63,6 @@ private static final int SHADOW_COLOR = 0x11000000; private static final long SNAP_SCROLL_DELAY_MS = 30; - // Taken from https://support.google.com/googleplay/answer/1727131?hl=en-GB - private static final String[] SUPPORTED_SAMSUNG_DEVICES = { - "sm-g920", // Galaxy S6 - "sm-g925", // Galaxy S6 Edge - "404sc", // Galaxy S6 Edge - "scv31", // Galaxy S6 Edge - "sm-g890", // Galaxy S6 Active - "sm-g800", // Galaxy S5 mini - "sm-g860", // Galaxy S5 K Sport - "sm-g870", // Galaxy S5 Active - "sm-g900", // Galaxy S5 - "sm-g901", // Galaxy S5 LTE-A - "sm-g906", // Galaxy S5 - "scl23", // Galaxy S5 - "sm-n915", // Galaxy Note Edge - "scl24", // Galaxy Note Edge - "sm-n916", // Galaxy Note 4 - "sm-n910", // Galaxy Note 4 - "sm-g850", // Galaxy Alpha - }; - private ViewGroup mContentView; private NewTabScrollView mScrollView; private LogoView mSearchProviderLogoView; @@ -332,13 +312,8 @@ private int getTabsMovedIllustration() { switch (Build.MANUFACTURER.toLowerCase(Locale.US)) { case "samsung": - String model = Build.MODEL.toLowerCase(Locale.US); - for (String supportedModel : SUPPORTED_SAMSUNG_DEVICES) { - if (model.contains(supportedModel)) { - return R.drawable.tabs_moved_samsung; - } - } - return 0; + if (DocumentModeManager.isDeviceTabbedModeByDefault()) return 0; + return R.drawable.tabs_moved_samsung; case "htc": return R.drawable.tabs_moved_htc; default: @@ -372,7 +347,12 @@ optOutText.setMovementMethod(LinkMovementMethod.getInstance()); ImageView illustration = (ImageView) mOptOutView.findViewById(R.id.tabs_moved_illustration); - illustration.setImageResource(getTabsMovedIllustration()); + int resourceId = getTabsMovedIllustration(); + if (resourceId != 0) { + illustration.setImageResource(getTabsMovedIllustration()); + } else { + illustration.setImageDrawable(null); + } mOptOutView.setVisibility(View.VISIBLE); mMostVisitedLayout.setVisibility(View.GONE);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java index cca791b..7a94603 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java
@@ -16,9 +16,10 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.components.bookmarks.BookmarkId; import org.chromium.components.bookmarks.BookmarkType; +import org.chromium.components.offlinepages.DeletePageResult; import org.chromium.components.offlinepages.SavePageResult; -import org.chromium.content.browser.ContentViewCore; import org.chromium.content_public.browser.WebContents; +import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.base.WindowAndroid.PermissionCallback; import java.util.ArrayList; @@ -186,22 +187,22 @@ * * @param webContents Contents of the page to save. * @param bookmarkId Id of the bookmark related to the offline page. + * @param windowAndroid The Android window used to access the file system. * @param callback Interface that contains a callback. * @see SavePageCallback */ @VisibleForTesting public void savePage(final WebContents webContents, final BookmarkId bookmarkId, - final SavePageCallback callback) { + WindowAndroid windowAndroid, final SavePageCallback callback) { assert mIsNativeOfflinePageModelLoaded; RecordHistogram.recordEnumeratedHistogram( "OfflinePages.SavePage.FreeSpacePercentage", getFreeSpacePercentage(), 101); RecordHistogram.recordCustomCountHistogram( "OfflinePages.SavePage.FreeSpaceMB", getFreeSpaceMB(), 1, 500000, 50); - ContentViewCore view = ContentViewCore.fromWebContents(webContents); - if (view == null) { + if (windowAndroid == null) { callback.onSavePageDone(SavePageResult.CONTENT_UNAVAILABLE, webContents.getUrl()); - } else if (OfflinePageUtils.hasFileAccessPermission(view)) { + } else if (OfflinePageUtils.hasFileAccessPermission(windowAndroid)) { nativeSavePage(mNativeOfflinePageBridge, callback, webContents, bookmarkId.getId()); } else { PermissionCallback permissionCallback = new PermissionCallback() { @@ -217,7 +218,7 @@ } }; - OfflinePageUtils.requestFileAccessPermission(view, permissionCallback); + OfflinePageUtils.requestFileAccessPermission(windowAndroid, permissionCallback); } } @@ -235,17 +236,37 @@ * Deletes an offline page related to a specified bookmark. * * @param bookmarkId Bookmark ID for which the offline copy will be deleted. + * @param windowAndroid The Android window used to access the file system. * @param callback Interface that contains a callback. * @see DeletePageCallback */ @VisibleForTesting - public void deletePage(BookmarkId bookmarkId, DeletePageCallback callback) { + public void deletePage(final BookmarkId bookmarkId, WindowAndroid windowAndroid, + final DeletePageCallback callback) { assert mIsNativeOfflinePageModelLoaded; + assert windowAndroid != null; RecordHistogram.recordEnumeratedHistogram( "OfflinePages.DeletePage.FreeSpacePercentage", getFreeSpacePercentage(), 101); RecordHistogram.recordCustomCountHistogram( "OfflinePages.DeletePage.FreeSpaceMB", getFreeSpaceMB(), 1, 500000, 50); - nativeDeletePage(mNativeOfflinePageBridge, callback, bookmarkId.getId()); + + if (OfflinePageUtils.hasFileAccessPermission(windowAndroid)) { + nativeDeletePage(mNativeOfflinePageBridge, callback, bookmarkId.getId()); + } else { + PermissionCallback permissionCallback = new PermissionCallback() { + @Override + public void onRequestPermissionsResult(String[] permission, int[] grantResults) { + if (grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + nativeDeletePage(mNativeOfflinePageBridge, callback, bookmarkId.getId()); + } else { + callback.onDeletePageDone(DeletePageResult.DEVICE_FAILURE); + } + } + }; + + OfflinePageUtils.requestFileAccessPermission(windowAndroid, permissionCallback); + } } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java index 282b8ae..5b6c4706 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
@@ -14,24 +14,27 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeBrowserProviderClient; +import org.chromium.chrome.browser.enhancedbookmarks.EnhancedBookmarkUtils; import org.chromium.chrome.browser.snackbar.Snackbar; import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarController; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.content.browser.ContentViewCore; +import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkType; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.ui.base.PageTransition; +import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.base.WindowAndroid.PermissionCallback; /** * A class holding static util functions for offline pages. */ public class OfflinePageUtils { - private enum SnackbarButtonType { - NONE, - RELOAD, - SAVE, - }; + /** Snackbar button types */ + private static final int NO_BUTTON = 0; + private static final int RELOAD_BUTTON = 1; + private static final int SAVE_BUTTON = 2; + private static final int EDIT_BUTTON = 3; private static final long STORAGE_ALMOST_FULL_THRESHOLD_BYTES = 10L * (1 << 20); // 10M @@ -84,6 +87,7 @@ } boolean save; + final long bookmarkId = tab.getUserBookmarkId(); if (tab.isOfflinePage()) { // If an offline page is being visited, prompt that an offline copy is being shown. save = false; @@ -104,33 +108,35 @@ tab.addObserver(new EmptyTabObserver() { @Override public void onShown(Tab visibleTab) { - showOfflineSnackbar(activity, visibleTab.getId(), finalSave); + showOfflineSnackbar(activity, visibleTab.getId(), finalSave, bookmarkId); } }); } else { - showOfflineSnackbar(activity, tab.getId(), save); + showOfflineSnackbar(activity, tab.getId(), save, bookmarkId); } } /** * Returns whether file access is allowed. * - * @param view The ContentViewCore to access the file system. + * @param windowAndroid The Android window used to access the file system. * @return true if allowed, or false otherwise. */ - public static boolean hasFileAccessPermission(ContentViewCore view) { - return view.getWindowAndroid().hasPermission(permission.WRITE_EXTERNAL_STORAGE); + public static boolean hasFileAccessPermission(WindowAndroid windowAndroid) { + assert windowAndroid != null; + return windowAndroid.hasPermission(permission.WRITE_EXTERNAL_STORAGE); } /** * Called to prompt user with the file access permission. * - * @param view The ContentViewCore to access the file system. + * @param windowAndroid The Android window used to access the file system. * @param callback Callback for the permission request. */ public static void requestFileAccessPermission( - ContentViewCore view, PermissionCallback callback) { - view.getWindowAndroid().requestPermissions( + WindowAndroid windowAndroid, PermissionCallback callback) { + assert windowAndroid != null; + windowAndroid.requestPermissions( new String[] {android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, callback); } @@ -139,25 +145,30 @@ * @param activity The activity owning the tab. * @param tabId The ID of current tab. * @param save Whether to offer saving the page. + * @param bookmarkId Bookmark ID related to the opened page. */ private static void showOfflineSnackbar( - final ChromeActivity activity, final int tabId, boolean save) { + final ChromeActivity activity, final int tabId, boolean save, final long bookmarkId) { Context context = activity.getBaseContext(); int snackbarTextId = -1; int actionTextId = -1; - SnackbarButtonType buttonType = SnackbarButtonType.NONE; + int buttonType = NO_BUTTON; if (save) { - buttonType = SnackbarButtonType.SAVE; + buttonType = SAVE_BUTTON; snackbarTextId = R.string.offline_pages_save_page_offline; actionTextId = R.string.save; } else { snackbarTextId = R.string.offline_pages_viewing_offline_page; - // Offer to reload the original page if there is network connection. + // Offer to reload the original page if there is network connection or edit if there is + // none. if (isConnected(context)) { - buttonType = SnackbarButtonType.RELOAD; + buttonType = RELOAD_BUTTON; actionTextId = R.string.reload; + } else { + buttonType = EDIT_BUTTON; + actionTextId = R.string.enhanced_bookmark_item_edit; } } @@ -168,17 +179,22 @@ if (tab == null) { return; } - SnackbarButtonType buttonType = (SnackbarButtonType) actionData; + int buttonType = (int) actionData; switch (buttonType) { - case RELOAD: + case RELOAD_BUTTON: RecordUserAction.record("OfflinePages.ReloadButtonClicked"); tab.loadUrl(new LoadUrlParams( tab.getOfflinePageOriginalUrl(), PageTransition.RELOAD)); break; - case SAVE: + case SAVE_BUTTON: RecordUserAction.record("OfflinePages.SaveButtonClicked"); activity.saveBookmarkOffline(tab); break; + case EDIT_BUTTON: + RecordUserAction.record("OfflinePages.ViewingOffline.EditButtonClicked"); + EnhancedBookmarkUtils.startEditActivity( + activity, new BookmarkId(bookmarkId, BookmarkType.NORMAL), null); + break; default: assert false; break; @@ -188,17 +204,20 @@ @Override public void onDismissNoAction(Object actionData) { if (actionData == null) return; - SnackbarButtonType buttonType = (SnackbarButtonType) actionData; + int buttonType = (int) actionData; switch (buttonType) { - case NONE: + case NO_BUTTON: // No recording is needed. break; - case RELOAD: + case RELOAD_BUTTON: RecordUserAction.record("OfflinePages.ReloadButtonNotClicked"); break; - case SAVE: + case SAVE_BUTTON: RecordUserAction.record("OfflinePages.SaveButtonNotClicked"); break; + case EDIT_BUTTON: + RecordUserAction.record("OfflinePages.ViewingOffline.EditButtonNotClicked"); + break; default: assert false; break;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/DocumentModeManager.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/DocumentModeManager.java index c45339e..6add6b8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/DocumentModeManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/DocumentModeManager.java
@@ -227,7 +227,12 @@ sharedPreferencesEditor.apply(); } - private static boolean isDeviceTabbedModeByDefault() { + /** + * @return Whether Chrome should default to Tabbed mode despite Document mode being supported + * at the platform level. A device will default to Tabbed mode if accessing the + * platform Overview screen is deemed too difficult to make Document mode user friendly. + */ + public static boolean isDeviceTabbedModeByDefault() { String model = Build.MODEL.toUpperCase(Locale.US); for (String device : DEFAULT_TABBED_MODE_DEVICES) { if (model.contains(device)) return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java index 492b771..2145723 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java
@@ -213,6 +213,7 @@ } else { getPreferenceScreen().removePreference(findPreference(PREF_SIGN_IN_CHILD_MESSAGE)); signOutSwitch.setChecked(true); + signOutSwitch.setEnabled(getSignOutAllowedPreferenceValue(getActivity())); signOutSwitch.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java index 0ffa9a9..5103cdc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java
@@ -300,7 +300,7 @@ } @CalledByNative - public void notifyRefreshTokenAvailable(String accountName) { + private void notifyRefreshTokenAvailable(String accountName) { assert accountName != null; Account account = AccountManagerHelper.createAccountFromName(accountName); for (OAuth2TokenServiceObserver observer : mObservers) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ClipDrawableProgressBar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ClipDrawableProgressBar.java index 7f2f992a..937cf15 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ClipDrawableProgressBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ClipDrawableProgressBar.java
@@ -39,6 +39,7 @@ private final ColorDrawable mForegroundDrawable; private int mBackgroundColor = Color.TRANSPARENT; private float mProgress; + private int mProgressUpdateCount; private int mDesiredVisibility; /** @@ -98,6 +99,7 @@ if (mProgress == progress) return; mProgress = progress; + mProgressUpdateCount += 1; getDrawable().setLevel(Math.round(progress * CLIP_DRAWABLE_MAX)); } @@ -143,6 +145,20 @@ } } + /** + * Resets progress update count to 0. + */ + public void resetProgressUpdateCount() { + mProgressUpdateCount = 0; + } + + /** + * @return Progress update count since reset. + */ + public int getProgressUpdateCount() { + return mProgressUpdateCount; + } + private void updateInternalVisibility() { int oldVisibility = getVisibility(); int newVisibility = mDesiredVisibility;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java index a9960ccb..e10e53f5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java
@@ -12,6 +12,7 @@ import org.chromium.base.CommandLine; import org.chromium.base.VisibleForTesting; +import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.components.variations.VariationsAssociatedData; import org.chromium.ui.interpolators.BakedBezierInterpolator; @@ -22,6 +23,10 @@ public class ToolbarProgressBar extends ClipDrawableProgressBar { private static final String ANIMATION_FIELD_TRIAL_NAME = "ProgressBarAnimationAndroid"; + private static final String PROGRESS_BAR_UPDATE_COUNT_HISTOGRAM = + "Omnibox.ProgressBarUpdateCount"; + private static final String PROGRESS_BAR_BREAK_POINT_UPDATE_COUNT_HISTOGRAM = + "Omnibox.ProgressBarBreakPointUpdateCount"; /** * Interface for progress bar animation interpolation logics. @@ -48,7 +53,8 @@ private boolean mIsStarted; private float mTargetProgress; - AnimationLogic mAnimationLogic; + private int mTargetProgressUpdateCount; + private AnimationLogic mAnimationLogic; private boolean mAnimationInitialized; private final Runnable mHideRunnable = new Runnable() { @@ -125,6 +131,8 @@ */ public void start() { mIsStarted = true; + mTargetProgressUpdateCount = 0; + resetProgressUpdateCount(); super.setProgress(0.0f); if (mAnimationLogic != null) mAnimationLogic.reset(); removeCallbacks(mHideRunnable); @@ -140,6 +148,11 @@ if (delayed) { updateVisibleProgress(); + RecordHistogram.recordCount1000Histogram(PROGRESS_BAR_UPDATE_COUNT_HISTOGRAM, + getProgressUpdateCount()); + RecordHistogram.recordCount100Histogram( + PROGRESS_BAR_BREAK_POINT_UPDATE_COUNT_HISTOGRAM, + mTargetProgressUpdateCount); } else { removeCallbacks(mHideRunnable); animate().cancel(); @@ -190,7 +203,9 @@ @Override public void setProgress(float progress) { assert mIsStarted; + if (mTargetProgress == progress) return; + mTargetProgressUpdateCount += 1; mTargetProgress = progress; updateVisibleProgress(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java index c492dcb..3b8e1b6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java
@@ -155,7 +155,7 @@ final ViewGroup view = viewCore.getContainerView(); final TestInputMethodManagerWrapper immw = new TestInputMethodManagerWrapper(viewCore); - viewCore.getImeAdapterForTest().setInputMethodManagerWrapper(immw); + viewCore.getImeAdapterForTest().setInputMethodManagerWrapperForTest(immw); // Add an Autofill profile. AutofillProfile profile = new AutofillProfile(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java index 68ff525..da264d5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -12,7 +12,6 @@ import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.graphics.Bitmap; -import android.net.Uri; import android.test.mock.MockPackageManager; import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.SmallTest; @@ -424,27 +423,7 @@ @SmallTest @Feature({"AppBanners"}) public void testWebAppBannerAppears() throws Exception { - // Create a Tab that doesn't have the AppBannerManager enabled. This prevents race - // conditions between service worker activation and AppBannerManager getting triggered. - // This race condition is a known problem, which is why the specs include wiggle room for - // how many times a site must be visited. - AppBannerManager.setIsEnabledForTesting(false); - loadUrlInNewTab("about:blank"); - - // Visit a site that can have a banner, then wait until the service worker is activated. - assertTrue(CriteriaHelper.pollForUIThreadCriteria( - new TabLoadObserver(getActivity().getActivityTab(), WEB_APP_URL))); - assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() { - @Override - public boolean isSatisfied() { - String url = getActivity().getActivityTab().getUrl(); - Uri uri = Uri.parse(url); - return TextUtils.equals(uri.getFragment(), "sw_activated"); - } - })); - AppBannerManager.setIsEnabledForTesting(true); - - // Revisit the site in a new tab, which will have the AppBannerManager enabled. + // Visit the site in a new tab. loadUrlInNewTab("about:blank"); assertTrue(CriteriaHelper.pollForUIThreadCriteria( new TabLoadObserver(getActivity().getActivityTab(), WEB_APP_URL))); @@ -481,27 +460,7 @@ final TestDataStorageFactory dataStorageFactory = new TestDataStorageFactory(); WebappDataStorage.setFactoryForTests(dataStorageFactory); - // Create a Tab that doesn't have the AppBannerManager enabled. This prevents race - // conditions between service worker activation and AppBannerManager getting triggered. - // This race condition is a known problem, which is why the specs include wiggle room for - // how many times a site must be visited. - AppBannerManager.setIsEnabledForTesting(false); - loadUrlInNewTab("about:blank"); - - // Visit a site that can have a banner, then wait until the service worker is activated. - assertTrue(CriteriaHelper.pollForUIThreadCriteria( - new TabLoadObserver(getActivity().getActivityTab(), WEB_APP_URL))); - assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() { - @Override - public boolean isSatisfied() { - String url = getActivity().getActivityTab().getUrl(); - Uri uri = Uri.parse(url); - return TextUtils.equals(uri.getFragment(), "sw_activated"); - } - })); - AppBannerManager.setIsEnabledForTesting(true); - - // Revisit the site in a new tab, which will have the AppBannerManager enabled. + // Visit the site in a new tab. loadUrlInNewTab("about:blank"); assertTrue(CriteriaHelper.pollForUIThreadCriteria( new TabLoadObserver(getActivity().getActivityTab(), WEB_APP_URL)));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java index f9fe987..f95dc1c5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -180,22 +180,28 @@ public void testContextMenuEntriesForImage() throws InterruptedException, TimeoutException { startCustomTabActivityWithIntent(createMinimalCustomTabIntent()); - final int expectedMenuSize = 5; + final int expectedMenuSize = 8; Menu menu = ContextMenuUtils.openContextMenu(this, getActivity().getActivityTab(), "logo"); assertEquals(expectedMenuSize, menu.size()); assertNotNull(menu.findItem(R.id.contextmenu_copy_link_address)); + assertNotNull(menu.findItem(R.id.contextmenu_copy_email_address)); assertNotNull(menu.findItem(R.id.contextmenu_copy_link_text)); assertNotNull(menu.findItem(R.id.contextmenu_save_link_as)); assertNotNull(menu.findItem(R.id.contextmenu_save_image)); + assertNotNull(menu.findItem(R.id.contextmenu_share_image)); assertNotNull(menu.findItem(R.id.contextmenu_open_image)); + assertNotNull(menu.findItem(R.id.contextmenu_save_video)); assertTrue(menu.findItem(R.id.contextmenu_save_image).isVisible()); + assertTrue(menu.findItem(R.id.contextmenu_share_image).isVisible()); assertTrue(menu.findItem(R.id.contextmenu_open_image).isVisible()); - assertTrue(!menu.findItem(R.id.contextmenu_copy_link_address).isVisible()); - assertTrue(!menu.findItem(R.id.contextmenu_copy_link_text).isVisible()); - assertTrue(!menu.findItem(R.id.contextmenu_save_link_as).isVisible()); + assertFalse(menu.findItem(R.id.contextmenu_copy_link_address).isVisible()); + assertFalse(menu.findItem(R.id.contextmenu_copy_email_address).isVisible()); + assertFalse(menu.findItem(R.id.contextmenu_copy_link_text).isVisible()); + assertFalse(menu.findItem(R.id.contextmenu_save_link_as).isVisible()); + assertFalse(menu.findItem(R.id.contextmenu_save_video).isVisible()); } /** @@ -205,23 +211,29 @@ public void testContextMenuEntriesForLink() throws InterruptedException, TimeoutException { startCustomTabActivityWithIntent(createMinimalCustomTabIntent()); - final int expectedMenuSize = 5; + final int expectedMenuSize = 8; Menu menu = ContextMenuUtils.openContextMenu(this, getActivity().getActivityTab(), "aboutLink"); assertEquals(expectedMenuSize, menu.size()); assertNotNull(menu.findItem(R.id.contextmenu_copy_link_address)); + assertNotNull(menu.findItem(R.id.contextmenu_copy_email_address)); assertNotNull(menu.findItem(R.id.contextmenu_copy_link_text)); assertNotNull(menu.findItem(R.id.contextmenu_save_link_as)); assertNotNull(menu.findItem(R.id.contextmenu_save_image)); + assertNotNull(menu.findItem(R.id.contextmenu_share_image)); assertNotNull(menu.findItem(R.id.contextmenu_open_image)); + assertNotNull(menu.findItem(R.id.contextmenu_save_video)); assertTrue(menu.findItem(R.id.contextmenu_copy_link_address).isVisible()); assertTrue(menu.findItem(R.id.contextmenu_copy_link_text).isVisible()); assertTrue(menu.findItem(R.id.contextmenu_save_link_as).isVisible()); - assertTrue(!menu.findItem(R.id.contextmenu_save_image).isVisible()); - assertTrue(!menu.findItem(R.id.contextmenu_open_image).isVisible()); + assertFalse(menu.findItem(R.id.contextmenu_share_image).isVisible()); + assertFalse(menu.findItem(R.id.contextmenu_copy_email_address).isVisible()); + assertFalse(menu.findItem(R.id.contextmenu_save_image).isVisible()); + assertFalse(menu.findItem(R.id.contextmenu_open_image).isVisible()); + assertFalse(menu.findItem(R.id.contextmenu_save_video).isVisible()); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feedback/FeedbackCollectorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feedback/FeedbackCollectorTest.java index edcd399e..286eaac 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/feedback/FeedbackCollectorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feedback/FeedbackCollectorTest.java
@@ -76,11 +76,11 @@ } @Override - public void onGotBitmap(@Nullable final Bitmap bitmap, final boolean success) { + public void onGotBitmap(@Nullable final Bitmap bitmap) { ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() { - TestFeedbackCollector.super.onGotBitmap(bitmap, success); + TestFeedbackCollector.super.onGotBitmap(bitmap); } }); } @@ -245,7 +245,7 @@ mCollector.setDescription("some description"); mCollector.add("foo", "bar"); Bitmap bitmap = createBitmap(); - mCollector.onGotBitmap(bitmap, true); + mCollector.onGotBitmap(bitmap); // Wait until the callback has been called. assertTrue("Failed to acquire semaphore.", semaphore.tryAcquire(1, TimeUnit.SECONDS)); @@ -278,7 +278,7 @@ mTestConnectivityTask.setFeedbackData(feedbackData); assertFalse("Result should not be ready after connectivity data.", hasResult.get()); Bitmap bitmap = createBitmap(); - mCollector.onGotBitmap(bitmap, true); + mCollector.onGotBitmap(bitmap); // This timeout task should trigger the callback. mCollector.setTimedOut(true); @@ -320,7 +320,7 @@ // Trigger callback by finishing taking the screenshot. Bitmap bitmap = createBitmap(); - mCollector.onGotBitmap(bitmap, true); + mCollector.onGotBitmap(bitmap); // Wait until the callback has been called. assertTrue("Failed to acquire semaphore.", semaphore.tryAcquire(1, TimeUnit.SECONDS));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java index 4e78576..1f95aaf 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java
@@ -151,7 +151,7 @@ getActivity().getActivityTab().getWebContents()); mOfflinePageBridge.savePage(getActivity().getActivityTab().getWebContents(), - BOOKMARK_ID, new SavePageCallback() { + BOOKMARK_ID, getActivity().getWindowAndroid(), new SavePageCallback() { @Override public void onSavePageDone(int savePageResult, String url) { assertEquals( @@ -190,14 +190,15 @@ ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() { - mOfflinePageBridge.deletePage(BOOKMARK_ID, new DeletePageCallback() { - @Override - public void onDeletePageDone(int deletePageResult) { - assertEquals( - "Delete result incorrect.", expectedResult, deletePageResult); - semaphore.release(); - } - }); + mOfflinePageBridge.deletePage( + BOOKMARK_ID, getActivity().getWindowAndroid(), new DeletePageCallback() { + @Override + public void onDeletePageDone(int deletePageResult) { + assertEquals("Delete result incorrect.", expectedResult, + deletePageResult); + semaphore.release(); + } + }); } }); assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
diff --git a/chrome/app/DEPS b/chrome/app/DEPS index 14c8861..cd3a112 100644 --- a/chrome/app/DEPS +++ b/chrome/app/DEPS
@@ -19,7 +19,7 @@ "+components/nacl/renderer/plugin/ppapi_entrypoints.h", "+components/nacl/zygote", "+components/policy/core/browser/android", - "+components/startup_metric_utils", + "+components/startup_metric_utils/browser", "+components/upload_list", "+components/version_info", "+content/public/app",
diff --git a/chrome/app/android/chrome_main_delegate_android.cc b/chrome/app/android/chrome_main_delegate_android.cc index dec88e9c..f4440cae 100644 --- a/chrome/app/android/chrome_main_delegate_android.cc +++ b/chrome/app/android/chrome_main_delegate_android.cc
@@ -16,7 +16,7 @@ #include "chrome/browser/android/metrics/uma_utils.h" #include "chrome/browser/media/android/remote/remote_media_player_manager.h" #include "components/policy/core/browser/android/android_combined_policy_provider.h" -#include "components/startup_metric_utils/startup_metric_utils.h" +#include "components/startup_metric_utils/browser/startup_metric_utils.h" #include "content/browser/media/android/browser_media_player_manager.h" #include "content/public/browser/browser_main_runner.h"
diff --git a/chrome/app/chrome_exe_main_win.cc b/chrome/app/chrome_exe_main_win.cc index b4af4a62..a5f8ee1 100644 --- a/chrome/app/chrome_exe_main_win.cc +++ b/chrome/app/chrome_exe_main_win.cc
@@ -15,13 +15,13 @@ #include "base/logging.h" #include "base/time/time.h" #include "base/win/windows_version.h" -#include "chrome/app/client_util.h" +#include "chrome/app/main_dll_loader_win.h" #include "chrome/browser/chrome_process_finder_win.h" #include "chrome/browser/policy/policy_path_parser.h" #include "chrome/common/chrome_paths_internal.h" #include "chrome/common/chrome_switches.h" #include "chrome_elf/chrome_elf_main.h" -#include "components/startup_metric_utils/startup_metric_utils.h" +#include "components/startup_metric_utils/browser/startup_metric_utils.h" #include "content/public/common/result_codes.h" #include "ui/gfx/win/dpi.h"
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index b6c7bac..cb27994b 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc
@@ -40,7 +40,6 @@ #include "chrome/utility/chrome_content_utility_client.h" #include "components/component_updater/component_updater_paths.h" #include "components/content_settings/core/common/content_settings_pattern.h" -#include "components/startup_metric_utils/startup_metric_utils.h" #include "components/version_info/version_info.h" #include "content/public/common/content_client.h" #include "content/public/common/content_paths.h" @@ -126,6 +125,10 @@ #include "pdf/pdf.h" #endif +#if !defined(CHROME_MULTIPLE_DLL_CHILD) +#include "components/startup_metric_utils/browser/startup_metric_utils.h" +#endif + #if !defined(CHROME_MULTIPLE_DLL_BROWSER) #include "chrome/child/pdf_child_init.h" @@ -403,9 +406,8 @@ } #endif -} // namespace - -ChromeMainDelegate::ChromeMainDelegate() { +#if !defined(CHROME_MULTIPLE_DLL_CHILD) +void RecordMainStartupMetrics() { #if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX) // Record the startup process creation time on supported platforms. startup_metric_utils::RecordStartupProcessCreationTime( @@ -421,6 +423,19 @@ startup_metric_utils::RecordMainEntryPointTime(base::Time::Now()); #endif } +#endif // !defined(CHROME_MULTIPLE_DLL_CHILD) + +} // namespace + +ChromeMainDelegate::ChromeMainDelegate() { +#if !defined(CHROME_MULTIPLE_DLL_CHILD) + // Record startup metrics in the browser process. For component builds, there + // is no way to know the type of process (process command line is not yet + // initialized), so the function below will also be called in renderers. + // This doesn't matter as it simply sets global variables. + RecordMainStartupMetrics(); +#endif // !defined(CHROME_MULTIPLE_DLL_CHILD) +} ChromeMainDelegate::~ChromeMainDelegate() { }
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index dc9b83e2..c230009c 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -66,7 +66,7 @@ Chrome cannot set wallpaper. </message> <message name="IDS_CURRENT_WALLPAPER_SET_BY_MESSAGE" desc="The string displayed to user if the current wallpaper is set by a third party wallpaper app/extension."> - Current wallpaper is set by '<ph name="APP_NAME">$1</ph>' + The current wallpaper is set by '<ph name="APP_NAME">$1</ph>'. You may need to uninstall '<ph name="APP_NAME">$1</ph>' before selecting a different wallpaper. </message> <!-- File Manager -->
diff --git a/chrome/app/client_util.cc b/chrome/app/client_util.cc deleted file mode 100644 index e12bec9..0000000 --- a/chrome/app/client_util.cc +++ /dev/null
@@ -1,376 +0,0 @@ -// Copyright (c) 2012 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 <windows.h> -#include <shlwapi.h> - -#include "base/base_paths.h" -#include "base/base_switches.h" -#include "base/command_line.h" -#include "base/compiler_specific.h" -#include "base/environment.h" -#include "base/file_version_info.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/path_service.h" -#include "base/strings/string16.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "base/trace_event/trace_event.h" -#include "base/version.h" -#include "base/win/scoped_handle.h" -#include "base/win/windows_version.h" -#include "chrome/app/chrome_crash_reporter_client.h" -#include "chrome/app/chrome_watcher_client_win.h" -#include "chrome/app/chrome_watcher_command_line_win.h" -#include "chrome/app/client_util.h" -#include "chrome/app/image_pre_reader_win.h" -#include "chrome/app/kasko_client.h" -#include "chrome/chrome_watcher/chrome_watcher_main_api.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/chrome_result_codes.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/env_vars.h" -#include "chrome/installer/util/google_update_constants.h" -#include "chrome/installer/util/google_update_settings.h" -#include "chrome/installer/util/install_util.h" -#include "chrome/installer/util/util_constants.h" -#include "components/crash/content/app/breakpad_win.h" -#include "components/crash/content/app/crash_reporter_client.h" -#include "content/public/app/sandbox_helper_win.h" -#include "content/public/common/content_switches.h" -#include "sandbox/win/src/sandbox.h" - -namespace { -// The entry point signature of chrome.dll. -typedef int (*DLL_MAIN)(HINSTANCE, sandbox::SandboxInterfaceInfo*); - -typedef void (*RelaunchChromeBrowserWithNewCommandLineIfNeededFunc)(); - -base::LazyInstance<ChromeCrashReporterClient>::Leaky g_chrome_crash_client = - LAZY_INSTANCE_INITIALIZER; - -// Loads |module| after setting the CWD to |module|'s directory. Returns a -// reference to the loaded module on success, or null on error. -HMODULE LoadModuleWithDirectory(const base::FilePath& module, bool pre_read) { - ::SetCurrentDirectoryW(module.DirName().value().c_str()); - - if (pre_read) { - // We pre-read the binary to warm the memory caches (fewer hard faults to - // page parts of the binary in). - const size_t kStepSize = 1024 * 1024; - size_t percent = 100; - ImagePreReader::PartialPreReadImage(module.value().c_str(), percent, - kStepSize); - } - - return ::LoadLibraryExW(module.value().c_str(), nullptr, - LOAD_WITH_ALTERED_SEARCH_PATH); -} - -void RecordDidRun(const base::FilePath& dll_path) { - bool system_level = !InstallUtil::IsPerUserInstall(dll_path); - GoogleUpdateSettings::UpdateDidRunState(true, system_level); -} - -void ClearDidRun(const base::FilePath& dll_path) { - bool system_level = !InstallUtil::IsPerUserInstall(dll_path); - GoogleUpdateSettings::UpdateDidRunState(false, system_level); -} - -bool InMetroMode() { - return (wcsstr( - ::GetCommandLineW(), L" -ServerName:DefaultBrowserServer") != nullptr); -} - -typedef int (*InitMetro)(); - -// Returns the directory in which the currently running executable resides. -base::FilePath GetExecutableDir() { - base::char16 path[MAX_PATH]; - ::GetModuleFileNameW(nullptr, path, MAX_PATH); - return base::FilePath(path).DirName(); -} - -} // namespace - -base::string16 GetCurrentModuleVersion() { - scoped_ptr<FileVersionInfo> file_version_info( - CREATE_FILE_VERSION_INFO_FOR_CURRENT_MODULE()); - if (file_version_info.get()) { - base::string16 version_string(file_version_info->file_version()); - if (Version(base::UTF16ToASCII(version_string)).IsValid()) - return version_string; - } - return base::string16(); -} - -//============================================================================= - -MainDllLoader::MainDllLoader() - : dll_(nullptr), metro_mode_(InMetroMode()) { -} - -MainDllLoader::~MainDllLoader() { -} - -// Loading chrome is an interesting affair. First we try loading from the -// current directory to support run-what-you-compile and other development -// scenarios. -// If that fails then we look at the version resource in the current -// module. This is the expected path for chrome.exe browser instances in an -// installed build. -HMODULE MainDllLoader::Load(base::string16* version, base::FilePath* module) { - const base::char16* dll_name = nullptr; - if (metro_mode_) { - dll_name = installer::kChromeMetroDll; - } else if (process_type_ == "service" || process_type_.empty()) { - dll_name = installer::kChromeDll; - } else if (process_type_ == "watcher") { - dll_name = kChromeWatcherDll; - } else { -#if defined(CHROME_MULTIPLE_DLL) - dll_name = installer::kChromeChildDll; -#else - dll_name = installer::kChromeDll; -#endif - } - - const bool pre_read = !metro_mode_; - base::FilePath module_dir = GetExecutableDir(); - *module = module_dir.Append(dll_name); - HMODULE dll = LoadModuleWithDirectory(*module, pre_read); - if (!dll) { - base::string16 version_string(GetCurrentModuleVersion()); - if (version_string.empty()) { - LOG(ERROR) << "No valid Chrome version found"; - return nullptr; - } - *version = version_string; - *module = module_dir.Append(version_string).Append(dll_name); - dll = LoadModuleWithDirectory(*module, pre_read); - if (!dll) { - PLOG(ERROR) << "Failed to load Chrome DLL from " << module->value(); - return nullptr; - } - } - - DCHECK(dll); - return dll; -} - -// Launching is a matter of loading the right dll, setting the CHROME_VERSION -// environment variable and just calling the entry point. Derived classes can -// add custom code in the OnBeforeLaunch callback. -int MainDllLoader::Launch(HINSTANCE instance) { - const base::CommandLine& cmd_line = *base::CommandLine::ForCurrentProcess(); - process_type_ = cmd_line.GetSwitchValueASCII(switches::kProcessType); - - base::string16 version; - base::FilePath file; - - if (metro_mode_) { - HMODULE metro_dll = Load(&version, &file); - if (!metro_dll) - return chrome::RESULT_CODE_MISSING_DATA; - - InitMetro chrome_metro_main = - reinterpret_cast<InitMetro>(::GetProcAddress(metro_dll, "InitMetro")); - return chrome_metro_main(); - } - - if (process_type_ == "watcher") { - chrome::RegisterPathProvider(); - - base::win::ScopedHandle parent_process; - base::win::ScopedHandle on_initialized_event; - DWORD main_thread_id = 0; - if (!InterpretChromeWatcherCommandLine(cmd_line, &parent_process, - &main_thread_id, - &on_initialized_event)) { - return chrome::RESULT_CODE_UNSUPPORTED_PARAM; - } - - base::FilePath default_user_data_directory; - if (!PathService::Get(chrome::DIR_USER_DATA, &default_user_data_directory)) - return chrome::RESULT_CODE_MISSING_DATA; - // The actual user data directory may differ from the default according to - // policy and command-line arguments evaluated in the browser process. - // The hang monitor will simply be disabled if a window with this name is - // never instantiated by the browser process. Since this should be - // exceptionally rare it should not impact stability efforts. - base::string16 message_window_name = default_user_data_directory.value(); - - base::FilePath watcher_data_directory; - if (!PathService::Get(chrome::DIR_WATCHER_DATA, &watcher_data_directory)) - return chrome::RESULT_CODE_MISSING_DATA; - - base::string16 channel_name = GoogleUpdateSettings::GetChromeChannel( - !InstallUtil::IsPerUserInstall(cmd_line.GetProgram())); - - // Intentionally leaked. - HMODULE watcher_dll = Load(&version, &file); - if (!watcher_dll) - return chrome::RESULT_CODE_MISSING_DATA; - - ChromeWatcherMainFunction watcher_main = - reinterpret_cast<ChromeWatcherMainFunction>( - ::GetProcAddress(watcher_dll, kChromeWatcherDLLEntrypoint)); - return watcher_main(chrome::kBrowserExitCodesRegistryPath, - parent_process.Take(), main_thread_id, - on_initialized_event.Take(), - watcher_data_directory.value().c_str(), - message_window_name.c_str(), channel_name.c_str()); - } - - // Initialize the sandbox services. - sandbox::SandboxInterfaceInfo sandbox_info = {0}; - content::InitializeSandboxInfo(&sandbox_info); - - crash_reporter::SetCrashReporterClient(g_chrome_crash_client.Pointer()); - bool exit_now = true; - if (process_type_.empty()) { - if (breakpad::ShowRestartDialogIfCrashed(&exit_now)) { - // We restarted because of a previous crash. Ask user if we should - // Relaunch. Only for the browser process. See crbug.com/132119. - if (exit_now) - return content::RESULT_CODE_NORMAL_EXIT; - } - } - breakpad::InitCrashReporter(process_type_); - - dll_ = Load(&version, &file); - if (!dll_) - return chrome::RESULT_CODE_MISSING_DATA; - - scoped_ptr<base::Environment> env(base::Environment::Create()); - env->SetVar(chrome::kChromeVersionEnvVar, base::WideToUTF8(version)); - - OnBeforeLaunch(process_type_, file); - DLL_MAIN chrome_main = - reinterpret_cast<DLL_MAIN>(::GetProcAddress(dll_, "ChromeMain")); - int rc = chrome_main(instance, &sandbox_info); - rc = OnBeforeExit(rc, file); - // Sandboxed processes close some system DLL handles after lockdown so ignore - // EXCEPTION_INVALID_HANDLE generated on Windows 10 during shutdown of these - // processes. - // TODO(wfh): Check whether MS have fixed this in Win10 RTM. crbug.com/456193 - if (base::win::GetVersion() >= base::win::VERSION_WIN10) - breakpad::ConsumeInvalidHandleExceptions(); - return rc; -} - -void MainDllLoader::RelaunchChromeBrowserWithNewCommandLineIfNeeded() { - if (!dll_) - return; - - RelaunchChromeBrowserWithNewCommandLineIfNeededFunc relaunch_function = - reinterpret_cast<RelaunchChromeBrowserWithNewCommandLineIfNeededFunc>( - ::GetProcAddress(dll_, - "RelaunchChromeBrowserWithNewCommandLineIfNeeded")); - if (!relaunch_function) { - LOG(ERROR) << "Could not find exported function " - << "RelaunchChromeBrowserWithNewCommandLineIfNeeded"; - } else { - relaunch_function(); - } -} - -//============================================================================= - -class ChromeDllLoader : public MainDllLoader { - protected: - // MainDllLoader implementation. - void OnBeforeLaunch(const std::string& process_type, - const base::FilePath& dll_path) override; - int OnBeforeExit(int return_code, const base::FilePath& dll_path) override; - - private: - scoped_ptr<ChromeWatcherClient> chrome_watcher_client_; -#if defined(KASKO) - scoped_ptr<KaskoClient> kasko_client_; -#endif // KASKO -}; - -void ChromeDllLoader::OnBeforeLaunch(const std::string& process_type, - const base::FilePath& dll_path) { - if (process_type.empty()) { - RecordDidRun(dll_path); - - // Launch the watcher process if stats collection consent has been granted. - if (g_chrome_crash_client.Get().GetCollectStatsConsent()) { - base::FilePath exe_path; - if (PathService::Get(base::FILE_EXE, &exe_path)) { - chrome_watcher_client_.reset(new ChromeWatcherClient( - base::Bind(&GenerateChromeWatcherCommandLine, exe_path))); - if (chrome_watcher_client_->LaunchWatcher()) { -#if defined(KASKO) - kasko::api::MinidumpType minidump_type = kasko::api::SMALL_DUMP_TYPE; - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kFullMemoryCrashReport)) { - minidump_type = kasko::api::FULL_DUMP_TYPE; - } else { - bool is_per_user_install = - g_chrome_crash_client.Get().GetIsPerUserInstall( - base::FilePath(exe_path)); - if (g_chrome_crash_client.Get().GetShouldDumpLargerDumps( - is_per_user_install)) { - minidump_type = kasko::api::LARGER_DUMP_TYPE; - } - } - - kasko_client_.reset( - new KaskoClient(chrome_watcher_client_.get(), minidump_type)); -#endif // KASKO - } - } - } - } else { - // Set non-browser processes up to be killed by the system after the browser - // goes away. The browser uses the default shutdown order, which is 0x280. - // Note that lower numbers here denote "kill later" and higher numbers mean - // "kill sooner". - // This gets rid of most of those unsighly sad tabs on logout and shutdown. - ::SetProcessShutdownParameters(0x280 - 1, SHUTDOWN_NORETRY); - } -} - -int ChromeDllLoader::OnBeforeExit(int return_code, - const base::FilePath& dll_path) { - // NORMAL_EXIT_CANCEL is used for experiments when the user cancels - // so we need to reset the did_run signal so omaha does not count - // this run as active usage. - if (chrome::RESULT_CODE_NORMAL_EXIT_CANCEL == return_code) { - ClearDidRun(dll_path); - } - -#if defined(KASKO) - kasko_client_.reset(); -#endif // KASKO - chrome_watcher_client_.reset(); - - return return_code; -} - -//============================================================================= - -class ChromiumDllLoader : public MainDllLoader { - protected: - void OnBeforeLaunch(const std::string& process_type, - const base::FilePath& dll_path) override {} - int OnBeforeExit(int return_code, const base::FilePath& dll_path) override { - return return_code; - } -}; - -MainDllLoader* MakeMainDllLoader() { -#if defined(GOOGLE_CHROME_BUILD) - return new ChromeDllLoader(); -#else - return new ChromiumDllLoader(); -#endif -}
diff --git a/chrome/app/client_util.h b/chrome/app/client_util.h deleted file mode 100644 index de09a667..0000000 --- a/chrome/app/client_util.h +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright (c) 2012 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. - -// This file defines utility functions that can report details about the -// host operating environment. - -#ifndef CHROME_APP_CLIENT_UTIL_H_ -#define CHROME_APP_CLIENT_UTIL_H_ - -#include <windows.h> - -#include <string> -#include "base/strings/string16.h" - -namespace sandbox { - struct SandboxInterfaceInfo; -} - -// Returns the version in the current module's version resource or the empty -// string if none found. -base::string16 GetCurrentModuleVersion(); - -// Implements the common aspects of loading the main dll for both chrome and -// chromium scenarios, which are in charge of implementing two abstract -// methods: GetRegistryPath() and OnBeforeLaunch(). -class MainDllLoader { - public: - MainDllLoader(); - virtual ~MainDllLoader(); - - // Loads and calls the entry point of chrome.dll. |instance| is the exe - // instance retrieved from wWinMain. - // The return value is what the main entry point of chrome.dll returns - // upon termination. - int Launch(HINSTANCE instance); - - // Launches a new instance of the browser if the current instance in - // persistent mode an upgrade is detected. - void RelaunchChromeBrowserWithNewCommandLineIfNeeded(); - - protected: - // Called after chrome.dll has been loaded but before the entry point - // is invoked. Derived classes can implement custom actions here. - // |process_type| is the argument to the --type command line argument, e.g. - // "renderer", "watcher", etc. - // |dll_path| refers to the path of the Chrome dll being loaded. - virtual void OnBeforeLaunch(const std::string& process_type, - const base::FilePath& dll_path) = 0; - - // Called after the chrome.dll entry point returns and before terminating - // this process. The return value will be used as the process return code. - // |dll_path| refers to the path of the Chrome dll being loaded. - virtual int OnBeforeExit(int return_code, const base::FilePath& dll_path) = 0; - - private: - // Loads chrome.dll, populating |version| with the version of the DLL loaded - // and |module| with the path of the loaded DLL. Returns a reference to the - // module, or null on failure. - HMODULE Load(base::string16* version, base::FilePath* module); - - private: - HMODULE dll_; - std::string process_type_; - const bool metro_mode_; -}; - -// Factory for the MainDllLoader. Caller owns the pointer and should call -// delete to free it. -MainDllLoader* MakeMainDllLoader(); - -#endif // CHROME_APP_CLIENT_UTIL_H_
diff --git a/chrome/app/file_pre_reader_win.cc b/chrome/app/file_pre_reader_win.cc new file mode 100644 index 0000000..8b410e00 --- /dev/null +++ b/chrome/app/file_pre_reader_win.cc
@@ -0,0 +1,80 @@ +// Copyright (c) 2012 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/app/file_pre_reader_win.h" + +#include <windows.h> + +#include "base/files/file.h" +#include "base/files/memory_mapped_file.h" +#include "base/logging.h" +#include "base/threading/thread_restrictions.h" +#include "base/win/windows_version.h" + +namespace { + +// A helper function to touch all pages in the range +// [base_addr, base_addr + length). +void TouchPagesInRange(const void* base_addr, size_t length) { + DCHECK(base_addr); + DCHECK_GT(length, static_cast<size_t>(0)); + + // Get the system info so we know the page size. Also, make sure we use a + // non-zero value for the page size; GetSystemInfo() is hookable/patchable, + // and you never know what shenanigans someone could get up to. + SYSTEM_INFO system_info = {}; + ::GetSystemInfo(&system_info); + if (system_info.dwPageSize == 0) + system_info.dwPageSize = 4096; + + // We don't want to read outside the byte range (which could trigger an + // access violation), so let's figure out the exact locations of the first + // and final bytes we want to read. + volatile uint8_t const* touch_ptr = + reinterpret_cast<uint8_t const*>(base_addr); + volatile uint8_t const* final_touch_ptr = touch_ptr + length - 1; + + // Read the memory in the range [touch_ptr, final_touch_ptr] with a stride + // of the system page size, to ensure that it's been paged in. + uint8_t dummy; + for (; touch_ptr < final_touch_ptr; touch_ptr += system_info.dwPageSize) + dummy = *touch_ptr; + dummy = *final_touch_ptr; +} + +} // namespace + +bool PreReadFile(const base::FilePath& file_path, int step_size) { + DCHECK_GT(step_size, 0); + base::ThreadRestrictions::AssertIOAllowed(); + + if (base::win::GetVersion() > base::win::VERSION_XP) { + // Vista+ branch. On these OSes, the forced reads through the DLL actually + // slows warm starts. The solution is to sequentially read file contents. + base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ | + base::File::FLAG_SEQUENTIAL_SCAN); + if (!file.IsValid()) + return false; + + char* buffer = reinterpret_cast<char*>(::VirtualAlloc( + nullptr, static_cast<DWORD>(step_size), MEM_COMMIT, PAGE_READWRITE)); + if (!buffer) + return false; + + while (file.ReadAtCurrentPos(buffer, step_size) > 0) {} + + ::VirtualFree(buffer, 0, MEM_RELEASE); + } else { + // WinXP branch. Here, reading the DLL from disk doesn't do what we want so + // instead we pull the pages into memory and touch pages at a stride. We use + // the system's page size as the stride, ignoring the passed in step_size, + // to make sure each page in the range is touched. + base::MemoryMappedFile file_memory_map; + if (!file_memory_map.Initialize(file_path)) + return false; + TouchPagesInRange(file_memory_map.data(), file_memory_map.length()); + } + + return true; +}
diff --git a/chrome/app/file_pre_reader_win.h b/chrome/app/file_pre_reader_win.h new file mode 100644 index 0000000..4ca0a1f --- /dev/null +++ b/chrome/app/file_pre_reader_win.h
@@ -0,0 +1,23 @@ +// Copyright (c) 2012 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. + +// This file defines a function to pre-read a file in order to avoid touching +// the disk when it is subsequently used. + +#ifndef CHROME_APP_FILE_PRE_READER_WIN_H_ +#define CHROME_APP_FILE_PRE_READER_WIN_H_ + +namespace base { +class FilePath; +} + +// Reads |file_path| to avoid touching the disk when the file is actually used. +// The function checks the Windows version to determine which pre-reading +// mechanism to use. On Vista+, chunks of |step_size| bytes are read into a +// buffer. The bigger |step_size| is, the faster the file is pre-read (up to +// about 4MB according to local tests), but also the more memory is allocated +// for the buffer. +bool PreReadFile(const base::FilePath& file_path, int step_size); + +#endif // CHROME_APP_FILE_PRE_READER_WIN_H_
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 1e32cde..3c0d2fa 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -5479,6 +5479,12 @@ <message name="IDS_FLAGS_ENABLE_FAST_UNLOAD_NAME" desc="Name of the 'Extensions on chrome:// URLs' lab"> Enable fast tab/window close </message> + <message name="IDS_FLAGS_DISABLE_DISTILLER_IN_PRINT_PREVIEW_NAME" desc="Name of the 'disable simplify on print preview' lab"> + Disable simplify page on print preview + </message> + <message name="IDS_FLAGS_DISABLE_DISTILLER_IN_PRINT_PREVIEW_DESCRIPTION" desc="Description of the 'disable simplify on print preview' lab"> + Disable the simplify page check box on the print preview dialog + </message> <message name="IDS_FLAGS_ENABLE_APP_WINDOW_CONTROLS_NAME" desc="Name of the 'Enable 'window-controls' element' lab."> Enable 'window-controls' element </message> @@ -6656,6 +6662,12 @@ <message name="IDS_FLAGS_PPAPI_WIN32K_LOCKDOWN_ALL" desc="Enable Win32k lockdown for all plugins"> All plugins </message> + <message name="IDS_FLAGS_ENABLE_APPCONTAINER_NAME" desc="Name of the flag to enable AppContainer lockdown experiment."> + Enable AppContainer Lockdown. + </message> + <message name="IDS_FLAGS_ENABLE_APPCONTAINER_DESCRIPTION" desc="Description of the flag to enable AppContainer lockdown experiment."> + Enables the use of an AppContainer on sandboxed processes to improve security. + </message> </if> <!-- WebRTC logs --> @@ -7682,18 +7694,23 @@ </message> <message name="IDS_DEL_BROWSING_HISTORY_COUNTER" desc="A counter showing how many items of browsing history the user has."> {COUNT, plural, + =0 {none} =1 {1 item} other {# items}} </message> - <message name="IDS_DEL_CACHE_COUNTER" desc="A counter showing how many kBs of cached data the user has."> + <message name="IDS_DEL_BROWSING_HISTORY_COUNTER_SYNCED" desc="A counter showing the user how many local items of browsing history they have, and informing them that more items might be synced. In the case when COUNT is zero, the counter only mentions existence of synced items."> {COUNT, plural, - =1 {1 kB} - other {# kB}} + =0 {at least 1 item on synced devices} + =1 {1 item (and more on synced devices)} + other {# items (and more on synced devices)}} + </message> + <message name="IDS_DEL_CACHE_COUNTER_UPPER_ESTIMATE" desc="A counter showing that the user has less than X megabytes of cache. The value X will be substituted."> + less than <ph name="UPPER_ESTIMATE">$1<ex>328 MB</ex></ph> </message> <message name="IDS_DEL_PASSWORDS_COUNTER" desc="A counter showing how many passwords the user has."> {COUNT, plural, - =1 {1 password} - other {# passwords}} + =0 {none} + other {#}} </message> <!-- Supervised User (Legacy and Accounts for Kids) Avatar Menu --> @@ -15266,14 +15283,6 @@ </if> <if expr="not is_android and not is_ios"> - <!-- WebUsb Notifications Flag --> - <message name="IDS_FLAGS_ENABLE_WEBUSB_NOTIFICATIONS_NAME" desc="Title for the flag which enables WebUsb notifications."> - WebUsb notifications. - </message> - <message name="IDS_FLAGS_ENABLE_WEBUSB_NOTIFICATIONS_DESCRIPTION" desc="Description for the flag which enables WebUsb notifications."> - Experimental WebUsb notifications. - </message> - <!-- WebUSB permission bypass flag. --> <message name="IDS_FLAGS_ENABLE_WEBUSB_ON_ANY_ORIGIN_NAME" desc="Title for the flag that bypasses WebUSB permission prompts."> Allow WebUSB from any origin.
diff --git a/chrome/app/image_pre_reader_win.cc b/chrome/app/image_pre_reader_win.cc deleted file mode 100644 index 9998a036..0000000 --- a/chrome/app/image_pre_reader_win.cc +++ /dev/null
@@ -1,419 +0,0 @@ -// Copyright (c) 2012 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/app/image_pre_reader_win.h" - -#include <windows.h> -#include <algorithm> -#include <limits> -#include <vector> - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/threading/thread_restrictions.h" -#include "base/win/pe_image.h" -#include "base/win/scoped_handle.h" -#include "base/win/windows_version.h" - -namespace { - -// The minimum buffer size to allocate when reading the PE file headers. -// -// The PE file headers usually fit into a single 1KB page, and a PE file must -// at least contain the initial page with the headers. That said, as long as -// we expect at least sizeof(IMAGE_DOS_HEADER) bytes, we're ok. -const size_t kMinHeaderBufferSize = 0x400; - -// A handy symbolic constant. -const size_t kOneHundredPercent = 100; - -static_assert(kMinHeaderBufferSize >= sizeof(IMAGE_DOS_HEADER), - "kMinHeaderBufferSize must be at least as big as the dos header"); - -// This struct provides a deallocation functor for use with scoped_ptr<T> -// allocated with ::VirtualAlloc(). -struct VirtualFreeDeleter { - void operator() (void* ptr) { - ::VirtualFree(ptr, 0, MEM_RELEASE); - } -}; - -// A wrapper for the Win32 ::SetFilePointer() function with some error checking. -bool SetFilePointer(HANDLE file_handle, size_t position) { - return position <= static_cast<size_t>(std::numeric_limits<LONG>::max()) && - ::SetFilePointer(file_handle, - static_cast<LONG>(position), - NULL, - FILE_BEGIN) != INVALID_SET_FILE_POINTER; -} - -// A helper function to read the next |bytes_to_read| bytes from the file -// given by |file_handle| into |buffer|. -bool ReadNextBytes(HANDLE file_handle, void* buffer, size_t bytes_to_read) { - DCHECK(file_handle != INVALID_HANDLE_VALUE); - DCHECK(buffer != NULL); - DCHECK(bytes_to_read > 0); - - DWORD bytes_read = 0; - return bytes_to_read <= std::numeric_limits<DWORD>::max() && - ::ReadFile(file_handle, - buffer, - static_cast<DWORD>(bytes_to_read), - &bytes_read, - NULL) && - bytes_read == bytes_to_read; -} - -// A helper function to extend the |current_buffer| of bytes such that it -// contains |desired_length| bytes read from the file given by |file_handle|. -// -// It is assumed that |file_handle| has been used to sequentially populate -// |current_buffer| thus far and is already positioned at the appropriate -// read location. -bool ReadMissingBytes(HANDLE file_handle, - std::vector<uint8>* current_buffer, - size_t desired_length) { - DCHECK(file_handle != INVALID_HANDLE_VALUE); - DCHECK(current_buffer != NULL); - - size_t current_length = current_buffer->size(); - if (current_length >= desired_length) - return true; - - size_t bytes_to_read = desired_length - current_length; - current_buffer->resize(desired_length); - return ReadNextBytes(file_handle, - &(current_buffer->at(current_length)), - bytes_to_read); -} - -// Return a |percentage| of the number of initialized bytes in the given -// |section|. -// -// This returns a percentage of the lesser of the size of the raw data in -// the section and the virtual size of the section. -// -// Note that sections can have their tails implicitly initialized to zero -// (i.e., their virtual size is larger than the raw size) and that raw data -// is padded to the PE page size if the entire section is initialized (i.e., -// their raw data size will be larger than the virtual size). -// -// Any data after the initialized portion of the section will be soft-faulted -// in (very quickly) as needed, so we don't need to include it in the returned -// length. -size_t GetPercentageOfSectionLength(const IMAGE_SECTION_HEADER* section, - size_t percentage) { - DCHECK(section != NULL); - DCHECK_GT(percentage, 0u); - DCHECK_LE(percentage, kOneHundredPercent); - - size_t initialized_length = std::min(section->SizeOfRawData, - section->Misc.VirtualSize); - - if (initialized_length == 0) - return 0; - - size_t length = (initialized_length * percentage) / kOneHundredPercent; - - return std::max<size_t>(length, 1); -} - -// Helper function to read through a |percentage| of the given |section| -// of the file denoted by |file_handle|. The |temp_buffer| is (re)used as -// a transient storage area as the section is read in chunks of -// |temp_buffer_size| bytes. -bool ReadThroughSection(HANDLE file_handle, - const IMAGE_SECTION_HEADER* section, - size_t percentage, - void* temp_buffer, - size_t temp_buffer_size) { - DCHECK(file_handle != INVALID_HANDLE_VALUE); - DCHECK(section != NULL); - DCHECK_LE(percentage, kOneHundredPercent); - DCHECK(temp_buffer != NULL); - DCHECK(temp_buffer_size > 0); - - size_t bytes_to_read = GetPercentageOfSectionLength(section, percentage); - if (bytes_to_read == 0) - return true; - - if (!SetFilePointer(file_handle, section->PointerToRawData)) - return false; - - // Read all chunks except the last one. - while (bytes_to_read > temp_buffer_size) { - if (!ReadNextBytes(file_handle, temp_buffer, temp_buffer_size)) - return false; - bytes_to_read -= temp_buffer_size; - } - - // Read the last (possibly partial) chunk and return. - DCHECK(bytes_to_read > 0); - DCHECK(bytes_to_read <= temp_buffer_size); - return ReadNextBytes(file_handle, temp_buffer, bytes_to_read); -} - -// A helper function to touch all pages in the range -// [base_addr, base_addr + length). -void TouchPagesInRange(void* base_addr, size_t length) { - DCHECK(base_addr != NULL); - DCHECK(length > 0); - - // Get the system info so we know the page size. Also, make sure we use a - // non-zero value for the page size; GetSystemInfo() is hookable/patchable, - // and you never know what shenanigans someone could get up to. - SYSTEM_INFO system_info = {}; - GetSystemInfo(&system_info); - if (system_info.dwPageSize == 0) - system_info.dwPageSize = 4096; - - // We don't want to read outside the byte range (which could trigger an - // access violation), so let's figure out the exact locations of the first - // and final bytes we want to read. - volatile uint8* touch_ptr = reinterpret_cast<uint8*>(base_addr); - volatile uint8* final_touch_ptr = touch_ptr + length - 1; - - // Read the memory in the range [touch_ptr, final_touch_ptr] with a stride - // of the system page size, to ensure that it's been paged in. - uint8 dummy; - while (touch_ptr < final_touch_ptr) { - dummy = *touch_ptr; - touch_ptr += system_info.dwPageSize; - } - dummy = *final_touch_ptr; -} - -} // namespace - -bool ImagePreReader::PartialPreReadImageOnDisk(const wchar_t* file_path, - size_t percentage, - size_t max_chunk_size) { - // TODO(rogerm): change this to have the number of bytes pre-read per - // section be driven by a static table within the PE file (defaulting to - // full read if it's not there?) that's initialized by the optimization - // toolchain. - DCHECK(file_path != NULL); - - if (percentage == 0) - return true; - - if (percentage > kOneHundredPercent) - percentage = kOneHundredPercent; - - // Validate/setup max_chunk_size, imposing a 1MB minimum on the chunk size. - const size_t kMinChunkSize = 1024 * 1024; - max_chunk_size = std::max(max_chunk_size, kMinChunkSize); - - // Open the file. - base::win::ScopedHandle file( - CreateFile(file_path, - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_FLAG_SEQUENTIAL_SCAN, - NULL)); - - if (!file.IsValid()) - return false; - - // Allocate a resizable buffer for the headers. We initially reserve as much - // space as we typically see as the header size for chrome.dll and other - // PE images. - std::vector<uint8> headers; - headers.reserve(kMinHeaderBufferSize); - - // Read, hopefully, all of the headers. - if (!ReadMissingBytes(file.Get(), &headers, kMinHeaderBufferSize)) - return false; - - // The DOS header starts at offset 0 and allows us to get the offset of the - // NT headers. Let's ensure we've read enough to capture the NT headers. - size_t nt_headers_start = - reinterpret_cast<IMAGE_DOS_HEADER*>(&headers[0])->e_lfanew; - size_t nt_headers_end = nt_headers_start + sizeof(IMAGE_NT_HEADERS); - if (!ReadMissingBytes(file.Get(), &headers, nt_headers_end)) - return false; - - // Now that we've got the NT headers we can get the total header size, - // including all of the section headers. Let's ensure we've read enough - // to capture all of the header data. - size_t size_of_headers = reinterpret_cast<IMAGE_NT_HEADERS*>( - &headers[nt_headers_start])->OptionalHeader.SizeOfHeaders; - if (!ReadMissingBytes(file.Get(), &headers, size_of_headers)) - return false; - - // Now we have all of the headers. This is enough to let us use the PEImage - // wrapper to query the structure of the image. - base::win::PEImage pe_image(reinterpret_cast<HMODULE>(&headers[0])); - CHECK(pe_image.VerifyMagic()); - - // Allocate a buffer to hold the pre-read bytes. - scoped_ptr<uint8, VirtualFreeDeleter> buffer( - static_cast<uint8*>( - ::VirtualAlloc(NULL, max_chunk_size, MEM_COMMIT, PAGE_READWRITE))); - if (buffer.get() == NULL) - return false; - - // Iterate over each section, reading in a percentage of each. - const IMAGE_SECTION_HEADER* section = NULL; - for (UINT i = 0; (section = pe_image.GetSectionHeader(i)) != NULL; ++i) { - CHECK_LE(reinterpret_cast<const uint8*>(section + 1), - &headers[0] + headers.size()); - if (!ReadThroughSection(file.Get(), section, percentage, buffer.get(), - max_chunk_size)) { - return false; - } - } - - // We're done. - return true; -} - -bool ImagePreReader::PartialPreReadImageInMemory(const wchar_t* file_path, - size_t percentage) { - // TODO(rogerm): change this to have the number of bytes pre-read per - // section be driven by a static table within the PE file (defaulting to - // full read if it's not there?) that's initialized by the optimization - // toolchain. - DCHECK(file_path != NULL); - - if (percentage == 0) - return true; - - if (percentage > kOneHundredPercent) - percentage = kOneHundredPercent; - - HMODULE dll_module = ::LoadLibraryExW( - file_path, - NULL, - LOAD_WITH_ALTERED_SEARCH_PATH | DONT_RESOLVE_DLL_REFERENCES); - - if (!dll_module) - return false; - - base::win::PEImage pe_image(dll_module); - CHECK(pe_image.VerifyMagic()); - - // Iterate over each section, stepping through a percentage of each to page - // it in off the disk. - const IMAGE_SECTION_HEADER* section = NULL; - for (UINT i = 0; (section = pe_image.GetSectionHeader(i)) != NULL; ++i) { - // Get the extent we want to touch. - size_t length = GetPercentageOfSectionLength(section, percentage); - if (length == 0) - continue; - uint8* start = - static_cast<uint8*>(pe_image.RVAToAddr(section->VirtualAddress)); - - // Verify that the extent we're going to touch falls inside the section - // we expect it to (and by implication, inside the pe_image). - CHECK_EQ(section, - pe_image.GetImageSectionFromAddr(start)); - CHECK_EQ(section, - pe_image.GetImageSectionFromAddr(start + length - 1)); - - // Page in the section range. - TouchPagesInRange(start, length); - } - - FreeLibrary(dll_module); - - return true; -} - -bool ImagePreReader::PreReadImage(const wchar_t* file_path, - size_t size_to_read, - size_t step_size) { - base::ThreadRestrictions::AssertIOAllowed(); - if (base::win::GetVersion() > base::win::VERSION_XP) { - // Vista+ branch. On these OSes, the forced reads through the DLL actually - // slows warm starts. The solution is to sequentially read file contents - // with an optional cap on total amount to read. - base::win::ScopedHandle file( - CreateFile(file_path, - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_FLAG_SEQUENTIAL_SCAN, - NULL)); - - if (!file.IsValid()) - return false; - - // Default to 1MB sequential reads. - const DWORD actual_step_size = std::max(static_cast<DWORD>(step_size), - static_cast<DWORD>(1024*1024)); - LPVOID buffer = ::VirtualAlloc(NULL, - actual_step_size, - MEM_COMMIT, - PAGE_READWRITE); - - if (buffer == NULL) - return false; - - DWORD len; - size_t total_read = 0; - while (::ReadFile(file.Get(), buffer, actual_step_size, &len, NULL) && - len > 0 && - (size_to_read ? total_read < size_to_read : true)) { - total_read += static_cast<size_t>(len); - } - ::VirtualFree(buffer, 0, MEM_RELEASE); - } else { - // WinXP branch. Here, reading the DLL from disk doesn't do - // what we want so instead we pull the pages into memory by loading - // the DLL and touching pages at a stride. We use the system's page - // size as the stride, ignoring the passed in step_size, to make sure - // each page in the range is touched. - HMODULE dll_module = ::LoadLibraryExW( - file_path, - NULL, - LOAD_WITH_ALTERED_SEARCH_PATH | DONT_RESOLVE_DLL_REFERENCES); - - if (!dll_module) - return false; - - base::win::PEImage pe_image(dll_module); - CHECK(pe_image.VerifyMagic()); - - // We don't want to read past the end of the module (which could trigger - // an access violation), so make sure to check the image size. - PIMAGE_NT_HEADERS nt_headers = pe_image.GetNTHeaders(); - size_t dll_module_length = std::min( - size_to_read ? size_to_read : ~0, - static_cast<size_t>(nt_headers->OptionalHeader.SizeOfImage)); - - // Page in then release the module. - TouchPagesInRange(dll_module, dll_module_length); - FreeLibrary(dll_module); - } - - return true; -} - -bool ImagePreReader::PartialPreReadImage(const wchar_t* file_path, - size_t percentage, - size_t max_chunk_size) { - base::ThreadRestrictions::AssertIOAllowed(); - - if (percentage >= kOneHundredPercent) { - // If we're reading the whole image, we don't need to parse headers and - // navigate sections, the basic PreReadImage() can be used to just step - // blindly through the entire file / address-space. - return PreReadImage(file_path, 0, max_chunk_size); - } - - if (base::win::GetVersion() > base::win::VERSION_XP) { - // Vista+ branch. On these OSes, we warm up the Image by reading its - // file off the disk. - return PartialPreReadImageOnDisk(file_path, percentage, max_chunk_size); - } - - // WinXP branch. For XP, reading the image from disk doesn't do what we want - // so instead we pull the pages into memory by loading the DLL and touching - // initialized pages at a stride. - return PartialPreReadImageInMemory(file_path, percentage); -}
diff --git a/chrome/app/image_pre_reader_win.h b/chrome/app/image_pre_reader_win.h deleted file mode 100644 index e32e0190..0000000 --- a/chrome/app/image_pre_reader_win.h +++ /dev/null
@@ -1,73 +0,0 @@ -// Copyright (c) 2012 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. - -// This file defines utility functions to pre-read a PE Image in order to -// avoid hard page faults when the image is subsequently loaded into memory -// for execution. - -#ifndef CHROME_APP_IMAGE_PRE_READER_WIN_H_ -#define CHROME_APP_IMAGE_PRE_READER_WIN_H_ - -#include "base/basictypes.h" - -// This class defines static helper functions to pre-read a PE Image in order -// to avoid hard page faults when the image is subsequently loaded into memory -// for execution. -class ImagePreReader { - public: - // Reads the file passed in as a PE Image and touches pages to avoid - // subsequent hard page faults during LoadLibrary. The size to be pre-read - // is passed in. If it is 0 then the whole file is paged in. The step size - // which indicates the number of bytes to skip after every page touched is - // also passed in. - // - // This function checks the Windows version to determine which pre-reading - // mechanism to use. - static bool PreReadImage(const wchar_t* file_path, - size_t size_to_read, - size_t step_size); - - // Loads the file passed in as PE Image and touches a percentage of the - // pages in each of the image's sections to avoid subsequent hard page - // faults during LoadLibrary. - // - // This function checks the Windows version to determine which pre-reading - // mechanism to use. - // - // The percentage of the file to be read is an integral value between 0 and - // 100, inclusive. If it is 0 then this is a NOP, if it is 100 (or greater) - // then the whole file is paged in sequentially via PreReadImage. Otherwise, - // for each section, in order, the given percentage of the blocks in that - // section are paged in, starting at the beginning of each section. For - // example: if percentage is 30 and there is a .text section and a .data - // section, then the first 30% of .text will be paged and the first 30% of - // .data will be paged in. - // - // The max_chunk_size indicates the number of bytes to read off the disk in - // each step (for Vista and greater, where this is the way the pages are - // warmed). - // - // This function is intended to be used in the context of a PE image with - // an optimized layout, such that the blocks in each section are arranged - // with the data and code most needed for startup moved to the front. - // See also: http://code.google.com/p/chromium/issues/detail?id=98508 - static bool PartialPreReadImage(const wchar_t* file_path, - size_t percentage, - size_t max_chunk_size); - - // Helper function used by PartialPreReadImage on Windows versions (Vista+) - // where reading through the file on disk serves to warm up the page cache. - // Exported for unit-testing purposes. - static bool PartialPreReadImageOnDisk(const wchar_t* file_path, - size_t percentage, - size_t max_chunk_size); - - // Helper function used by PartialPreReadImage on Windows versions (XP) where - // cheaply loading the image then stepping through its address space serves - // to warm up the page cache. Exported for unit-testing purposes. - static bool PartialPreReadImageInMemory(const wchar_t* file_path, - size_t percentage); -}; // namespace internal - -#endif // CHROME_APP_IMAGE_PRE_READER_WIN_H_
diff --git a/chrome/app/main_dll_loader_win.cc b/chrome/app/main_dll_loader_win.cc new file mode 100644 index 0000000..ba14dba --- /dev/null +++ b/chrome/app/main_dll_loader_win.cc
@@ -0,0 +1,349 @@ +// Copyright (c) 2012 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 <windows.h> // NOLINT +#include <shlwapi.h> // NOLINT + +#include "chrome/app/main_dll_loader_win.h" + +#include "base/base_paths.h" +#include "base/base_switches.h" +#include "base/command_line.h" +#include "base/compiler_specific.h" +#include "base/environment.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/path_service.h" +#include "base/strings/string16.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "base/trace_event/trace_event.h" +#include "base/win/scoped_handle.h" +#include "base/win/windows_version.h" +#include "chrome/app/chrome_crash_reporter_client.h" +#include "chrome/app/chrome_watcher_client_win.h" +#include "chrome/app/chrome_watcher_command_line_win.h" +#include "chrome/app/file_pre_reader_win.h" +#include "chrome/app/kasko_client.h" +#include "chrome/chrome_watcher/chrome_watcher_main_api.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_result_codes.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/env_vars.h" +#include "chrome/installer/util/google_update_constants.h" +#include "chrome/installer/util/google_update_settings.h" +#include "chrome/installer/util/install_util.h" +#include "chrome/installer/util/module_util_win.h" +#include "chrome/installer/util/util_constants.h" +#include "components/crash/content/app/breakpad_win.h" +#include "components/crash/content/app/crash_reporter_client.h" +#include "content/public/app/sandbox_helper_win.h" +#include "content/public/common/content_switches.h" +#include "sandbox/win/src/sandbox.h" + +namespace { +// The entry point signature of chrome.dll. +typedef int (*DLL_MAIN)(HINSTANCE, sandbox::SandboxInterfaceInfo*); + +typedef void (*RelaunchChromeBrowserWithNewCommandLineIfNeededFunc)(); + +base::LazyInstance<ChromeCrashReporterClient>::Leaky g_chrome_crash_client = + LAZY_INSTANCE_INITIALIZER; + +// Loads |module| after setting the CWD to |module|'s directory. Returns a +// reference to the loaded module on success, or null on error. +HMODULE LoadModuleWithDirectory(const base::FilePath& module, bool pre_read) { + ::SetCurrentDirectoryW(module.DirName().value().c_str()); + + if (pre_read) { + // We pre-read the binary to warm the memory caches (fewer hard faults to + // page parts of the binary in). + const size_t kStepSize = 1024 * 1024; + PreReadFile(module, kStepSize); + } + + return ::LoadLibraryExW(module.value().c_str(), nullptr, + LOAD_WITH_ALTERED_SEARCH_PATH); +} + +void RecordDidRun(const base::FilePath& dll_path) { + bool system_level = !InstallUtil::IsPerUserInstall(dll_path); + GoogleUpdateSettings::UpdateDidRunState(true, system_level); +} + +void ClearDidRun(const base::FilePath& dll_path) { + bool system_level = !InstallUtil::IsPerUserInstall(dll_path); + GoogleUpdateSettings::UpdateDidRunState(false, system_level); +} + +bool InMetroMode() { + return (wcsstr( + ::GetCommandLineW(), L" -ServerName:DefaultBrowserServer") != nullptr); +} + +typedef int (*InitMetro)(); + +} // namespace + +//============================================================================= + +MainDllLoader::MainDllLoader() + : dll_(nullptr), metro_mode_(InMetroMode()) { +} + +MainDllLoader::~MainDllLoader() { +} + +// Loading chrome is an interesting affair. First we try loading from the +// current directory to support run-what-you-compile and other development +// scenarios. +// If that fails then we look at the version resource in the current +// module. This is the expected path for chrome.exe browser instances in an +// installed build. +HMODULE MainDllLoader::Load(base::string16* version, base::FilePath* module) { + const base::char16* dll_name = nullptr; + if (metro_mode_) { + dll_name = installer::kChromeMetroDll; + } else if (process_type_ == "service" || process_type_.empty()) { + dll_name = installer::kChromeDll; + } else if (process_type_ == "watcher") { + dll_name = kChromeWatcherDll; + } else { +#if defined(CHROME_MULTIPLE_DLL) + dll_name = installer::kChromeChildDll; +#else + dll_name = installer::kChromeDll; +#endif + } + + *module = installer::GetModulePath(dll_name, version); + if (module->empty()) { + PLOG(ERROR) << "Cannot find module " << dll_name; + return nullptr; + } + const bool pre_read = !metro_mode_; + HMODULE dll = LoadModuleWithDirectory(*module, pre_read); + if (!dll) { + PLOG(ERROR) << "Failed to load Chrome DLL from " << module->value(); + return nullptr; + } + + DCHECK(dll); + return dll; +} + +// Launching is a matter of loading the right dll, setting the CHROME_VERSION +// environment variable and just calling the entry point. Derived classes can +// add custom code in the OnBeforeLaunch callback. +int MainDllLoader::Launch(HINSTANCE instance) { + const base::CommandLine& cmd_line = *base::CommandLine::ForCurrentProcess(); + process_type_ = cmd_line.GetSwitchValueASCII(switches::kProcessType); + + base::string16 version; + base::FilePath file; + + if (metro_mode_) { + HMODULE metro_dll = Load(&version, &file); + if (!metro_dll) + return chrome::RESULT_CODE_MISSING_DATA; + + InitMetro chrome_metro_main = + reinterpret_cast<InitMetro>(::GetProcAddress(metro_dll, "InitMetro")); + return chrome_metro_main(); + } + + if (process_type_ == "watcher") { + chrome::RegisterPathProvider(); + + base::win::ScopedHandle parent_process; + base::win::ScopedHandle on_initialized_event; + DWORD main_thread_id = 0; + if (!InterpretChromeWatcherCommandLine(cmd_line, &parent_process, + &main_thread_id, + &on_initialized_event)) { + return chrome::RESULT_CODE_UNSUPPORTED_PARAM; + } + + base::FilePath default_user_data_directory; + if (!PathService::Get(chrome::DIR_USER_DATA, &default_user_data_directory)) + return chrome::RESULT_CODE_MISSING_DATA; + // The actual user data directory may differ from the default according to + // policy and command-line arguments evaluated in the browser process. + // The hang monitor will simply be disabled if a window with this name is + // never instantiated by the browser process. Since this should be + // exceptionally rare it should not impact stability efforts. + base::string16 message_window_name = default_user_data_directory.value(); + + base::FilePath watcher_data_directory; + if (!PathService::Get(chrome::DIR_WATCHER_DATA, &watcher_data_directory)) + return chrome::RESULT_CODE_MISSING_DATA; + + base::string16 channel_name = GoogleUpdateSettings::GetChromeChannel( + !InstallUtil::IsPerUserInstall(cmd_line.GetProgram())); + + // Intentionally leaked. + HMODULE watcher_dll = Load(&version, &file); + if (!watcher_dll) + return chrome::RESULT_CODE_MISSING_DATA; + + ChromeWatcherMainFunction watcher_main = + reinterpret_cast<ChromeWatcherMainFunction>( + ::GetProcAddress(watcher_dll, kChromeWatcherDLLEntrypoint)); + return watcher_main(chrome::kBrowserExitCodesRegistryPath, + parent_process.Take(), main_thread_id, + on_initialized_event.Take(), + watcher_data_directory.value().c_str(), + message_window_name.c_str(), channel_name.c_str()); + } + + // Initialize the sandbox services. + sandbox::SandboxInterfaceInfo sandbox_info = {0}; + content::InitializeSandboxInfo(&sandbox_info); + + crash_reporter::SetCrashReporterClient(g_chrome_crash_client.Pointer()); + bool exit_now = true; + if (process_type_.empty()) { + if (breakpad::ShowRestartDialogIfCrashed(&exit_now)) { + // We restarted because of a previous crash. Ask user if we should + // Relaunch. Only for the browser process. See crbug.com/132119. + if (exit_now) + return content::RESULT_CODE_NORMAL_EXIT; + } + } + breakpad::InitCrashReporter(process_type_); + + dll_ = Load(&version, &file); + if (!dll_) + return chrome::RESULT_CODE_MISSING_DATA; + + scoped_ptr<base::Environment> env(base::Environment::Create()); + env->SetVar(chrome::kChromeVersionEnvVar, base::WideToUTF8(version)); + + OnBeforeLaunch(process_type_, file); + DLL_MAIN chrome_main = + reinterpret_cast<DLL_MAIN>(::GetProcAddress(dll_, "ChromeMain")); + int rc = chrome_main(instance, &sandbox_info); + rc = OnBeforeExit(rc, file); + // Sandboxed processes close some system DLL handles after lockdown so ignore + // EXCEPTION_INVALID_HANDLE generated on Windows 10 during shutdown of these + // processes. + // TODO(wfh): Check whether MS have fixed this in Win10 RTM. crbug.com/456193 + if (base::win::GetVersion() >= base::win::VERSION_WIN10) + breakpad::ConsumeInvalidHandleExceptions(); + return rc; +} + +void MainDllLoader::RelaunchChromeBrowserWithNewCommandLineIfNeeded() { + if (!dll_) + return; + + RelaunchChromeBrowserWithNewCommandLineIfNeededFunc relaunch_function = + reinterpret_cast<RelaunchChromeBrowserWithNewCommandLineIfNeededFunc>( + ::GetProcAddress(dll_, + "RelaunchChromeBrowserWithNewCommandLineIfNeeded")); + if (!relaunch_function) { + LOG(ERROR) << "Could not find exported function " + << "RelaunchChromeBrowserWithNewCommandLineIfNeeded"; + } else { + relaunch_function(); + } +} + +//============================================================================= + +class ChromeDllLoader : public MainDllLoader { + protected: + // MainDllLoader implementation. + void OnBeforeLaunch(const std::string& process_type, + const base::FilePath& dll_path) override; + int OnBeforeExit(int return_code, const base::FilePath& dll_path) override; + + private: + scoped_ptr<ChromeWatcherClient> chrome_watcher_client_; +#if defined(KASKO) + scoped_ptr<KaskoClient> kasko_client_; +#endif // KASKO +}; + +void ChromeDllLoader::OnBeforeLaunch(const std::string& process_type, + const base::FilePath& dll_path) { + if (process_type.empty()) { + RecordDidRun(dll_path); + + // Launch the watcher process if stats collection consent has been granted. + if (g_chrome_crash_client.Get().GetCollectStatsConsent()) { + base::FilePath exe_path; + if (PathService::Get(base::FILE_EXE, &exe_path)) { + chrome_watcher_client_.reset(new ChromeWatcherClient( + base::Bind(&GenerateChromeWatcherCommandLine, exe_path))); + if (chrome_watcher_client_->LaunchWatcher()) { +#if defined(KASKO) + kasko::api::MinidumpType minidump_type = kasko::api::SMALL_DUMP_TYPE; + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kFullMemoryCrashReport)) { + minidump_type = kasko::api::FULL_DUMP_TYPE; + } else { + bool is_per_user_install = + g_chrome_crash_client.Get().GetIsPerUserInstall( + base::FilePath(exe_path)); + if (g_chrome_crash_client.Get().GetShouldDumpLargerDumps( + is_per_user_install)) { + minidump_type = kasko::api::LARGER_DUMP_TYPE; + } + } + + kasko_client_.reset( + new KaskoClient(chrome_watcher_client_.get(), minidump_type)); +#endif // KASKO + } + } + } + } else { + // Set non-browser processes up to be killed by the system after the browser + // goes away. The browser uses the default shutdown order, which is 0x280. + // Note that lower numbers here denote "kill later" and higher numbers mean + // "kill sooner". + // This gets rid of most of those unsighly sad tabs on logout and shutdown. + ::SetProcessShutdownParameters(0x280 - 1, SHUTDOWN_NORETRY); + } +} + +int ChromeDllLoader::OnBeforeExit(int return_code, + const base::FilePath& dll_path) { + // NORMAL_EXIT_CANCEL is used for experiments when the user cancels + // so we need to reset the did_run signal so omaha does not count + // this run as active usage. + if (chrome::RESULT_CODE_NORMAL_EXIT_CANCEL == return_code) { + ClearDidRun(dll_path); + } + +#if defined(KASKO) + kasko_client_.reset(); +#endif // KASKO + chrome_watcher_client_.reset(); + + return return_code; +} + +//============================================================================= + +class ChromiumDllLoader : public MainDllLoader { + protected: + void OnBeforeLaunch(const std::string& process_type, + const base::FilePath& dll_path) override {} + int OnBeforeExit(int return_code, const base::FilePath& dll_path) override { + return return_code; + } +}; + +MainDllLoader* MakeMainDllLoader() { +#if defined(GOOGLE_CHROME_BUILD) + return new ChromeDllLoader(); +#else + return new ChromiumDllLoader(); +#endif +}
diff --git a/chrome/app/main_dll_loader_win.h b/chrome/app/main_dll_loader_win.h new file mode 100644 index 0000000..99852ff --- /dev/null +++ b/chrome/app/main_dll_loader_win.h
@@ -0,0 +1,65 @@ +// Copyright (c) 2012 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. + +// This file defines a class to load the main DLL of a Chrome process. + +#ifndef CHROME_APP_MAIN_DLL_LOADER_WIN_H_ +#define CHROME_APP_MAIN_DLL_LOADER_WIN_H_ + +#include <windows.h> // NOLINT + +#include <string> + +#include "base/files/file_path.h" +#include "base/strings/string16.h" + +// Implements the common aspects of loading the main dll for both chrome and +// chromium scenarios, which are in charge of implementing two abstract +// methods: GetRegistryPath() and OnBeforeLaunch(). +class MainDllLoader { + public: + MainDllLoader(); + virtual ~MainDllLoader(); + + // Loads and calls the entry point of chrome.dll. |instance| is the exe + // instance retrieved from wWinMain. + // The return value is what the main entry point of chrome.dll returns + // upon termination. + int Launch(HINSTANCE instance); + + // Launches a new instance of the browser if the current instance in + // persistent mode an upgrade is detected. + void RelaunchChromeBrowserWithNewCommandLineIfNeeded(); + + protected: + // Called after chrome.dll has been loaded but before the entry point + // is invoked. Derived classes can implement custom actions here. + // |process_type| is the argument to the --type command line argument, e.g. + // "renderer", "watcher", etc. + // |dll_path| refers to the path of the Chrome dll being loaded. + virtual void OnBeforeLaunch(const std::string& process_type, + const base::FilePath& dll_path) = 0; + + // Called after the chrome.dll entry point returns and before terminating + // this process. The return value will be used as the process return code. + // |dll_path| refers to the path of the Chrome dll being loaded. + virtual int OnBeforeExit(int return_code, const base::FilePath& dll_path) = 0; + + private: + // Loads chrome.dll, populating |version| with the version of the DLL loaded + // and |module| with the path of the loaded DLL. Returns a reference to the + // module, or null on failure. + HMODULE Load(base::string16* version, base::FilePath* module); + + private: + HMODULE dll_; + std::string process_type_; + const bool metro_mode_; +}; + +// Factory for the MainDllLoader. Caller owns the pointer and should call +// delete to free it. +MainDllLoader* MakeMainDllLoader(); + +#endif // CHROME_APP_MAIN_DLL_LOADER_WIN_H_
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 556c489c..37fbb00 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -158,7 +158,7 @@ "//components/security_interstitials/core", "//components/signin/core/browser", "//components/ssl_errors", - "//components/startup_metric_utils", + "//components/startup_metric_utils/browser", "//components/strings", "//components/suggestions", "//components/sync_bookmarks", @@ -871,20 +871,6 @@ "autofill/validation_rules_storage_factory.h", ] } - if (enable_wifi_bootstrapping) { - sources += - rebase_path(gypi_values.chrome_browser_wifi_bootstrapping_sources, - ".", - "//chrome") - if (is_win || is_mac) { - # TODO(brettw) as of this writing wifi bootstrapping is set on Windows - # and Mac, so this test is meaningless. Can we merge these lists? - sources += rebase_path( - gypi_values.chrome_browser_wifi_bootstrapping_win_mac_sources, - ".", - "//chrome") - } - } if (enable_media_router) { deps += [ "//chrome/browser/media/router" ] } @@ -1226,13 +1212,6 @@ "ui/app_list/test/test_app_list_controller_delegate.h", ] } - - if (enable_wifi_bootstrapping) { - sources += [ - "local_discovery/wifi/mock_wifi_manager.cc", - "local_discovery/wifi/mock_wifi_manager.h", - ] - } } # In GYP this is part of test_support_ui.
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index cfe67c6c..1cc3965 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -95,7 +95,7 @@ "+components/signin", "+components/ssl_config", "+components/ssl_errors", - "+components/startup_metric_utils", + "+components/startup_metric_utils/browser", "+components/storage_monitor", "+components/suggestions", "+components/sync_bookmarks",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index bc66e454..c909945 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1333,6 +1333,13 @@ kOsDesktop, SINGLE_VALUE_TYPE(switches::kEnablePrintPreviewRegisterPromos)}, #endif // ENABLE_SERVICE_DISCOVERY +#if defined(ENABLE_PRINT_PREVIEW) + {"disable-print-preview-simplify", + IDS_FLAGS_DISABLE_DISTILLER_IN_PRINT_PREVIEW_NAME, + IDS_FLAGS_DISABLE_DISTILLER_IN_PRINT_PREVIEW_DESCRIPTION, + kOsDesktop, + SINGLE_VALUE_TYPE(switches::kDisablePrintPreviewSimplify)}, +#endif #if defined(OS_WIN) {"enable-cloud-print-xps", IDS_FLAGS_ENABLE_CLOUD_PRINT_XPS_NAME, @@ -2088,11 +2095,6 @@ switches::kDisablePushApiBackgroundMode)}, #endif // defined(ENABLE_BACKGROUND) #if !defined(OS_ANDROID) && !defined(OS_IOS) - {"enable-webusb-notifications", - IDS_FLAGS_ENABLE_WEBUSB_NOTIFICATIONS_NAME, - IDS_FLAGS_ENABLE_WEBUSB_NOTIFICATIONS_DESCRIPTION, - kOsDesktop, - SINGLE_VALUE_TYPE(switches::kEnableWebUsbNotifications)}, // TODO(reillyg): Remove this flag when the permission granting UI is // available. crbug.com/529950 {"enable-webusb-on-any-origin", @@ -2122,6 +2124,12 @@ ENABLE_DISABLE_VALUE_TYPE(switches::kEnableWebNotificationCustomLayouts, switches::kDisableWebNotificationCustomLayouts)}, #endif // defined(ENABLE_NOTIFICATIONS) && defined(OS_ANDROID) +#if defined(OS_WIN) + {"enable-appcontainer", IDS_FLAGS_ENABLE_APPCONTAINER_NAME, + IDS_FLAGS_ENABLE_APPCONTAINER_DESCRIPTION, kOsWin, + ENABLE_DISABLE_VALUE_TYPE(switches::kEnableAppContainer, + switches::kDisableAppContainer)}, +#endif // defined(OS_WIN) // NOTE: Adding new command-line switches requires adding corresponding // entries to enum "LoginCustomFlags" in histograms.xml. See note in // histograms.xml and don't forget to run AboutFlagsHistogramTest unit test.
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc index 100df2cb..87c83e5 100644 --- a/chrome/browser/android/chrome_jni_registrar.cc +++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -39,6 +39,7 @@ #include "chrome/browser/android/favicon_helper.h" #include "chrome/browser/android/feature_utilities.h" #include "chrome/browser/android/feedback/connectivity_checker.h" +#include "chrome/browser/android/feedback/screenshot_task.h" #include "chrome/browser/android/find_in_page/find_in_page_bridge.h" #include "chrome/browser/android/foreign_session_helper.h" #include "chrome/browser/android/fullscreen/fullscreen_infobar_delegate.h" @@ -125,6 +126,7 @@ #include "chrome/browser/ui/android/connection_info_popup_android.h" #include "chrome/browser/ui/android/context_menu_helper.h" #include "chrome/browser/ui/android/infobars/app_banner_infobar_android.h" +#include "chrome/browser/ui/android/infobars/auto_signin_first_run_infobar.h" #include "chrome/browser/ui/android/infobars/confirm_infobar.h" #include "chrome/browser/ui/android/infobars/data_reduction_proxy_infobar.h" #include "chrome/browser/ui/android/infobars/download_overwrite_infobar.h" @@ -136,7 +138,7 @@ #include "chrome/browser/ui/android/javascript_app_modal_dialog_android.h" #include "chrome/browser/ui/android/omnibox/omnibox_url_emphasizer.h" #include "chrome/browser/ui/android/omnibox/omnibox_view_util.h" -#include "chrome/browser/ui/android/snackbars/auto_signin_snackbar_controller.h" +#include "chrome/browser/ui/android/snackbars/auto_signin_prompt_controller.h" #include "chrome/browser/ui/android/ssl_client_certificate_request.h" #include "chrome/browser/ui/android/tab_model/single_tab_model.h" #include "chrome/browser/ui/android/tab_model/tab_model_jni_bridge.h" @@ -314,7 +316,9 @@ remote_media::RemoteMediaPlayerBridge::RegisterRemoteMediaPlayerBridge}, {"RevenueStats", RegisterRevenueStats}, {"SavePasswordInfoBar", SavePasswordInfoBar::Register}, + {"AutoSigninFirstRunInfoBar", AutoSigninFirstRunInfoBar::Register}, {"SceneLayer", chrome::android::RegisterSceneLayer}, + {"ScreenshotTask", RegisterScreenshotTask}, {"ServiceTabLauncher", service_tab_launcher::RegisterServiceTabLauncherJni}, {"SessionTabHelper", RegisterSessionTabHelper}, {"SigninManager", SigninManagerAndroid::Register},
diff --git a/chrome/browser/android/compositor/layer/contextual_search_layer.cc b/chrome/browser/android/compositor/layer/contextual_search_layer.cc index 33b48da..1c5bd77a 100644 --- a/chrome/browser/android/compositor/layer/contextual_search_layer.cc +++ b/chrome/browser/android/compositor/layer/contextual_search_layer.cc
@@ -79,7 +79,6 @@ float search_bar_shadow_opacity, bool search_provider_icon_sprite_visible, float search_provider_icon_sprite_completion_percentage, - float search_provider_icon_sprite_size, float arrow_icon_opacity, float arrow_icon_rotation, float close_icon_opacity, @@ -312,7 +311,8 @@ // Positions the Search Provider Icon at the start of the Search Bar. float icon_x; if (is_rtl) { - icon_x = search_panel_width - search_provider_icon_sprite_size - + icon_x = search_panel_width - + search_provider_icon_sprite_->layer()->bounds().width() - search_bar_margin_side; } else { icon_x = search_bar_margin_side; @@ -320,15 +320,9 @@ // Centers the Search Provider Icon vertically in the Search Bar. float icon_y = search_bar_top + search_bar_height / 2 - - search_provider_icon_sprite_size / 2; + - search_provider_icon_sprite_->layer()->bounds().height() / 2; search_provider_icon_sprite_->layer()->SetPosition( gfx::PointF(icon_x, icon_y)); - - // Scales the layer to the correct size. - search_provider_icon_sprite_->layer()->SetBounds( - gfx::Size(search_provider_icon_sprite_size, - search_provider_icon_sprite_size)); - } else { if (search_provider_icon_sprite_->layer().get() && search_provider_icon_sprite_->layer()->parent()) {
diff --git a/chrome/browser/android/compositor/layer/contextual_search_layer.h b/chrome/browser/android/compositor/layer/contextual_search_layer.h index 7a7bfd2..e020404 100644 --- a/chrome/browser/android/compositor/layer/contextual_search_layer.h +++ b/chrome/browser/android/compositor/layer/contextual_search_layer.h
@@ -72,7 +72,6 @@ float search_bar_shadow_opacity, bool search_provider_icon_sprite_visible, float search_provider_icon_sprite_completion_percentage, - float search_provider_icon_sprite_size, float arrow_icon_opacity, float arrow_icon_rotation, float close_icon_opacity,
diff --git a/chrome/browser/android/compositor/layer/crushed_sprite_layer.cc b/chrome/browser/android/compositor/layer/crushed_sprite_layer.cc index 6309071..3d42f459 100644 --- a/chrome/browser/android/compositor/layer/crushed_sprite_layer.cc +++ b/chrome/browser/android/compositor/layer/crushed_sprite_layer.cc
@@ -51,8 +51,8 @@ // Set up an SkCanvas backed by an SkBitmap to draw into. SkBitmap bitmap; - bitmap.allocN32Pixels(resource->GetSpriteSize().width(), - resource->GetSpriteSize().height()); + bitmap.allocN32Pixels(resource->GetUnscaledSpriteSize().width(), + resource->GetUnscaledSpriteSize().height()); skia::RefPtr<SkCanvas> canvas = skia::AdoptRef(new SkCanvas(bitmap)); // If this isn't the first or last frame, draw the previous frame(s). @@ -77,6 +77,9 @@ bitmap.setImmutable(); layer_->SetBitmap(bitmap); + // Set bounds to scale the layer. + layer_->SetBounds(resource->GetScaledSpriteSize()); + // Evict the crushed sprite bitmap from memory if this is the last frame. if (sprite_frame == frame_count_ - 1) { resource->EvictBitmapFromMemory();
diff --git a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc index 0572723e..c138f9aa 100644 --- a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc +++ b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc
@@ -64,7 +64,6 @@ jfloat search_bar_shadow_opacity, jboolean search_provider_icon_sprite_visible, jfloat search_provider_icon_sprite_completion_percentage, - jfloat search_provider_icon_sprite_size, jfloat arrow_icon_opacity, jfloat arrow_icon_rotation, jfloat close_icon_opacity, @@ -131,7 +130,6 @@ search_bar_shadow_opacity, search_provider_icon_sprite_visible, search_provider_icon_sprite_completion_percentage, - search_provider_icon_sprite_size, arrow_icon_opacity, arrow_icon_rotation, close_icon_opacity,
diff --git a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.h b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.h index a6a22da0..e0100ae 100644 --- a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.h +++ b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.h
@@ -65,7 +65,6 @@ jfloat search_bar_shadow_opacity, jboolean search_provider_icon_sprite_visible, jfloat search_provider_icon_sprite_completion_percentage, - jfloat search_provider_icon_sprite_size, jfloat arrow_icon_opacity, jfloat arrow_icon_rotation, jfloat close_icon_opacity,
diff --git a/chrome/browser/android/datausage/external_data_use_observer.cc b/chrome/browser/android/datausage/external_data_use_observer.cc index 411863e..2b3112e3 100644 --- a/chrome/browser/android/datausage/external_data_use_observer.cc +++ b/chrome/browser/android/datausage/external_data_use_observer.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/android/datausage/external_data_use_observer.h" +#include <utility> + #include "base/android/jni_string.h" #include "base/message_loop/message_loop.h" #include "components/data_usage/core/data_use.h" @@ -13,60 +15,79 @@ #include "url/gurl.h" using base::android::ConvertUTF8ToJavaString; +using base::android::ToJavaArrayOfStrings; namespace chrome { namespace android { ExternalDataUseObserver::ExternalDataUseObserver( - data_usage::DataUseAggregator* data_use_aggregator) + data_usage::DataUseAggregator* data_use_aggregator, + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) : data_use_aggregator_(data_use_aggregator), matching_rules_fetch_pending_(false), submit_data_report_pending_(false), registered_as_observer_(false), - task_runner_(nullptr), - weak_factory_(this) { + io_task_runner_(io_task_runner), + ui_task_runner_(ui_task_runner), + previous_report_time_(base::Time::Now()), + io_weak_factory_(this), + ui_weak_factory_(this) { DCHECK(data_use_aggregator_); + DCHECK(io_task_runner_); + DCHECK(ui_task_runner_); + ui_task_runner_->PostTask( + FROM_HERE, + base::Bind(&ExternalDataUseObserver::CreateJavaObjectOnUIThread, + GetUIWeakPtr())); - // TODO(tbansal): Remove this check. - if (base::MessageLoop::current()) - task_runner_ = base::MessageLoop::current()->task_runner(); + ui_task_runner_->PostTask( + FROM_HERE, + base::Bind(&ExternalDataUseObserver::FetchMatchingRulesOnUIThread, + GetUIWeakPtr())); + matching_rules_fetch_pending_ = true; + data_use_aggregator_->AddObserver(this); + registered_as_observer_ = true; +} + +void ExternalDataUseObserver::CreateJavaObjectOnUIThread() { + DCHECK(ui_task_runner_->BelongsToCurrentThread()); JNIEnv* env = base::android::AttachCurrentThread(); j_external_data_use_observer_.Reset(Java_ExternalDataUseObserver_create( env, base::android::GetApplicationContext(), reinterpret_cast<intptr_t>(this))); DCHECK(!j_external_data_use_observer_.is_null()); - - if (Java_ExternalDataUseObserver_fetchMatchingRules( - env, j_external_data_use_observer_.obj())) { - matching_rules_fetch_pending_ = true; - data_use_aggregator_->AddObserver(this); - registered_as_observer_ = true; - } } ExternalDataUseObserver::~ExternalDataUseObserver() { DCHECK(thread_checker_.CalledOnValidThread()); JNIEnv* env = base::android::AttachCurrentThread(); - - Java_ExternalDataUseObserver_onDestroy(env, - j_external_data_use_observer_.obj()); - + if (!j_external_data_use_observer_.is_null()) { + Java_ExternalDataUseObserver_onDestroy(env, + j_external_data_use_observer_.obj()); + } if (registered_as_observer_) data_use_aggregator_->RemoveObserver(this); } +void ExternalDataUseObserver::FetchMatchingRulesOnUIThread() const { + DCHECK(ui_task_runner_->BelongsToCurrentThread()); + DCHECK(!j_external_data_use_observer_.is_null()); + JNIEnv* env = base::android::AttachCurrentThread(); + Java_ExternalDataUseObserver_fetchMatchingRules( + env, j_external_data_use_observer_.obj()); +} + void ExternalDataUseObserver::FetchMatchingRulesCallback( JNIEnv* env, jobject obj, const base::android::JavaParamRef<jobjectArray>& app_package_name, const base::android::JavaParamRef<jobjectArray>& domain_path_regex, const base::android::JavaParamRef<jobjectArray>& label) { - if (!task_runner_) - return; - + DCHECK(ui_task_runner_->BelongsToCurrentThread()); // Convert to native objects. std::vector<std::string> app_package_name_native; std::vector<std::string> domain_path_regex_native; @@ -81,10 +102,10 @@ &label_native); } - task_runner_->PostTask( + io_task_runner_->PostTask( FROM_HERE, base::Bind(&ExternalDataUseObserver::FetchMatchingRulesCallbackOnIOThread, - weak_factory_.GetWeakPtr(), app_package_name_native, + GetIOWeakPtr(), app_package_name_native, domain_path_regex_native, label_native)); } @@ -102,13 +123,19 @@ void ExternalDataUseObserver::OnReportDataUseDone(JNIEnv* env, jobject obj, bool success) { - if (!task_runner_) - return; - - task_runner_->PostTask( + DCHECK(ui_task_runner_->BelongsToCurrentThread()); + io_task_runner_->PostTask( FROM_HERE, base::Bind(&ExternalDataUseObserver::OnReportDataUseDoneOnIOThread, - weak_factory_.GetWeakPtr(), success)); + GetIOWeakPtr(), success)); +} + +base::WeakPtr<ExternalDataUseObserver> ExternalDataUseObserver::GetIOWeakPtr() { + return io_weak_factory_.GetWeakPtr(); +} + +base::WeakPtr<ExternalDataUseObserver> ExternalDataUseObserver::GetUIWeakPtr() { + return ui_weak_factory_.GetWeakPtr(); } void ExternalDataUseObserver::OnReportDataUseDoneOnIOThread(bool success) { @@ -116,58 +143,123 @@ DCHECK(!buffered_data_reports_.empty()); DCHECK(submit_data_report_pending_); - // TODO(tbansal): If not successful, retry. + // TODO(tbansal): If not successful, record UMA. submit_data_report_pending_ = false; - // TODO(tbansal): Submit one more report from |buffered_data_reports_|. + SubmitBufferedDataUseReport(); } void ExternalDataUseObserver::OnDataUse( const std::vector<const data_usage::DataUse*>& data_use_sequence) { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!j_external_data_use_observer_.is_null()); - - JNIEnv* env = base::android::AttachCurrentThread(); if (matching_rules_fetch_pending_) { // TODO(tbansal): Buffer reports. } std::string label; + for (const data_usage::DataUse* data_use : data_use_sequence) { if (!Matches(data_use->url, &label)) continue; - int64_t bytes_downloaded = data_use->rx_bytes; - int64_t bytes_uploaded = data_use->tx_bytes; - buffered_data_reports_.push_back( - DataReport(label, bytes_downloaded, bytes_uploaded)); + BufferDataUseReport(data_use, label, previous_report_time_, + base::Time::Now()); + } + previous_report_time_ = base::Time::Now(); + // TODO(tbansal): Post SubmitBufferedDataUseReport on IO thread once the + // task runners are plumbed in. + SubmitBufferedDataUseReport(); +} + +void ExternalDataUseObserver::BufferDataUseReport( + const data_usage::DataUse* data_use, + const std::string& label, + const base::Time& start_time, + const base::Time& end_time) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(!label.empty()); + DCHECK_LE(0, data_use->rx_bytes); + DCHECK_LE(0, data_use->tx_bytes); + if (data_use->rx_bytes < 0 || data_use->tx_bytes < 0) + return; + + DataUseReportKey data_use_report_key = + DataUseReportKey(label, data_use->connection_type, data_use->mcc_mnc); + + DataUseReport report = DataUseReport(start_time, end_time, data_use->rx_bytes, + data_use->tx_bytes); + + // Check if the |data_use_report_key| is already in the buffered reports. + DataUseReports::iterator it = + buffered_data_reports_.find(data_use_report_key); + if (it == buffered_data_reports_.end()) { // Limit the buffer size. - if (buffered_data_reports_.size() > static_cast<size_t>(kMaxBufferSize)) { + if (buffered_data_reports_.size() == kMaxBufferSize) { // TODO(tbansal): Add UMA to track impact of lost reports. + // Remove the first entry. buffered_data_reports_.erase(buffered_data_reports_.begin()); } + buffered_data_reports_.insert(std::make_pair(data_use_report_key, report)); + } else { + DataUseReport existing_report = DataUseReport(it->second); + DataUseReport merged_report = DataUseReport( + std::min(existing_report.start_time, report.start_time), + std::max(existing_report.end_time, report.end_time), + existing_report.bytes_downloaded + report.bytes_downloaded, + existing_report.bytes_uploaded + report.bytes_uploaded); + buffered_data_reports_.erase(it); + buffered_data_reports_.insert( + std::make_pair(data_use_report_key, merged_report)); + } DCHECK_LE(buffered_data_reports_.size(), static_cast<size_t>(kMaxBufferSize)); +} - if (submit_data_report_pending_) - continue; +void ExternalDataUseObserver::SubmitBufferedDataUseReport() { + DCHECK(thread_checker_.CalledOnValidThread()); - // TODO(tbansal): Use buffering to avoid frequent JNI calls. - submit_data_report_pending_ = true; - DCHECK_GT(buffered_data_reports_.size(), 0U); - DataReport earliest_report = buffered_data_reports_[0]; - // TODO(tbansal): Get real values, instead of using 0s. - Java_ExternalDataUseObserver_reportDataUse( - env, j_external_data_use_observer_.obj(), - ConvertUTF8ToJavaString(env, earliest_report.label).obj(), 0, - ConvertUTF8ToJavaString(env, "").obj(), 0, 0, - earliest_report.bytes_downloaded, earliest_report.bytes_uploaded); - buffered_data_reports_.erase(buffered_data_reports_.begin()); - } + if (submit_data_report_pending_ || buffered_data_reports_.empty()) + return; + + // TODO(tbansal): Keep buffering until enough data has been received. + + // Send one data use report. + DataUseReports::iterator it = buffered_data_reports_.begin(); + DataUseReportKey key = it->first; + DataUseReport report = it->second; + + // Remove the entry from the map. + buffered_data_reports_.erase(it); + + submit_data_report_pending_ = true; + + ui_task_runner_->PostTask( + FROM_HERE, base::Bind(&ExternalDataUseObserver::ReportDataUseOnUIThread, + GetIOWeakPtr(), key, report)); +} + +void ExternalDataUseObserver::ReportDataUseOnUIThread( + const DataUseReportKey& key, + const DataUseReport& report) const { + DCHECK(ui_task_runner_->BelongsToCurrentThread()); + JNIEnv* env = base::android::AttachCurrentThread(); + DCHECK(!j_external_data_use_observer_.is_null()); + + // End time should be greater than start time. + int64_t start_time_milliseconds = report.start_time.ToJavaTime(); + int64_t end_time_milliseconds = report.end_time.ToJavaTime(); + if (start_time_milliseconds >= end_time_milliseconds) + start_time_milliseconds = end_time_milliseconds - 1; + + Java_ExternalDataUseObserver_reportDataUse( + env, j_external_data_use_observer_.obj(), + ConvertUTF8ToJavaString(env, key.label).obj(), key.connection_type, + ConvertUTF8ToJavaString(env, key.mcc_mnc).obj(), start_time_milliseconds, + end_time_milliseconds, report.bytes_downloaded, report.bytes_uploaded); } void ExternalDataUseObserver::RegisterURLRegexes(
diff --git a/chrome/browser/android/datausage/external_data_use_observer.h b/chrome/browser/android/datausage/external_data_use_observer.h index 6f12159d..a7dd885 100644 --- a/chrome/browser/android/datausage/external_data_use_observer.h +++ b/chrome/browser/android/datausage/external_data_use_observer.h
@@ -6,7 +6,10 @@ #define CHROME_BROWSER_ANDROID_DATAUSAGE_EXTERNAL_DATA_USE_OBSERVER_H_ #include <jni.h> +#include <stdint.h> + #include <string> +#include <unordered_map> #include <vector> #include "base/android/jni_array.h" @@ -16,9 +19,12 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" #include "base/thread_task_runner_handle.h" #include "base/threading/thread_checker.h" +#include "base/time/time.h" #include "components/data_usage/core/data_use_aggregator.h" +#include "net/base/network_change_notifier.h" class GURL; @@ -43,10 +49,13 @@ // of the requests, and notifies the filtered data use to the Java listener. The // Java object in turn may notify the platform APIs of the data usage // observations. +// TODO(tbansal): Create an inner class that manages the UI and IO threads. class ExternalDataUseObserver : public data_usage::DataUseAggregator::Observer { public: - explicit ExternalDataUseObserver( - data_usage::DataUseAggregator* data_use_aggregator); + ExternalDataUseObserver( + data_usage::DataUseAggregator* data_use_aggregator, + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); ~ExternalDataUseObserver() override; // Called by Java when new matching rules have been fetched. This may be @@ -56,7 +65,8 @@ // reports corresponding to the matching rule, and must // uniquely identify the matching rule. Each element in |label| must have // non-zero length. The three vectors should have equal length. The vectors - // may be empty which implies that no matching rules are active. + // may be empty which implies that no matching rules are active. Must be + // called on UI thread. void FetchMatchingRulesCallback( JNIEnv* env, jobject obj, @@ -66,7 +76,8 @@ // Called by Java when the reporting of data usage has finished. This may be // called on a different thread. |success| is true if the request was - // successfully submitted to the external data use observer by Java. + // successfully submitted to the external data use observer by Java. Must be + // called on UI thread. void OnReportDataUseDone(JNIEnv* env, jobject obj, bool success); private: @@ -77,20 +88,104 @@ FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, AtMostOneDataUseSubmitRequest); FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, MultipleMatchingRules); + FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, ReportsMergedCorrectly); + FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, + TimestampsMergedCorrectly); + FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, HashFunction); + FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, BufferSize); - // Data report that is sent to the external observer. - struct DataReport { - DataReport(const std::string& label, - int64_t bytes_downloaded, - int64_t bytes_uploaded) - : label(label), + // DataUseReportKey is a unique identifier for a data use report. + struct DataUseReportKey { + DataUseReportKey(const std::string& label, + net::NetworkChangeNotifier::ConnectionType connection_type, + const std::string& mcc_mnc) + : label(label), connection_type(connection_type), mcc_mnc(mcc_mnc) {} + + DataUseReportKey(const DataUseReportKey& other) + : label(other.label), + connection_type(other.connection_type), + mcc_mnc(other.mcc_mnc) {} + + bool operator==(const DataUseReportKey& other) const { + return (label == other.label && + connection_type == other.connection_type && + mcc_mnc == other.mcc_mnc); + } + + virtual ~DataUseReportKey() {} + + // Label provided by the matching rules. + const std::string label; + + // Type of network used by the request. + const net::NetworkChangeNotifier::ConnectionType connection_type; + + // mcc_mnc operator of the provider of the SIM as obtained from + // TelephonyManager#getNetworkOperator() Java API in Android. + const std::string mcc_mnc; + }; + + // DataUseReport is paired with a DataUseReportKey object. DataUseReport + // contains the bytes send/received during a specific interval. Only the bytes + // from the data use reports that have the |label|, |connection_type|, and + // |mcc_mnc| specified in the corresponding DataUseReportKey object are + // counted in the DataUseReport. + struct DataUseReport { + // |start_time| and |end_time| are the start and end timestamps (in UTC + // since the standard Java epoch of 1970-01-01 00:00:00) of the interval + // that this data report covers. |bytes_downloaded| and |bytes_uploaded| are + // the total bytes received and send during this interval. + DataUseReport(const base::Time& start_time, + const base::Time& end_time, + int64_t bytes_downloaded, + int64_t bytes_uploaded) + : start_time(start_time), + end_time(end_time), bytes_downloaded(bytes_downloaded), bytes_uploaded(bytes_uploaded) {} - std::string label; - int64_t bytes_downloaded; - int64_t bytes_uploaded; + + virtual ~DataUseReport() {} + + // Start time of |this| data report (in UTC since the standard Java epoch of + // 1970-01-01 00:00:00). + const base::Time start_time; + + // End time of |this| data report (in UTC since the standard Java epoch of + // 1970-01-01 00:00:00) + const base::Time end_time; + + // Number of bytes downloaded and uploaded by Chromium from |start_time| to + // |end_time|. + const int64_t bytes_downloaded; + const int64_t bytes_uploaded; }; + // Class that implements hash operator on DataUseReportKey. + class DataUseReportKeyHash { + public: + // A simple heuristical hash function that satisifes the property that two + // equal data structures have the same hash value. The hash is computed by + // hashing individual variables and combining them using prime numbers. + // Prime numbers are used for multiplication because the number of buckets + // used by map is always an even number. Using a prime number ensures that + // for two different DataUseReportKey objects (say |j| and |k|), if the + // hash value of |k.label| is equal to hash value of |j.mcc_mnc|, then |j| + // and |k| map to different buckets. Large prime numbers are used so that + // hash value is spread over a larger range. + size_t operator()(const DataUseReportKey& k) const { + std::hash<std::string> hash_function; + size_t hash = 1; + hash = hash * 23 + hash_function(k.label); + hash = hash * 43 + k.connection_type; + hash = hash * 83 + hash_function(k.mcc_mnc); + return hash; + } + }; + + typedef std::unordered_map<DataUseReportKey, + DataUseReport, + DataUseReportKeyHash> DataUseReports; + // Stores the matching rules. class MatchingRule { public: @@ -119,10 +214,35 @@ // size |kMaxBufferSize|, then the oldest entry will be removed. static const size_t kMaxBufferSize = 100; + // Creates Java object. Must be called on the UI thread. + void CreateJavaObjectOnUIThread(); + // data_usage::DataUseAggregator::Observer implementation: void OnDataUse(const std::vector<const data_usage::DataUse*>& data_use_sequence) override; + // Fetches matching rules from Java. Must be called on the UI thread. Returns + // result asynchronously on UI thread via FetchMatchingRulesCallback. + void FetchMatchingRulesOnUIThread() const; + + // Called by FetchMatchingRulesCallback on IO thread when new matching rules + // Adds |data_use| to buffered reports. |data_use| is the data use report + // received from DataUseAggregator. |data_use| should not be null. |label| is + // a non-empty label that applies to |data_use|. |start_time| and |end_time| + // are the start, and end times of the interval during which bytes reported in + // |data_use| went over the network. + void BufferDataUseReport(const data_usage::DataUse* data_use, + const std::string& label, + const base::Time& start_time, + const base::Time& end_time); + + // Submits the first data report among the buffered data reports in + // |buffered_data_reports_|. Since an unordered_map is used to buffer the + // reports, the order of reports may change. The reports are buffered in an + // arbitrary order and there are no guarantees that the next report to be + // submitted is the oldest one buffered. + void SubmitBufferedDataUseReport(); + // Called by |FetchMatchingRulesCallback| on IO thread when new matching rules // have been fetched. void FetchMatchingRulesCallbackOnIOThread( @@ -130,7 +250,12 @@ const std::vector<std::string>& domain_path_regex, const std::vector<std::string>& label); - // Called by |OnReportDataUseDone| on IO thread when a data use report has + // Reports data use to Java. Must be called on the UI thread. Returns + // result asynchronously on UI thread via OnReportDataUseDone. + void ReportDataUseOnUIThread(const DataUseReportKey& key, + const DataUseReport& report) const; + + // Called by OnReportDataUseDone on IO thread when a data use report has // been submitted. void OnReportDataUseDoneOnIOThread(bool success); @@ -147,6 +272,11 @@ // matching rule's label. bool Matches(const GURL& gurl, std::string* label) const; + // Return the weak pointer to |this| to be used on IO and UI thread, + // respectively. + base::WeakPtr<ExternalDataUseObserver> GetIOWeakPtr(); + base::WeakPtr<ExternalDataUseObserver> GetUIWeakPtr(); + // Aggregator that sends data use observations to |this|. data_usage::DataUseAggregator* data_use_aggregator_; @@ -166,18 +296,28 @@ // Buffered data reports that need to be submitted to the Java data use // observer. - std::vector<DataReport> buffered_data_reports_; + DataUseReports buffered_data_reports_; // True if |this| is currently registered as a data use observer. bool registered_as_observer_; - // |task_runner_| accesses ExternalDataUseObserver members on IO thread. - scoped_refptr<base::TaskRunner> task_runner_; + // |io_task_runner_| accesses ExternalDataUseObserver members on IO thread. + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; + + // |ui_task_runner_| is used to call Java code on UI thread. This ensures + // that Java code is safely called only on a single thread, and eliminates + // the need for locks in Java. + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; + + // Time when the data use reports were last received from DataUseAggregator. + base::Time previous_report_time_; base::ThreadChecker thread_checker_; - // |weak_factory_| is used for posting tasks on the IO thread. - base::WeakPtrFactory<ExternalDataUseObserver> weak_factory_; + // |io_weak_factory_| and |ui_weak_factory_| are used for posting tasks on the + // IO and UI thread, respectively. + base::WeakPtrFactory<ExternalDataUseObserver> io_weak_factory_; + base::WeakPtrFactory<ExternalDataUseObserver> ui_weak_factory_; DISALLOW_COPY_AND_ASSIGN(ExternalDataUseObserver); };
diff --git a/chrome/browser/android/datausage/external_data_use_observer_unittest.cc b/chrome/browser/android/datausage/external_data_use_observer_unittest.cc index 747fc98..ed79bcf2 100644 --- a/chrome/browser/android/datausage/external_data_use_observer_unittest.cc +++ b/chrome/browser/android/datausage/external_data_use_observer_unittest.cc
@@ -8,8 +8,14 @@ #include <vector> #include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" +#include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" +#include "base/thread_task_runner_handle.h" #include "components/data_usage/core/data_use.h" #include "components/data_usage/core/data_use_aggregator.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "net/base/network_change_notifier.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -18,12 +24,35 @@ namespace android { -TEST(ExternalDataUseObserverTest, SingleRegex) { - scoped_ptr<data_usage::DataUseAggregator> data_use_aggregator( - new data_usage::DataUseAggregator()); - scoped_ptr<ExternalDataUseObserver> external_data_use_observer( - new ExternalDataUseObserver(data_use_aggregator.get())); +class ExternalDataUseObserverTest : public testing::Test { + public: + void SetUp() override { + thread_bundle_.reset(new content::TestBrowserThreadBundle( + content::TestBrowserThreadBundle::REAL_IO_THREAD)); + io_task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::IO); + ui_task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::UI); + data_use_aggregator_.reset(new data_usage::DataUseAggregator()); + external_data_use_observer_.reset(new ExternalDataUseObserver( + data_use_aggregator_.get(), io_task_runner_.get(), + ui_task_runner_.get())); + } + ExternalDataUseObserver* external_data_use_observer() const { + return external_data_use_observer_.get(); + } + + private: + // Required for creating multiple threads for unit testing. + scoped_ptr<content::TestBrowserThreadBundle> thread_bundle_; + scoped_ptr<data_usage::DataUseAggregator> data_use_aggregator_; + scoped_ptr<ExternalDataUseObserver> external_data_use_observer_; + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; +}; + +TEST_F(ExternalDataUseObserverTest, SingleRegex) { const struct { std::string url; std::string regex; @@ -53,12 +82,12 @@ std::string label("test"); for (size_t i = 0; i < arraysize(tests); ++i) { - external_data_use_observer->RegisterURLRegexes( + external_data_use_observer()->RegisterURLRegexes( std::vector<std::string>(1, std::string()), std::vector<std::string>(1, tests[i].regex), std::vector<std::string>(1, "label")); EXPECT_EQ(tests[i].expect_match, - external_data_use_observer->Matches(GURL(tests[i].url), &label)) + external_data_use_observer()->Matches(GURL(tests[i].url), &label)) << i; // Verify label matches the expected label. @@ -70,12 +99,7 @@ } } -TEST(ExternalDataUseObserverTest, TwoRegex) { - scoped_ptr<data_usage::DataUseAggregator> data_use_aggregator( - new data_usage::DataUseAggregator()); - scoped_ptr<ExternalDataUseObserver> external_data_use_observer( - new ExternalDataUseObserver(data_use_aggregator.get())); - +TEST_F(ExternalDataUseObserverTest, TwoRegex) { const struct { std::string url; std::string regex1; @@ -115,26 +139,21 @@ for (size_t i = 0; i < arraysize(tests); ++i) { std::vector<std::string> url_regexes; url_regexes.push_back(tests[i].regex1 + "|" + tests[i].regex2); - external_data_use_observer->RegisterURLRegexes( + external_data_use_observer()->RegisterURLRegexes( std::vector<std::string>(url_regexes.size(), std::string()), url_regexes, std::vector<std::string>(url_regexes.size(), "label")); EXPECT_EQ(tests[i].expect_match, - external_data_use_observer->Matches(GURL(tests[i].url), &label)) + external_data_use_observer()->Matches(GURL(tests[i].url), &label)) << i; } } -TEST(ExternalDataUseObserverTest, MultipleRegex) { - scoped_ptr<data_usage::DataUseAggregator> data_use_aggregator( - new data_usage::DataUseAggregator()); - scoped_ptr<ExternalDataUseObserver> external_data_use_observer( - new ExternalDataUseObserver(data_use_aggregator.get())); - +TEST_F(ExternalDataUseObserverTest, MultipleRegex) { std::vector<std::string> url_regexes; url_regexes.push_back( "https?://www[.]google[.]com/#q=.*|https?://www[.]google[.]com[.]ph/" "#q=.*|https?://www[.]google[.]com[.]ph/[?]gws_rd=ssl#q=.*"); - external_data_use_observer->RegisterURLRegexes( + external_data_use_observer()->RegisterURLRegexes( std::vector<std::string>(url_regexes.size(), std::string()), url_regexes, std::vector<std::string>(url_regexes.size(), "label")); @@ -170,36 +189,29 @@ std::string label; for (size_t i = 0; i < arraysize(tests); ++i) { EXPECT_EQ(tests[i].expect_match, - external_data_use_observer->Matches(GURL(tests[i].url), &label)) + external_data_use_observer()->Matches(GURL(tests[i].url), &label)) << i << " " << tests[i].url; } } -TEST(ExternalDataUseObserverTest, ChangeRegex) { - scoped_ptr<data_usage::DataUseAggregator> data_use_aggregator( - new data_usage::DataUseAggregator()); - scoped_ptr<ExternalDataUseObserver> external_data_use_observer( - new ExternalDataUseObserver(data_use_aggregator.get())); - +TEST_F(ExternalDataUseObserverTest, ChangeRegex) { std::string label; // When no regex is specified, the URL match should fail. - EXPECT_FALSE(external_data_use_observer->Matches(GURL(""), &label)); - EXPECT_FALSE(external_data_use_observer->Matches( + EXPECT_FALSE(external_data_use_observer()->Matches(GURL(""), &label)); + EXPECT_FALSE(external_data_use_observer()->Matches( GURL("http://www.google.com"), &label)); - EXPECT_FALSE(external_data_use_observer->registered_as_observer_); - EXPECT_FALSE(external_data_use_observer->matching_rules_fetch_pending_); std::vector<std::string> url_regexes; url_regexes.push_back("http://www[.]google[.]com/#q=.*"); url_regexes.push_back("https://www[.]google[.]com/#q=.*"); - external_data_use_observer->RegisterURLRegexes( + external_data_use_observer()->RegisterURLRegexes( std::vector<std::string>(url_regexes.size(), std::string()), url_regexes, std::vector<std::string>(url_regexes.size(), "label")); - EXPECT_FALSE(external_data_use_observer->Matches(GURL(""), &label)); - EXPECT_TRUE(external_data_use_observer->Matches( + EXPECT_FALSE(external_data_use_observer()->Matches(GURL(""), &label)); + EXPECT_TRUE(external_data_use_observer()->Matches( GURL("http://www.google.com#q=abc"), &label)); - EXPECT_FALSE(external_data_use_observer->Matches( + EXPECT_FALSE(external_data_use_observer()->Matches( GURL("http://www.google.co.in#q=abc"), &label)); // Change the regular expressions to verify that the new regexes replace @@ -207,72 +219,190 @@ url_regexes.clear(); url_regexes.push_back("http://www[.]google[.]co[.]in/#q=.*"); url_regexes.push_back("https://www[.]google[.]co[.]in/#q=.*"); - external_data_use_observer->RegisterURLRegexes( + external_data_use_observer()->RegisterURLRegexes( std::vector<std::string>(url_regexes.size(), std::string()), url_regexes, std::vector<std::string>(url_regexes.size(), "label")); - EXPECT_FALSE(external_data_use_observer->Matches(GURL(""), &label)); - EXPECT_FALSE(external_data_use_observer->Matches( + EXPECT_FALSE(external_data_use_observer()->Matches(GURL(""), &label)); + EXPECT_FALSE(external_data_use_observer()->Matches( GURL("http://www.google.com#q=abc"), &label)); - EXPECT_TRUE(external_data_use_observer->Matches( + EXPECT_TRUE(external_data_use_observer()->Matches( GURL("http://www.google.co.in#q=abc"), &label)); } -// Tests that at most one data use request is submitted, and if buffer size -// does not exceed the specified limit. -TEST(ExternalDataUseObserverTest, AtMostOneDataUseSubmitRequest) { - scoped_ptr<data_usage::DataUseAggregator> data_use_aggregator( - new data_usage::DataUseAggregator()); - scoped_ptr<ExternalDataUseObserver> external_data_use_observer( - new ExternalDataUseObserver(data_use_aggregator.get())); - +// Tests that at most one data use request is submitted. +TEST_F(ExternalDataUseObserverTest, AtMostOneDataUseSubmitRequest) { const std::string label("label"); std::vector<std::string> url_regexes; url_regexes.push_back( "http://www[.]google[.]com/#q=.*|https://www[.]google[.]com/#q=.*"); - external_data_use_observer->FetchMatchingRulesCallbackOnIOThread( + external_data_use_observer()->FetchMatchingRulesCallbackOnIOThread( std::vector<std::string>(url_regexes.size(), std::string()), url_regexes, std::vector<std::string>(url_regexes.size(), label)); - EXPECT_EQ(0U, external_data_use_observer->buffered_data_reports_.size()); - EXPECT_FALSE(external_data_use_observer->submit_data_report_pending_); - EXPECT_FALSE(external_data_use_observer->matching_rules_fetch_pending_); + EXPECT_EQ(0U, external_data_use_observer()->buffered_data_reports_.size()); + EXPECT_FALSE(external_data_use_observer()->submit_data_report_pending_); + EXPECT_FALSE(external_data_use_observer()->matching_rules_fetch_pending_); std::vector<const data_usage::DataUse*> data_use_sequence; - data_usage::DataUse data_use( + data_usage::DataUse data_use_foo( GURL("http://www.google.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0, - net::NetworkChangeNotifier::CONNECTION_UNKNOWN, std::string(), 0, 0); - data_use_sequence.push_back(&data_use); - data_use_sequence.push_back(&data_use); - external_data_use_observer->OnDataUse(data_use_sequence); + net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc_foo", 1, 2); + data_use_sequence.push_back(&data_use_foo); + data_usage::DataUse data_use_bar( + GURL("http://www.google.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0, + net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc_bar", 1, 2); + data_use_sequence.push_back(&data_use_bar); + external_data_use_observer()->OnDataUse(data_use_sequence); - EXPECT_EQ(1U, external_data_use_observer->buffered_data_reports_.size()); - EXPECT_TRUE(external_data_use_observer->submit_data_report_pending_); + EXPECT_EQ(1U, external_data_use_observer()->buffered_data_reports_.size()); + EXPECT_TRUE(external_data_use_observer()->submit_data_report_pending_); +} + +// Verifies that buffer size does not exceed the specified limit. +TEST_F(ExternalDataUseObserverTest, BufferSize) { + const std::string label("label"); + + std::vector<std::string> url_regexes; + url_regexes.push_back( + "http://www[.]google[.]com/#q=.*|https://www[.]google[.]com/#q=.*"); + + external_data_use_observer()->FetchMatchingRulesCallbackOnIOThread( + std::vector<std::string>(url_regexes.size(), std::string()), url_regexes, + std::vector<std::string>(url_regexes.size(), label)); const size_t max_buffer_size = ExternalDataUseObserver::kMaxBufferSize; - data_use_sequence.clear(); - for (size_t i = 0; i < max_buffer_size; ++i) - data_use_sequence.push_back(&data_use); + ScopedVector<data_usage::DataUse> data_use_vector; + // Push more entries than the buffer size. Buffer size should not be exceeded. + for (size_t i = 0; i < max_buffer_size * 5; ++i) { + scoped_ptr<data_usage::DataUse> data_use(new data_usage::DataUse( + GURL("http://www.google.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0, + net::NetworkChangeNotifier::CONNECTION_UNKNOWN, + "mccmnc" + base::Int64ToString(i), 0, 0)); + data_use_vector.push_back(data_use.Pass()); + } - external_data_use_observer->OnDataUse(data_use_sequence); - EXPECT_EQ(max_buffer_size, - external_data_use_observer->buffered_data_reports_.size()); + std::vector<const data_usage::DataUse*> const_sequence( + data_use_vector.begin(), data_use_vector.end()); + + external_data_use_observer()->OnDataUse(const_sequence); + // One report will be consumed. + EXPECT_EQ(max_buffer_size - 1, + external_data_use_observer()->buffered_data_reports_.size()); // Verify the label of the data use report. - for (const auto& data_report : - external_data_use_observer->buffered_data_reports_) { - EXPECT_EQ(label, data_report.label); + for (const auto& it : external_data_use_observer()->buffered_data_reports_) + EXPECT_EQ(label, it.first.label); +} + +// Tests that buffered data use reports are merged correctly. +TEST_F(ExternalDataUseObserverTest, ReportsMergedCorrectly) { + const std::string label("label"); + + std::vector<std::string> url_regexes; + url_regexes.push_back( + "http://www[.]google[.]com/#q=.*|https://www[.]google[.]com/#q=.*"); + + external_data_use_observer()->FetchMatchingRulesCallbackOnIOThread( + std::vector<std::string>(url_regexes.size(), std::string()), url_regexes, + std::vector<std::string>(url_regexes.size(), label)); + + const size_t num_iterations = ExternalDataUseObserver::kMaxBufferSize * 5; + + ScopedVector<data_usage::DataUse> data_use_vector; + for (size_t i = 0; i < num_iterations; ++i) { + scoped_ptr<data_usage::DataUse> data_use_foo(new data_usage::DataUse( + GURL("http://www.google.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0, + net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc_foo", 1, 2)); + data_use_vector.push_back(data_use_foo.Pass()); + + scoped_ptr<data_usage::DataUse> data_use_bar(new data_usage::DataUse( + GURL("http://www.google.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0, + net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc_bar", 1, 2)); + data_use_vector.push_back(data_use_bar.Pass()); + + scoped_ptr<data_usage::DataUse> data_use_baz(new data_usage::DataUse( + GURL("http://www.google.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0, + net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc_baz", 1, 2)); + data_use_vector.push_back(data_use_baz.Pass()); } + + std::vector<const data_usage::DataUse*> const_sequence( + data_use_vector.begin(), data_use_vector.end()); + + external_data_use_observer()->OnDataUse(const_sequence); + + EXPECT_EQ(2U, external_data_use_observer()->buffered_data_reports_.size()); + EXPECT_EQ(static_cast<int64_t>(num_iterations * 2), + external_data_use_observer() + ->buffered_data_reports_.begin() + ->second.bytes_downloaded); + EXPECT_EQ(static_cast<int64_t>(num_iterations * 1), + external_data_use_observer() + ->buffered_data_reports_.begin() + ->second.bytes_uploaded); + + // Delete the first entry and verify the next entry. + external_data_use_observer()->buffered_data_reports_.erase( + external_data_use_observer()->buffered_data_reports_.begin()); + EXPECT_EQ(1U, external_data_use_observer()->buffered_data_reports_.size()); + EXPECT_EQ(static_cast<int64_t>(num_iterations * 2), + external_data_use_observer() + ->buffered_data_reports_.begin() + ->second.bytes_downloaded); + EXPECT_EQ(static_cast<int64_t>(num_iterations * 1), + external_data_use_observer() + ->buffered_data_reports_.begin() + ->second.bytes_uploaded); +} + +// Tests that timestamps of merged reports is correct. +TEST_F(ExternalDataUseObserverTest, TimestampsMergedCorrectly) { + const std::string label("label"); + + std::vector<std::string> url_regexes; + url_regexes.push_back( + "http://www[.]google[.]com/#q=.*|https://www[.]google[.]com/#q=.*"); + + external_data_use_observer()->FetchMatchingRulesCallbackOnIOThread( + std::vector<std::string>(url_regexes.size(), std::string()), url_regexes, + std::vector<std::string>(url_regexes.size(), label)); + + const size_t num_iterations = ExternalDataUseObserver::kMaxBufferSize * 5; + + ScopedVector<data_usage::DataUse> data_use_vector; + for (size_t i = 0; i < num_iterations; ++i) { + scoped_ptr<data_usage::DataUse> data_use_foo(new data_usage::DataUse( + GURL("http://www.google.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0, + net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc_foo", 1, 2)); + data_use_vector.push_back(data_use_foo.Pass()); + } + + std::vector<const data_usage::DataUse*> const_sequence( + data_use_vector.begin(), data_use_vector.end()); + + int64_t start_timestamp = 0; + int64_t end_timestamp = 1; + for (auto it : const_sequence) { + const data_usage::DataUse* data_usage(it); + external_data_use_observer()->BufferDataUseReport( + data_usage, "foo_label", base::Time::FromDoubleT(start_timestamp++), + base::Time::FromDoubleT(end_timestamp++)); + } + EXPECT_EQ(1U, external_data_use_observer()->buffered_data_reports_.size()); + EXPECT_EQ(0, external_data_use_observer() + ->buffered_data_reports_.begin() + ->second.start_time.ToJavaTime()); + // Convert from seconds to milliseconds. + EXPECT_EQ(static_cast<int64_t>(num_iterations * 1000), + external_data_use_observer() + ->buffered_data_reports_.begin() + ->second.end_time.ToJavaTime()); } // Tests the behavior when multiple matching rules are available. -TEST(ExternalDataUseObserverTest, MultipleMatchingRules) { - scoped_ptr<data_usage::DataUseAggregator> data_use_aggregator( - new data_usage::DataUseAggregator()); - scoped_ptr<ExternalDataUseObserver> external_data_use_observer( - new ExternalDataUseObserver(data_use_aggregator.get())); - +TEST_F(ExternalDataUseObserverTest, MultipleMatchingRules) { std::vector<std::string> url_regexes; url_regexes.push_back( "http://www[.]foo[.]com/#q=.*|https://www[.]foo[.]com/#q=.*"); @@ -285,45 +415,75 @@ labels.push_back(label_foo); labels.push_back(label_bar); - external_data_use_observer->FetchMatchingRulesCallbackOnIOThread( + external_data_use_observer()->FetchMatchingRulesCallbackOnIOThread( std::vector<std::string>(url_regexes.size(), std::string()), url_regexes, labels); - EXPECT_EQ(0U, external_data_use_observer->buffered_data_reports_.size()); - EXPECT_FALSE(external_data_use_observer->submit_data_report_pending_); - EXPECT_FALSE(external_data_use_observer->matching_rules_fetch_pending_); + EXPECT_EQ(0U, external_data_use_observer()->buffered_data_reports_.size()); + EXPECT_FALSE(external_data_use_observer()->submit_data_report_pending_); + EXPECT_FALSE(external_data_use_observer()->matching_rules_fetch_pending_); // Check |label_foo| matching rule. std::vector<const data_usage::DataUse*> data_use_sequence; - data_usage::DataUse data_foo( + data_usage::DataUse data_foo_1( GURL("http://www.foo.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0, - net::NetworkChangeNotifier::CONNECTION_UNKNOWN, std::string(), 0, 0); - data_use_sequence.push_back(&data_foo); - data_use_sequence.push_back(&data_foo); - external_data_use_observer->OnDataUse(data_use_sequence); + net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc_1", 0, 0); + data_usage::DataUse data_foo_2( + GURL("http://www.foo.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0, + net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc_2", 0, 0); + data_use_sequence.push_back(&data_foo_1); + data_use_sequence.push_back(&data_foo_2); + external_data_use_observer()->OnDataUse(data_use_sequence); - EXPECT_EQ(1U, external_data_use_observer->buffered_data_reports_.size()); - EXPECT_TRUE(external_data_use_observer->submit_data_report_pending_); + EXPECT_EQ(1U, external_data_use_observer()->buffered_data_reports_.size()); + EXPECT_TRUE(external_data_use_observer()->submit_data_report_pending_); // Verify the label of the data use report. - EXPECT_EQ(label_foo, - external_data_use_observer->buffered_data_reports_.begin()->label); + EXPECT_EQ(label_foo, external_data_use_observer() + ->buffered_data_reports_.begin() + ->first.label); + EXPECT_EQ("mccmnc_1", external_data_use_observer() + ->buffered_data_reports_.begin() + ->first.mcc_mnc); // Clear the state. - external_data_use_observer->buffered_data_reports_.clear(); + external_data_use_observer()->buffered_data_reports_.clear(); data_use_sequence.clear(); // Check |label_bar| matching rule. data_usage::DataUse data_bar( GURL("http://www.bar.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0, - net::NetworkChangeNotifier::CONNECTION_UNKNOWN, std::string(), 0, 0); + net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc", 0, 0); data_use_sequence.push_back(&data_bar); - external_data_use_observer->OnDataUse(data_use_sequence); - for (const auto& data_report : - external_data_use_observer->buffered_data_reports_) { - EXPECT_EQ(label_bar, data_report.label); + external_data_use_observer()->OnDataUse(data_use_sequence); + for (const auto& it : external_data_use_observer()->buffered_data_reports_) { + EXPECT_EQ(label_bar, it.first.label); + EXPECT_EQ("mccmnc", it.first.mcc_mnc); } } +// Tests that hash function reports distinct values. This test may fail if there +// is a hash collision, however the chances of that happening are very low. +TEST_F(ExternalDataUseObserverTest, HashFunction) { + ExternalDataUseObserver::DataUseReportKeyHash hash; + + ExternalDataUseObserver::DataUseReportKey foo( + "foo_label", net::NetworkChangeNotifier::CONNECTION_UNKNOWN, + "foo_mcc_mnc"); + ExternalDataUseObserver::DataUseReportKey bar_label( + "bar_label", net::NetworkChangeNotifier::CONNECTION_UNKNOWN, + "foo_mcc_mnc"); + ExternalDataUseObserver::DataUseReportKey bar_network_type( + "foo_label", net::NetworkChangeNotifier::CONNECTION_WIFI, "foo_mcc_mnc"); + ExternalDataUseObserver::DataUseReportKey bar_mcc_mnc( + "foo_label", net::NetworkChangeNotifier::CONNECTION_UNKNOWN, + "bar_mcc_mnc"); + + EXPECT_NE(hash(foo), hash(bar_label)); + EXPECT_NE(hash(foo), hash(bar_label)); + EXPECT_NE(hash(foo), hash(bar_network_type)); + EXPECT_NE(hash(foo), hash(bar_mcc_mnc)); +} + } // namespace android } // namespace chrome
diff --git a/chrome/browser/android/feedback/screenshot_task.cc b/chrome/browser/android/feedback/screenshot_task.cc new file mode 100644 index 0000000..8864934 --- /dev/null +++ b/chrome/browser/android/feedback/screenshot_task.cc
@@ -0,0 +1,60 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/android/feedback/screenshot_task.h" + +#include "base/android/scoped_java_ref.h" +#include "base/bind.h" +#include "base/memory/ref_counted_memory.h" +#include "base/thread_task_runner_handle.h" +#include "jni/ScreenshotTask_jni.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/android/window_android.h" +#include "ui/gfx/display.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/screen.h" +#include "ui/snapshot/snapshot.h" + +using base::android::AttachCurrentThread; +using base::android::ScopedJavaGlobalRef; +using ui::WindowAndroid; + +namespace chrome { +namespace android { + +bool RegisterScreenshotTask(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +void SnapshotCallback(JNIEnv* env, + base::android::ScopedJavaGlobalRef<jobject>* callback, + scoped_refptr<base::RefCountedBytes> png_data) { + size_t size = png_data->size(); + jbyteArray jbytes = env->NewByteArray(size); + env->SetByteArrayRegion(jbytes, 0, size, (jbyte*)png_data->front()); + Java_ScreenshotTask_notifySnapshotFinished(AttachCurrentThread(), + callback->obj(), + jbytes); +} + +void GrabWindowSnapshotAsync(JNIEnv* env, + const JavaParamRef<jclass>& clazz, + const JavaParamRef<jobject>& jcallback, + jlong native_window_android) { + WindowAndroid* window_android = reinterpret_cast<WindowAndroid*>( + native_window_android); + // TODO(jinsukkim): Use window bounds once WindowAndroid provides it. + gfx::Display display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); + ui::GrabWindowSnapshotAsync( + window_android, + display.bounds(), + base::ThreadTaskRunnerHandle::Get(), + base::Bind(&SnapshotCallback, + env, + base::Owned(new ScopedJavaGlobalRef<jobject>(env, + jcallback)))); +} + +} // namespace android +} // namespace chrome
diff --git a/chrome/browser/android/feedback/screenshot_task.h b/chrome/browser/android/feedback/screenshot_task.h new file mode 100644 index 0000000..3751f20 --- /dev/null +++ b/chrome/browser/android/feedback/screenshot_task.h
@@ -0,0 +1,18 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ANDROID_FEEDBACK_SCREENSHOT_TASK_H_ +#define CHROME_BROWSER_ANDROID_FEEDBACK_SCREENSHOT_TASK_H_ + +#include "base/android/jni_android.h" + +namespace chrome { +namespace android { + +bool RegisterScreenshotTask(JNIEnv* env); + +} // namespace android +} // namespace chrome + +#endif // CHROME_BROWSER_ANDROID_FEEDBACK_SCREENSHOT_TASK_H_
diff --git a/chrome/browser/android/most_visited_sites.cc b/chrome/browser/android/most_visited_sites.cc index 4027868..b462b17 100644 --- a/chrome/browser/android/most_visited_sites.cc +++ b/chrome/browser/android/most_visited_sites.cc
@@ -10,6 +10,7 @@ #include "base/android/scoped_java_ref.h" #include "base/callback.h" #include "base/command_line.h" +#include "base/metrics/field_trial.h" #include "base/metrics/histogram.h" #include "base/metrics/sparse_histogram.h" #include "base/prefs/pref_service.h" @@ -33,6 +34,7 @@ #include "components/pref_registry/pref_registry_syncable.h" #include "components/suggestions/suggestions_service.h" #include "components/suggestions/suggestions_utils.h" +#include "components/variations/variations_associated_data.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/url_data_source.h" #include "jni/MostVisitedSites_jni.h"
diff --git a/chrome/browser/banners/app_banner_data_fetcher_browsertest.cc b/chrome/browser/banners/app_banner_data_fetcher_browsertest.cc index 027df6d..e803089b 100644 --- a/chrome/browser/banners/app_banner_data_fetcher_browsertest.cc +++ b/chrome/browser/banners/app_banner_data_fetcher_browsertest.cc
@@ -109,15 +109,6 @@ ASSERT_FALSE(fetcher->is_active()); } - void LoadURLAndWaitForServiceWorker(const GURL& url) { - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - content::TestNavigationObserver observer(web_contents, 2); - ui_test_utils::NavigateToURL(browser(), url); - observer.Wait(); - EXPECT_EQ("sw_activated", observer.last_navigation_url().ref()); - } - void RunBannerTest(const std::string& manifest_page, ui::PageTransition transition, unsigned int unshown_repetitions, @@ -128,13 +119,13 @@ browser()->tab_strip_model()->GetActiveWebContents(); for (unsigned int i = 0; i < unshown_repetitions; ++i) { - LoadURLAndWaitForServiceWorker(test_url); + ui_test_utils::NavigateToURL(browser(), test_url); RunFetcher(web_contents->GetURL(), std::string(), transition, false); AppBannerDataFetcher::SetTimeDeltaForTesting(i+1); } // On the final loop, check whether the banner triggered or not as expected. - LoadURLAndWaitForServiceWorker(test_url); + ui_test_utils::NavigateToURL(browser(), test_url); RunFetcher(web_contents->GetURL(), std::string(), transition, expectation); } @@ -246,40 +237,40 @@ browser()->tab_strip_model()->GetActiveWebContents(); // Add a direct nav on day 1. - LoadURLAndWaitForServiceWorker(test_url); + ui_test_utils::NavigateToURL(browser(), test_url); RunFetcher(web_contents->GetURL(), std::string(), ui::PAGE_TRANSITION_TYPED, false); // Add an indirect nav on day 1 which is ignored. - LoadURLAndWaitForServiceWorker(test_url); + ui_test_utils::NavigateToURL(browser(), test_url); RunFetcher(web_contents->GetURL(), std::string(), ui::PAGE_TRANSITION_LINK, false); AppBannerDataFetcher::SetTimeDeltaForTesting(1); // Add an indirect nav on day 2. - LoadURLAndWaitForServiceWorker(test_url); + ui_test_utils::NavigateToURL(browser(), test_url); RunFetcher(web_contents->GetURL(), std::string(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME, false); // Add a direct nav on day 2 which overrides. - LoadURLAndWaitForServiceWorker(test_url); + ui_test_utils::NavigateToURL(browser(), test_url); RunFetcher(web_contents->GetURL(), std::string(), ui::PAGE_TRANSITION_GENERATED, false); AppBannerDataFetcher::SetTimeDeltaForTesting(2); // Add a direct nav on day 3. - LoadURLAndWaitForServiceWorker(test_url); + ui_test_utils::NavigateToURL(browser(), test_url); RunFetcher(web_contents->GetURL(), std::string(), ui::PAGE_TRANSITION_GENERATED, false); AppBannerDataFetcher::SetTimeDeltaForTesting(3); // Add an indirect nav on day 4. - LoadURLAndWaitForServiceWorker(test_url); + ui_test_utils::NavigateToURL(browser(), test_url); RunFetcher(web_contents->GetURL(), std::string(), ui::PAGE_TRANSITION_FORM_SUBMIT, false); // Add a direct nav on day 4 which should trigger the banner. - LoadURLAndWaitForServiceWorker(test_url); + ui_test_utils::NavigateToURL(browser(), test_url); RunFetcher(web_contents->GetURL(), std::string(), ui::PAGE_TRANSITION_TYPED, true); }
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 9ad6608..e0c9e12 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -151,6 +151,8 @@ <include name="IDR_MD_EXTENSIONS_ITEM_CSS" file="resources\md_extensions\item.css" type="BINDATA" /> <include name="IDR_MD_EXTENSIONS_ITEM_HTML" file="resources\md_extensions\item.html" type="BINDATA" /> <include name="IDR_MD_EXTENSIONS_ITEM_JS" file="resources\md_extensions\item.js" type="BINDATA" /> + <include name="IDR_MD_EXTENSIONS_SERVICE_HTML" file="resources\md_extensions\service.html" type="BINDATA" /> + <include name="IDR_MD_EXTENSIONS_SERVICE_JS" file="resources\md_extensions\service.js" type="BINDATA" /> <include name="IDR_MD_EXTENSIONS_SIDEBAR_CSS" file="resources\md_extensions\sidebar.css" type="BINDATA" /> <include name="IDR_MD_EXTENSIONS_SIDEBAR_HTML" file="resources\md_extensions\sidebar.html" type="BINDATA" /> <include name="IDR_MD_EXTENSIONS_SIDEBAR_JS" file="resources\md_extensions\sidebar.js" type="BINDATA" />
diff --git a/chrome/browser/browsing_data/browsing_data_counter.cc b/chrome/browser/browsing_data/browsing_data_counter.cc index a716c32c9..c9aea83 100644 --- a/chrome/browser/browsing_data/browsing_data_counter.cc +++ b/chrome/browser/browsing_data/browsing_data_counter.cc
@@ -53,12 +53,50 @@ if (!profile_->GetPrefs()->GetBoolean(GetPrefName())) return; - callback_.Run(false, 0u); + callback_.Run(make_scoped_ptr(new Result(this))); Count(); } void BrowsingDataCounter::ReportResult(ResultInt value) { DCHECK(initialized_); - callback_.Run(true, value); + callback_.Run(make_scoped_ptr(new FinishedResult(this, value))); +} + +void BrowsingDataCounter::ReportResult(scoped_ptr<Result> result) { + DCHECK(initialized_); + callback_.Run(result.Pass()); +} + +// BrowsingDataCounter::Result ------------------------------------------------- + +BrowsingDataCounter::Result::Result(const BrowsingDataCounter* source) + : source_(source) { +} + +BrowsingDataCounter::Result::~Result() { +} + +bool BrowsingDataCounter::Result::Finished() const { + return false; +} + +// BrowsingDataCounter::FinishedResult ----------------------------------------- + +BrowsingDataCounter::FinishedResult::FinishedResult( + const BrowsingDataCounter* source, ResultInt value) + : Result(source), + value_(value) { +} + +BrowsingDataCounter::FinishedResult::~FinishedResult() { +} + +bool BrowsingDataCounter::FinishedResult::Finished() const { + return true; +} + +BrowsingDataCounter::ResultInt + BrowsingDataCounter::FinishedResult::Value() const { + return value_; }
diff --git a/chrome/browser/browsing_data/browsing_data_counter.h b/chrome/browser/browsing_data/browsing_data_counter.h index ba3afbd..9f92ee6c 100644 --- a/chrome/browser/browsing_data/browsing_data_counter.h +++ b/chrome/browser/browsing_data/browsing_data_counter.h
@@ -9,14 +9,52 @@ #include <string> #include "base/callback.h" +#include "base/macros.h" #include "base/prefs/pref_member.h" #include "chrome/browser/browsing_data/browsing_data_remover.h" #include "chrome/browser/profiles/profile.h" class BrowsingDataCounter { public: - typedef uint64_t ResultInt; - typedef base::Callback<void(bool, ResultInt)> Callback; + typedef int64_t ResultInt; + + // Base class of results returned by BrowsingDataCounter. When the computation + // has started, an instance is returned to represent a pending result. + class Result { + public: + explicit Result(const BrowsingDataCounter* source); + virtual ~Result(); + + const BrowsingDataCounter* source() const { return source_; } + virtual bool Finished() const; + + private: + const BrowsingDataCounter* source_; + + DISALLOW_COPY_AND_ASSIGN(Result); + }; + + // A subclass of Result returned when the computation has finished. The result + // value can be retrieved by calling |Value()|. Some BrowsingDataCounter + // subclasses might use a subclass of FinishedResult to provide more complex + // results. + class FinishedResult : public Result { + public: + FinishedResult(const BrowsingDataCounter* source, ResultInt value); + ~FinishedResult() override; + + // Result: + bool Finished() const override; + + ResultInt Value() const; + + private: + ResultInt value_; + + DISALLOW_COPY_AND_ASSIGN(FinishedResult); + }; + + typedef base::Callback<void(scoped_ptr<Result>)> Callback; BrowsingDataCounter(); virtual ~BrowsingDataCounter(); @@ -38,8 +76,12 @@ protected: // Should be called from |Count| by any overriding class to indicate that - // counting is finished and report the |result|. - void ReportResult(ResultInt result); + // counting is finished and report |value| as the result. + void ReportResult(ResultInt value); + + // A convenience overload of the previous method that allows subclasses to + // provide a custom |result|. + void ReportResult(scoped_ptr<Result> result); // Calculates the beginning of the counting period as |period_| before now. base::Time GetPeriodStart();
diff --git a/chrome/browser/browsing_data/cache_counter.cc b/chrome/browser/browsing_data/cache_counter.cc index 299ed1e..06f4cd6a 100644 --- a/chrome/browser/browsing_data/cache_counter.cc +++ b/chrome/browser/browsing_data/cache_counter.cc
@@ -40,15 +40,7 @@ if (result_bytes < 0) return; - // The cache size on all three backends (blockfile, simple and memory) is - // limited to int32. We are adding together results from several cache - // backends, so the result should fit into 32+epsilon bits. Thus, - // |result_bytes| / 1024^2 should fit into an int. - static const int kBToMb = 1024 * 1024; - int result_mb = result_bytes / kBToMb; - if (result_bytes % kBToMb) - ++result_mb; - ReportResult(result_mb); + ReportResult(result_bytes); } bool CacheCounter::Pending() {
diff --git a/chrome/browser/browsing_data/cache_counter_browsertest.cc b/chrome/browser/browsing_data/cache_counter_browsertest.cc index a156c73d..43a97207f 100644 --- a/chrome/browser/browsing_data/cache_counter_browsertest.cc +++ b/chrome/browser/browsing_data/cache_counter_browsertest.cc
@@ -129,11 +129,16 @@ } // Callback from the counter. - void CountingCallback(bool finished, BrowsingDataCounter::ResultInt count) { + void CountingCallback(scoped_ptr<BrowsingDataCounter::Result> result) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - finished_ = finished; - result_ = count; - if (run_loop_ && finished) + finished_ = result->Finished(); + + if (finished_) { + result_ = static_cast<BrowsingDataCounter::FinishedResult*>( + result.get())->Value(); + } + + if (run_loop_ && finished_) run_loop_->Quit(); }
diff --git a/chrome/browser/browsing_data/history_counter.cc b/chrome/browser/browsing_data/history_counter.cc index ae1fbe1..116dba92 100644 --- a/chrome/browser/browsing_data/history_counter.cc +++ b/chrome/browser/browsing_data/history_counter.cc
@@ -28,18 +28,6 @@ HistoryCounter::~HistoryCounter() { } -// Note that the local counting done by |VisitDatabase::GetHistoryCount| -// returns an int, which is at most a signed 64-bit number. On the other hand, -// ResultInt is an unsigned 64-bit number, so the range 2^63..2^64-1 is unused -// and we can use it to encode special values. -// static -const BrowsingDataCounter::ResultInt HistoryCounter::kOnlySyncedHistory = - std::numeric_limits<BrowsingDataCounter::ResultInt>::max(); -COMPILE_ASSERT( - std::numeric_limits<int>::digits < - std::numeric_limits<BrowsingDataCounter::ResultInt>::digits, - "BrowsingDataCounter::ResultInt must be wider than int."); - const std::string& HistoryCounter::GetPrefName() const { return pref_name_; } @@ -161,8 +149,17 @@ if (!local_counting_finished_ || !web_counting_finished_) return; - if (!local_result_ && has_synced_visits_) - ReportResult(kOnlySyncedHistory); - else - ReportResult(local_result_); + ReportResult(make_scoped_ptr(new HistoryResult( + this, local_result_, has_synced_visits_))); +} + +HistoryCounter::HistoryResult::HistoryResult( + const HistoryCounter* source, + ResultInt value, + bool has_synced_visits) + : FinishedResult(source, value), + has_synced_visits_(has_synced_visits) { +} + +HistoryCounter::HistoryResult::~HistoryResult() { }
diff --git a/chrome/browser/browsing_data/history_counter.h b/chrome/browser/browsing_data/history_counter.h index f38181c9..4061cdb 100644 --- a/chrome/browser/browsing_data/history_counter.h +++ b/chrome/browser/browsing_data/history_counter.h
@@ -13,11 +13,18 @@ class HistoryCounter: public BrowsingDataCounter { public: - // A special value indicating that the local counting result is zero, but some - // history entries exist in Sync. - // TODO(msramek): Change the callback signature so we can return a structured - // result instead of special int values. - static const BrowsingDataCounter::ResultInt kOnlySyncedHistory; + class HistoryResult : public FinishedResult { + public: + HistoryResult(const HistoryCounter* source, + ResultInt value, + bool has_synced_visits); + ~HistoryResult() override; + + bool has_synced_visits() const { return has_synced_visits_; } + + private: + bool has_synced_visits_; + }; HistoryCounter(); ~HistoryCounter() override;
diff --git a/chrome/browser/browsing_data/history_counter_browsertest.cc b/chrome/browser/browsing_data/history_counter_browsertest.cc index 4f9d685..30bcd108 100644 --- a/chrome/browser/browsing_data/history_counter_browsertest.cc +++ b/chrome/browser/browsing_data/history_counter_browsertest.cc
@@ -62,15 +62,28 @@ run_loop_->Run(); } - BrowsingDataCounter::ResultInt GetResult() { + BrowsingDataCounter::ResultInt GetLocalResult() { DCHECK(finished_); - return result_; + return local_result_; } - void Callback(bool finished, BrowsingDataCounter::ResultInt count) { - finished_ = finished; - result_ = count; - if (run_loop_ && finished) + bool HasSyncedVisits() { + DCHECK(finished_); + return has_synced_visits_; + } + + void Callback(scoped_ptr<BrowsingDataCounter::Result> result) { + finished_ = result->Finished(); + + if (finished_) { + HistoryCounter::HistoryResult* history_result = + static_cast<HistoryCounter::HistoryResult*>(result.get()); + + local_result_ = history_result->Value(); + has_synced_visits_ = history_result->has_synced_visits(); + } + + if (run_loop_ && finished_) run_loop_->Quit(); } @@ -80,7 +93,8 @@ base::Time time_; bool finished_; - BrowsingDataCounter::ResultInt result_; + BrowsingDataCounter::ResultInt local_result_; + bool has_synced_visits_; }; // Tests that the counter considers duplicate visits from the same day @@ -114,7 +128,7 @@ counter.Restart(); WaitForCounting(); - EXPECT_EQ(7u, GetResult()); + EXPECT_EQ(7u, GetLocalResult()); } // Tests that the counter starts counting automatically when the deletion @@ -131,7 +145,7 @@ SetHistoryDeletionPref(true); WaitForCounting(); - EXPECT_EQ(2u, GetResult()); + EXPECT_EQ(2u, GetLocalResult()); } // Tests that the counter does not count history if the deletion @@ -180,23 +194,23 @@ SetDeletionPeriodPref(BrowsingDataRemover::LAST_HOUR); WaitForCounting(); - EXPECT_EQ(1u, GetResult()); + EXPECT_EQ(1u, GetLocalResult()); SetDeletionPeriodPref(BrowsingDataRemover::LAST_DAY); WaitForCounting(); - EXPECT_EQ(1u, GetResult()); + EXPECT_EQ(1u, GetLocalResult()); SetDeletionPeriodPref(BrowsingDataRemover::LAST_WEEK); WaitForCounting(); - EXPECT_EQ(5u, GetResult()); + EXPECT_EQ(5u, GetLocalResult()); SetDeletionPeriodPref(BrowsingDataRemover::FOUR_WEEKS); WaitForCounting(); - EXPECT_EQ(8u, GetResult()); + EXPECT_EQ(8u, GetLocalResult()); SetDeletionPeriodPref(BrowsingDataRemover::EVERYTHING); WaitForCounting(); - EXPECT_EQ(9u, GetResult()); + EXPECT_EQ(9u, GetLocalResult()); } class FakeWebHistoryService : public history::WebHistoryService { @@ -338,14 +352,15 @@ base::Bind(&HistoryCounterTest::Callback, base::Unretained(this))); - // No entries locally and no entries in Sync - the result should be zero. + // No entries locally and no entries in Sync. service->SetRequestOptions(true /* success */, net::HTTP_OK); counter.Restart(); WaitForCounting(); - EXPECT_EQ(0u, GetResult()); + EXPECT_EQ(0u, GetLocalResult()); + EXPECT_FALSE(HasSyncedVisits()); // No entries locally. There are some entries in Sync, but they are out of the - // time range. The result should still be zero. + // time range. SetDeletionPeriodPref(BrowsingDataRemover::LAST_HOUR); service->AddSyncedVisit( "www.google.com", GetCurrentTime() - base::TimeDelta::FromHours(2)); @@ -354,15 +369,16 @@ service->SetRequestOptions(true /* success */, net::HTTP_OK); counter.Restart(); WaitForCounting(); - EXPECT_EQ(0u, GetResult()); + EXPECT_EQ(0u, GetLocalResult()); + EXPECT_FALSE(HasSyncedVisits()); - // No entries locally, but some entries in Sync - the result should be - // kOnlySyncedHistory. + // No entries locally, but some entries in Sync. service->AddSyncedVisit("www.google.com", GetCurrentTime()); service->SetRequestOptions(true /* success */, net::HTTP_OK); counter.Restart(); WaitForCounting(); - EXPECT_EQ(HistoryCounter::kOnlySyncedHistory, GetResult()); + EXPECT_EQ(0u, GetLocalResult()); + EXPECT_TRUE(HasSyncedVisits()); // To err on the safe side, if the server request fails, we assume that there // might be some items on the server. @@ -370,30 +386,33 @@ net::HTTP_INTERNAL_SERVER_ERROR); counter.Restart(); WaitForCounting(); - EXPECT_EQ(HistoryCounter::kOnlySyncedHistory, GetResult()); + EXPECT_EQ(0u, GetLocalResult()); + EXPECT_TRUE(HasSyncedVisits()); // Same when the entire query fails. service->SetRequestOptions(false /* success */, net::HTTP_INTERNAL_SERVER_ERROR); counter.Restart(); WaitForCounting(); - EXPECT_EQ(HistoryCounter::kOnlySyncedHistory, GetResult()); + EXPECT_EQ(0u, GetLocalResult()); + EXPECT_TRUE(HasSyncedVisits()); - // If the local count is nonzero, the server result has no influence on the - // output, whether its nonempty... + // Nonzero local count, nonempty sync. AddVisit("https://www.google.com"); AddVisit("https://www.chrome.com"); service->SetRequestOptions(true /* success */, net::HTTP_OK); counter.Restart(); WaitForCounting(); - EXPECT_EQ(2u, GetResult()); + EXPECT_EQ(2u, GetLocalResult()); + EXPECT_TRUE(HasSyncedVisits()); - // ...or empty. + // Nonzero local count, empty sync. service->ClearSyncedVisits(); service->SetRequestOptions(true /* success */, net::HTTP_OK); counter.Restart(); WaitForCounting(); - EXPECT_EQ(2u, GetResult()); + EXPECT_EQ(2u, GetLocalResult()); + EXPECT_FALSE(HasSyncedVisits()); } } // namespace
diff --git a/chrome/browser/browsing_data/passwords_counter_browsertest.cc b/chrome/browser/browsing_data/passwords_counter_browsertest.cc index 4ef3fd9..2d269027 100644 --- a/chrome/browser/browsing_data/passwords_counter_browsertest.cc +++ b/chrome/browser/browsing_data/passwords_counter_browsertest.cc
@@ -87,10 +87,15 @@ return result_; } - void Callback(bool finished, BrowsingDataCounter::ResultInt count) { - finished_ = finished; - result_ = count; - if (run_loop_ && finished) + void Callback(scoped_ptr<BrowsingDataCounter::Result> result) { + finished_ = result->Finished(); + + if (finished_) { + result_ = static_cast<BrowsingDataCounter::FinishedResult*>( + result.get())->Value(); + } + + if (run_loop_ && finished_) run_loop_->Quit(); }
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 010d0cbe..372d0ee4 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -117,7 +117,7 @@ #include "components/nacl/browser/nacl_browser.h" #include "components/rappor/rappor_service.h" #include "components/signin/core/common/profile_management_switches.h" -#include "components/startup_metric_utils/startup_metric_utils.h" +#include "components/startup_metric_utils/browser/startup_metric_utils.h" #include "components/tracing/tracing_switches.h" #include "components/translate/content/browser/browser_cld_utils.h" #include "components/translate/content/common/cld_data_source.h" @@ -1186,8 +1186,10 @@ #endif // defined(ENABLE_WEBRTC) #if !defined(OS_ANDROID) && !defined(OS_IOS) + // WebUSB is an experimental web API. The sites these notifications will link + // to will only work if the experiment is enabled. if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableWebUsbNotifications)) { + switches::kEnableExperimentalWebPlatformFeatures)) { webusb_browser_client_.reset(new ChromeWebUsbBrowserClient()); webusb_detector_.reset( new webusb::WebUsbDetector(webusb_browser_client_.get()));
diff --git a/chrome/browser/chrome_notification_types.h b/chrome/browser/chrome_notification_types.h index ef35936..278cf76 100644 --- a/chrome/browser/chrome_notification_types.h +++ b/chrome/browser/chrome_notification_types.h
@@ -337,11 +337,6 @@ // session data. NOTIFICATION_FOREIGN_SESSION_UPDATED, - // All tab metadata has been loaded from disk asynchronously. - // Sent on the UI thread. - // The source is the Profile. There are no details. - NOTIFICATION_SESSION_RESTORE_COMPLETE, - // Cookies ----------------------------------------------------------------- #if defined(ENABLE_EXTENSIONS)
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index f88e8b82..0f1fd635 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -121,6 +121,7 @@ #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" #include "device/bluetooth/bluetooth_adapter_factory.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" #include "media/audio/sounds/sounds_manager.h" #include "net/base/network_change_notifier.h" #include "net/socket/ssl_server_socket.h" @@ -186,6 +187,12 @@ // Initialize DBusThreadManager for the browser. This must be done after // the main message loop is started, as it uses the message loop. DBusThreadManager::Initialize(); + + bluez::BluezDBusManager::Initialize( + DBusThreadManager::Get()->GetSystemBus(), + chromeos::DBusThreadManager::Get()->IsUsingStub( + chromeos::DBusClientBundle::BLUETOOTH)); + PowerPolicyController::Initialize( DBusThreadManager::Get()->GetPowerManagerClient()); @@ -252,6 +259,7 @@ PowerDataCollector::Shutdown(); PowerPolicyController::Shutdown(); device::BluetoothAdapterFactory::Shutdown(); + bluez::BluezDBusManager::Shutdown(); // NOTE: This must only be called if Initialize() was called. DBusThreadManager::Shutdown();
diff --git a/chrome/browser/chromeos/file_manager/gallery_jstest.cc b/chrome/browser/chromeos/file_manager/gallery_jstest.cc index 9e304dd2..ab20f00 100644 --- a/chrome/browser/chromeos/file_manager/gallery_jstest.cc +++ b/chrome/browser/chromeos/file_manager/gallery_jstest.cc
@@ -52,3 +52,8 @@ IN_PROC_BROWSER_TEST_F(GalleryJsTest, SlideModeTest) { RunTest(base::FilePath(FILE_PATH_LITERAL("slide_mode_unittest.html"))); } + +IN_PROC_BROWSER_TEST_F(GalleryJsTest, DimmableUIControllerTest) { + RunTest(base::FilePath( + FILE_PATH_LITERAL("dimmable_ui_controller_unittest.html"))); +}
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.cc index 878eab7a..e3c11a8 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.cc
@@ -18,6 +18,7 @@ #include "chromeos/dbus/easy_unlock_client.h" #include "chromeos/login/auth/key.h" #include "components/proximity_auth/cryptauth/base64url.h" +#include "components/proximity_auth/logging/logging.h" #include "crypto/encryptor.h" #include "crypto/random.h" #include "crypto/symmetric_key.h" @@ -114,14 +115,14 @@ const std::string& ec_private_key, const std::string& ec_public_key) { if (ec_private_key.empty() || ec_public_key.empty()) { - LOG(ERROR) << "Easy unlock failed to generate ec key pair."; + PA_LOG(ERROR) << "Easy unlock failed to generate ec key pair."; callback_.Run(false); return; } std::string device_pub_key; if (!proximity_auth::Base64UrlDecode(device_->public_key, &device_pub_key)) { - LOG(ERROR) << "Easy unlock failed to decode device public key."; + PA_LOG(ERROR) << "Easy unlock failed to decode device public key."; callback_.Run(false); return; } @@ -137,7 +138,7 @@ void EasyUnlockCreateKeysOperation::ChallengeCreator::OnEskGenerated( const std::string& esk) { if (esk.empty()) { - LOG(ERROR) << "Easy unlock failed to generate challenge esk."; + PA_LOG(ERROR) << "Easy unlock failed to generate challenge esk."; callback_.Run(false); return; } @@ -157,7 +158,7 @@ void EasyUnlockCreateKeysOperation::ChallengeCreator::OnTPMPublicKeyWrapped( const std::string& wrapped_key) { if (wrapped_key.empty()) { - LOG(ERROR) << "Unable to wrap RSA key"; + PA_LOG(ERROR) << "Unable to wrap RSA key"; callback_.Run(false); return; } @@ -198,7 +199,7 @@ void EasyUnlockCreateKeysOperation::ChallengeCreator::OnPayloadGenerated( const std::string& payload) { if (payload.empty()) { - LOG(ERROR) << "Easy unlock failed to generate challenge payload."; + PA_LOG(ERROR) << "Easy unlock failed to generate challenge payload."; callback_.Run(false); return; } @@ -219,7 +220,7 @@ void EasyUnlockCreateKeysOperation::ChallengeCreator::OnChallengeGenerated( const std::string& challenge) { if (challenge.empty()) { - LOG(ERROR) << "Easy unlock failed to generate challenge."; + PA_LOG(ERROR) << "Easy unlock failed to generate challenge."; callback_.Run(false); return; } @@ -273,14 +274,14 @@ std::string iv(kSessionKeyByteSize, ' '); crypto::Encryptor encryptor; if (!encryptor.Init(session_key.get(), crypto::Encryptor::CBC, iv)) { - LOG(ERROR) << "Easy unlock failed to init encryptor for key creation."; + PA_LOG(ERROR) << "Easy unlock failed to init encryptor for key creation."; callback_.Run(false); return; } EasyUnlockDeviceKeyData* device = &devices_[index]; if (!encryptor.Encrypt(user_key, &device->wrapped_secret)) { - LOG(ERROR) << "Easy unlock failed to encrypt user key for key creation."; + PA_LOG(ERROR) << "Easy unlock failed to encrypt user key for key creation."; callback_.Run(false); return; } @@ -304,7 +305,7 @@ DCHECK_EQ(key_creation_index_, index); if (!success) { - LOG(ERROR) << "Easy unlock failed to create challenge for key creation."; + PA_LOG(ERROR) << "Easy unlock failed to create challenge for key creation."; callback_.Run(false); return; } @@ -320,7 +321,7 @@ const std::string& system_salt) { DCHECK_EQ(key_creation_index_, index); if (system_salt.empty()) { - LOG(ERROR) << "Easy unlock failed to get system salt for key creation."; + PA_LOG(ERROR) << "Easy unlock failed to get system salt for key creation."; callback_.Run(false); return; } @@ -337,6 +338,9 @@ key_def.provider_data.push_back(cryptohome::KeyDefinition::ProviderData( kEasyUnlockKeyMetaNameBluetoothAddress, device->bluetooth_address)); key_def.provider_data.push_back(cryptohome::KeyDefinition::ProviderData( + kEasyUnlockKeyMetaNameBluetoothType, + static_cast<int64>(device->bluetooth_type))); + key_def.provider_data.push_back(cryptohome::KeyDefinition::ProviderData( kEasyUnlockKeyMetaNamePsk, device->psk)); key_def.provider_data.push_back(cryptohome::KeyDefinition::ProviderData( kEasyUnlockKeyMetaNamePubKey, device->public_key)); @@ -374,7 +378,7 @@ DCHECK_EQ(key_creation_index_, index); if (!success) { - LOG(ERROR) << "Easy unlock failed to create key, code=" << return_code; + PA_LOG(ERROR) << "Easy unlock failed to create key, code=" << return_code; callback_.Run(false); return; }
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_get_keys_operation.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_get_keys_operation.cc index 7e625679..739b3d32 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_get_keys_operation.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_get_keys_operation.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/logging.h" #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h" +#include "components/proximity_auth/logging/logging.h" #include "components/signin/core/account_id/account_id.h" #include "google_apis/gaia/gaia_auth_util.h" @@ -57,7 +58,7 @@ return; } - LOG(ERROR) << "Easy unlock failed to get key data, code=" << return_code; + PA_LOG(ERROR) << "Easy unlock failed to get key data, code=" << return_code; callback_.Run(false, EasyUnlockDeviceKeyDataList()); return; } @@ -75,6 +76,19 @@ device.bluetooth_address = *entry.bytes; else NOTREACHED(); + } else if (entry.name == kEasyUnlockKeyMetaNameBluetoothType) { + if (entry.number) { + if (*entry.number >= + static_cast<int64>(EasyUnlockDeviceKeyData::NUM_BLUETOOTH_TYPES)) { + PA_LOG(ERROR) << "Invalid Bluetooth type: " << *entry.number; + } else { + device.bluetooth_type = + static_cast<EasyUnlockDeviceKeyData::BluetoothType>( + *entry.number); + } + } else { + NOTREACHED(); + } } else if (entry.name == kEasyUnlockKeyMetaNamePubKey) { if (entry.bytes) device.public_key = *entry.bytes; @@ -96,8 +110,8 @@ else NOTREACHED(); } else { - LOG(WARNING) << "Unknown Easy unlock key data entry, name=" - << entry.name; + PA_LOG(WARNING) << "Unknown Easy unlock key data entry, name=" + << entry.name; } } devices_.push_back(device);
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.cc index 3cfa4bc..eb42a33 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.cc
@@ -11,6 +11,7 @@ #include "base/values.h" #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h" #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h" +#include "components/proximity_auth/logging/logging.h" #include "components/signin/core/account_id/account_id.h" namespace chromeos { @@ -18,6 +19,7 @@ namespace { const char kKeyBluetoothAddress[] = "bluetoothAddress"; +const char kKeyBluetoothType[] = "bluetoothType"; const char kKeyPermitRecord[] = "permitRecord"; const char kKeyPermitId[] = "permitRecord.id"; const char kKeyPermitPermitId[] = "permitRecord.permitId"; @@ -55,7 +57,7 @@ EasyUnlockTpmKeyManagerFactory::GetInstance()->GetForUser( user_context.GetAccountId().GetUserEmail()); if (!tpm_key_manager) { - LOG(ERROR) << "No TPM key manager."; + PA_LOG(ERROR) << "No TPM key manager."; callback.Run(false); return; } @@ -112,6 +114,7 @@ const EasyUnlockDeviceKeyData& data, base::DictionaryValue* dict) { dict->SetString(kKeyBluetoothAddress, data.bluetooth_address); + dict->SetInteger(kKeyBluetoothType, static_cast<int>(data.bluetooth_type)); dict->SetString(kKeyPsk, data.psk); scoped_ptr<base::DictionaryValue> permit_record(new base::DictionaryValue); dict->Set(kKeyPermitRecord, permit_record.release()); @@ -137,6 +140,19 @@ return false; } + // TODO(tengs): Move this conditional up once we can be certain that the + // dictionary will contain the Bluetooth type key. + int bluetooth_type_as_int; + if (dict.GetInteger(kKeyBluetoothType, &bluetooth_type_as_int)) { + if (bluetooth_type_as_int >= EasyUnlockDeviceKeyData::NUM_BLUETOOTH_TYPES) { + PA_LOG(ERROR) << "Invalid Bluetooth type: " << bluetooth_type_as_int; + } else { + data->bluetooth_type = + static_cast<EasyUnlockDeviceKeyData::BluetoothType>( + bluetooth_type_as_int); + } + } + data->bluetooth_address.swap(bluetooth_address); data->public_key.swap(public_key); data->psk.swap(psk);
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_types.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_types.cc index a13eb4ab..783a31e 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_types.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_types.cc
@@ -7,13 +7,14 @@ namespace chromeos { const char kEasyUnlockKeyMetaNameBluetoothAddress[] = "eu.btaddr"; +const char kEasyUnlockKeyMetaNameBluetoothType[] = "eu.bttype"; const char kEasyUnlockKeyMetaNamePsk[] = "eu.psk"; const char kEasyUnlockKeyMetaNamePubKey[] = "eu.pubkey"; const char kEasyUnlockKeyMetaNameChallenge[] = "eu.C"; const char kEasyUnlockKeyMetaNameWrappedSecret[] = "eu.WUK"; -EasyUnlockDeviceKeyData::EasyUnlockDeviceKeyData() { -} +EasyUnlockDeviceKeyData::EasyUnlockDeviceKeyData() + : bluetooth_type(BLUETOOTH_CLASSIC) {} EasyUnlockDeviceKeyData::~EasyUnlockDeviceKeyData() { }
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_types.h b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_types.h index 0f71b9c0..55bc4e4 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_types.h +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_types.h
@@ -11,6 +11,7 @@ namespace chromeos { extern const char kEasyUnlockKeyMetaNameBluetoothAddress[]; +extern const char kEasyUnlockKeyMetaNameBluetoothType[]; extern const char kEasyUnlockKeyMetaNamePsk[]; extern const char kEasyUnlockKeyMetaNamePubKey[]; extern const char kEasyUnlockKeyMetaNameChallenge[]; @@ -18,11 +19,16 @@ // Device data that is stored with cryptohome keys. struct EasyUnlockDeviceKeyData { + // The Bluetooth type. By default, the assumed type is BLUETOOTH_CLASSIC. + enum BluetoothType { BLUETOOTH_CLASSIC, BLUETOOTH_LE, NUM_BLUETOOTH_TYPES }; + EasyUnlockDeviceKeyData(); ~EasyUnlockDeviceKeyData(); // Bluetooth address of the remote device. std::string bluetooth_address; + // The Bluetooth type to connect to the device. + BluetoothType bluetooth_type; // Public key of the remote device. std::string public_key; // Key to establish a secure channel with the remote device.
diff --git a/chrome/browser/chromeos/net/wake_on_wifi_manager.cc b/chrome/browser/chromeos/net/wake_on_wifi_manager.cc index 3fb3bba..370acb2 100644 --- a/chrome/browser/chromeos/net/wake_on_wifi_manager.cc +++ b/chrome/browser/chromeos/net/wake_on_wifi_manager.cc
@@ -15,7 +15,6 @@ #include "base/values.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/services/gcm/gcm_profile_service.h" #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" #include "chromeos/chromeos_switches.h" #include "chromeos/login/login_state.h" @@ -26,6 +25,7 @@ #include "chromeos/network/network_type_pattern.h" #include "components/gcm_driver/gcm_connection_observer.h" #include "components/gcm_driver/gcm_driver.h" +#include "components/gcm_driver/gcm_profile_service.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h"
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc index b547a00..2bef961 100644 --- a/chrome/browser/devtools/devtools_sanity_browsertest.cc +++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -610,19 +610,12 @@ &chrome::CloseAllBrowsers)); } -// Times out on Win and Linux -// @see http://crbug.com/410327 -#if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) -#define MAYBE_TestUndockedDevToolsUnresponsive DISABLED_TestUndockedDevToolsUnresponsive -#else -#define MAYBE_TestUndockedDevToolsUnresponsive TestUndockedDevToolsUnresponsive -#endif - // Tests that inspected tab gets closed if devtools renderer // becomes unresponsive during beforeunload event interception. // @see http://crbug.com/322380 +// Disabled because of http://crbug.com/410327 IN_PROC_BROWSER_TEST_F(DevToolsUnresponsiveBeforeUnloadTest, - MAYBE_TestUndockedDevToolsUnresponsive) { + DISABLED_TestUndockedDevToolsUnresponsive) { ASSERT_TRUE(test_server()->Start()); LoadTestPage(kDebuggerTestPage); DevToolsWindow* devtools_window = OpenDevToolWindowOnWebContents(
diff --git a/chrome/browser/dom_distiller/profile_utils.cc b/chrome/browser/dom_distiller/profile_utils.cc index 1e2c54d5..b48fdfc 100644 --- a/chrome/browser/dom_distiller/profile_utils.cc +++ b/chrome/browser/dom_distiller/profile_utils.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/dom_distiller/lazy_dom_distiller_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_isolated_world_ids.h" +#include "chrome/common/chrome_switches.h" #include "components/dom_distiller/content/browser/distiller_javascript_utils.h" #include "components/dom_distiller/content/browser/distiller_ui_handle.h" #include "components/dom_distiller/content/browser/dom_distiller_viewer_source.h" @@ -23,7 +24,8 @@ void RegisterDomDistillerViewerSource(Profile* profile) { const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); - if (command_line.HasSwitch(switches::kEnableDomDistiller)) { + if (command_line.HasSwitch(switches::kEnableDomDistiller) || + !command_line.HasSwitch(switches::kDisablePrintPreviewSimplify)) { dom_distiller::DomDistillerServiceFactory* dom_distiller_service_factory = dom_distiller::DomDistillerServiceFactory::GetInstance(); // The LazyDomDistillerService deletes itself when the profile is destroyed.
diff --git a/chrome/browser/download/download_shelf.cc b/chrome/browser/download/download_shelf.cc index 0ec6610..fd044c5 100644 --- a/chrome/browser/download/download_shelf.cc +++ b/chrome/browser/download/download_shelf.cc
@@ -121,9 +121,9 @@ double animation_progress) { // Start at full opacity, then loop back and forth five times before ending // at zero opacity. - canvas->sk_canvas()->saveLayerAlpha(nullptr, GetOpacity(animation_progress)); + canvas->SaveLayerAlpha(GetOpacity(animation_progress)); PaintDownloadProgress(canvas, theme_provider, base::TimeDelta(), 100); - canvas->sk_canvas()->restore(); + canvas->Restore(); } // static
diff --git a/chrome/browser/download/save_page_browsertest.cc b/chrome/browser/download/save_page_browsertest.cc index daa54c1..3ceee5d 100644 --- a/chrome/browser/download/save_page_browsertest.cc +++ b/chrome/browser/download/save_page_browsertest.cc
@@ -397,13 +397,7 @@ DISALLOW_COPY_AND_ASSIGN(SavePageBrowserTest); }; -// Disabled on Windows due to flakiness. http://crbug.com/162323 -#if defined(OS_WIN) -#define MAYBE_SaveHTMLOnly DISABLED_SaveHTMLOnly -#else -#define MAYBE_SaveHTMLOnly SaveHTMLOnly -#endif -IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_SaveHTMLOnly) { +IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveHTMLOnly) { GURL url = NavigateToMockURL("a"); base::FilePath full_file_name, dir; @@ -417,8 +411,7 @@ kTestDir)).Append(FILE_PATH_LITERAL("a.htm")), full_file_name)); } -// http://crbug.com/162323 -IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, DISABLED_SaveHTMLOnlyCancel) { +IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveHTMLOnlyCancel) { GURL url = NavigateToMockURL("a"); DownloadManager* manager(GetDownloadManager()); std::vector<DownloadItem*> downloads; @@ -468,13 +461,7 @@ DISALLOW_COPY_AND_ASSIGN(DelayingDownloadManagerDelegate); }; -// Disabled on Windows due to flakiness. http://crbug.com/162323 -#if defined(OS_WIN) -#define MAYBE_SaveHTMLOnlyTabDestroy DISABLED_SaveHTMLOnlyTabDestroy -#else -#define MAYBE_SaveHTMLOnlyTabDestroy SaveHTMLOnlyTabDestroy -#endif -IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_SaveHTMLOnlyTabDestroy) { +IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveHTMLOnlyTabDestroy) { GURL url = NavigateToMockURL("a"); scoped_ptr<DelayingDownloadManagerDelegate> delaying_delegate( new DelayingDownloadManagerDelegate(browser()->profile())); @@ -504,13 +491,7 @@ EXPECT_FALSE(base::PathExists(dir)); } -// Disabled on Windows due to flakiness. http://crbug.com/162323 -#if defined(OS_WIN) -#define MAYBE_SaveViewSourceHTMLOnly DISABLED_SaveViewSourceHTMLOnly -#else -#define MAYBE_SaveViewSourceHTMLOnly SaveViewSourceHTMLOnly -#endif -IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_SaveViewSourceHTMLOnly) { +IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveViewSourceHTMLOnly) { GURL mock_url = URLRequestMockHTTPJob::GetMockUrl("save_page/a.htm"); GURL view_source_url = GURL(content::kViewSourceScheme + std::string(":") + mock_url.spec()); @@ -530,13 +511,7 @@ full_file_name)); } -// Disabled on Windows due to flakiness. http://crbug.com/162323 -#if defined(OS_WIN) -#define MAYBE_SaveCompleteHTML DISABLED_SaveCompleteHTML -#else -#define MAYBE_SaveCompleteHTML SaveCompleteHTML -#endif -IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, DISABLED_SaveCompleteHTML) { +IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveCompleteHTML) { GURL url = NavigateToMockURL("b"); base::FilePath full_file_name, dir; @@ -557,16 +532,8 @@ dir.AppendASCII("1.css"))); } -// Invoke a save page during the initial navigation. -// (Regression test for http://crbug.com/156538). -// Disabled on Windows due to flakiness. http://crbug.com/162323 -#if defined(OS_WIN) -#define MAYBE_SaveDuringInitialNavigationIncognito DISABLED_SaveDuringInitialNavigationIncognito -#else -#define MAYBE_SaveDuringInitialNavigationIncognito SaveDuringInitialNavigationIncognito -#endif IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, - MAYBE_SaveDuringInitialNavigationIncognito) { + SaveDuringInitialNavigationIncognito) { // Open an Incognito window. Browser* incognito = CreateIncognitoBrowser(); // Waits. ASSERT_TRUE(incognito); @@ -606,13 +573,7 @@ EXPECT_FALSE(chrome::CanSavePage(browser())); } -// Disabled on Windows due to flakiness. http://crbug.com/162323 -#if defined(OS_WIN) -#define MAYBE_FileNameFromPageTitle DISABLED_FileNameFromPageTitle -#else -#define MAYBE_FileNameFromPageTitle FileNameFromPageTitle -#endif -IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, DISABLED_FileNameFromPageTitle) { +IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, FileNameFromPageTitle) { GURL url = NavigateToMockURL("b"); base::FilePath full_file_name = save_dir_.path().AppendASCII( @@ -647,13 +608,7 @@ dir.AppendASCII("1.css"))); } -// Disabled on Windows due to flakiness. http://crbug.com/162323 -#if defined(OS_WIN) -#define MAYBE_RemoveFromList DISABLED_RemoveFromList -#else -#define MAYBE_RemoveFromList RemoveFromList -#endif -IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_RemoveFromList) { +IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, RemoveFromList) { GURL url = NavigateToMockURL("a"); base::FilePath full_file_name, dir;
diff --git a/chrome/browser/extensions/api/copresence/copresence_api.cc b/chrome/browser/extensions/api/copresence/copresence_api.cc index edfd509..9324c3f 100644 --- a/chrome/browser/extensions/api/copresence/copresence_api.cc +++ b/chrome/browser/extensions/api/copresence/copresence_api.cc
@@ -9,7 +9,6 @@ #include "base/prefs/pref_service.h" #include "chrome/browser/copresence/chrome_whispernet_client.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/services/gcm/gcm_profile_service.h" #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" #include "chrome/common/channel_info.h" #include "chrome/common/extensions/api/copresence.h" @@ -19,6 +18,7 @@ #include "components/copresence/proto/data.pb.h" #include "components/copresence/proto/enums.pb.h" #include "components/copresence/proto/rpcs.pb.h" +#include "components/gcm_driver/gcm_profile_service.h" #include "components/pref_registry/pref_registry_syncable.h" #include "content/public/browser/browser_context.h" #include "extensions/browser/event_router.h"
diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc index 912bd70..fc1c8c8 100644 --- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc +++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc
@@ -26,6 +26,7 @@ #include "chromeos/dbus/fake_easy_unlock_client.h" #include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h" #include "components/proximity_auth/switches.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" #include "extensions/browser/api_test_utils.h" #include "extensions/browser/event_router.h" #include "extensions/browser/event_router_factory.h" @@ -127,6 +128,10 @@ protected: void SetUp() override { chromeos::DBusThreadManager::Initialize(); + bluez::BluezDBusManager::Initialize( + chromeos::DBusThreadManager::Get()->GetSystemBus(), + chromeos::DBusThreadManager::Get()->IsUsingStub( + chromeos::DBusClientBundle::BLUETOOTH)); client_ = chromeos::DBusThreadManager::Get()->GetEasyUnlockClient(); extensions::ExtensionApiUnittest::SetUp(); @@ -135,6 +140,7 @@ void TearDown() override { extensions::ExtensionApiUnittest::TearDown(); + bluez::BluezDBusManager::Shutdown(); chromeos::DBusThreadManager::Shutdown(); }
diff --git a/chrome/browser/extensions/api/gcd_private/gcd_private_api.cc b/chrome/browser/extensions/api/gcd_private/gcd_private_api.cc index 8a837566..cafa806 100644 --- a/chrome/browser/extensions/api/gcd_private/gcd_private_api.cc +++ b/chrome/browser/extensions/api/gcd_private/gcd_private_api.cc
@@ -31,10 +31,6 @@ #include "extensions/browser/event_router.h" #include "net/base/net_util.h" -#if defined(ENABLE_WIFI_BOOTSTRAPPING) -#include "chrome/browser/local_discovery/wifi/wifi_manager.h" -#endif - namespace extensions { namespace gcd_private = api::gcd_private; @@ -174,14 +170,6 @@ const CreateSessionCallback& callback, scoped_ptr<local_discovery::PrivetHTTPClient> client); -#if defined(ENABLE_WIFI_BOOTSTRAPPING) - void OnWifiPassword(const SuccessCallback& callback, - bool success, - const std::string& ssid, - const std::string& password); - void StartWifiIfNotStarted(); -#endif - int num_device_listeners_; scoped_refptr<local_discovery::ServiceDiscoverySharedClient> service_discovery_client_; @@ -198,9 +186,6 @@ content::BrowserContext* const browser_context_; -#if defined(ENABLE_WIFI_BOOTSTRAPPING) - scoped_ptr<local_discovery::wifi::WifiManager> wifi_manager_; -#endif PasswordMap wifi_passwords_; base::WeakPtrFactory<GcdPrivateAPIImpl> weak_ptr_factory_{this}; @@ -418,38 +403,9 @@ void GcdPrivateAPIImpl::RequestWifiPassword(const std::string& ssid, const SuccessCallback& callback) { -#if defined(ENABLE_WIFI_BOOTSTRAPPING) - StartWifiIfNotStarted(); - wifi_manager_->RequestNetworkCredentials( - ssid, - base::Bind(&GcdPrivateAPIImpl::OnWifiPassword, - base::Unretained(this), - callback)); -#else callback.Run(false); -#endif } -#if defined(ENABLE_WIFI_BOOTSTRAPPING) -void GcdPrivateAPIImpl::OnWifiPassword(const SuccessCallback& callback, - bool success, - const std::string& ssid, - const std::string& password) { - if (success) - wifi_passwords_[ssid] = password; - - callback.Run(success); -} - -void GcdPrivateAPIImpl::StartWifiIfNotStarted() { - if (!wifi_manager_) { - wifi_manager_ = local_discovery::wifi::WifiManager::Create(); - wifi_manager_->Start(); - } -} - -#endif - void GcdPrivateAPIImpl::RemoveSession(int session_id) { sessions_.erase(session_id); } @@ -463,14 +419,6 @@ scoped_ptr<base::ListValue> GcdPrivateAPIImpl::GetPrefetchedSSIDList() { scoped_ptr<base::ListValue> retval(new base::ListValue); -#if defined(ENABLE_WIFI_BOOTSTRAPPING) - for (PasswordMap::iterator i = wifi_passwords_.begin(); - i != wifi_passwords_.end(); - i++) { - retval->AppendString(i->first); - } -#endif - return retval.Pass(); }
diff --git a/chrome/browser/extensions/api/gcd_private/gcd_private_apitest.cc b/chrome/browser/extensions/api/gcd_private/gcd_private_apitest.cc index 6a920e8d..1552a784 100644 --- a/chrome/browser/extensions/api/gcd_private/gcd_private_apitest.cc +++ b/chrome/browser/extensions/api/gcd_private/gcd_private_apitest.cc
@@ -10,7 +10,6 @@ #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/local_discovery/gcd_api_flow.h" -#include "chrome/browser/local_discovery/wifi/mock_wifi_manager.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/api/mdns.h" #include "extensions/common/switches.h" @@ -328,47 +327,4 @@ } #endif // ENABLE_MDNS -#if defined(ENABLE_WIFI_BOOTSTRAPPING) -class GcdPrivateWithWifiAPITest : public GcdPrivateAPITest { - public: - virtual void OnCreateWifiManager() { - wifi_manager_ = wifi_manager_factory_.GetLastCreatedWifiManager(); - - EXPECT_CALL(*wifi_manager_, Start()); - - EXPECT_CALL(*wifi_manager_, - RequestNetworkCredentialsInternal("SuccessNetwork")) - .WillOnce(Invoke(this, &GcdPrivateWithWifiAPITest::RespondToNetwork)); - - EXPECT_CALL(*wifi_manager_, - RequestNetworkCredentialsInternal("FailureNetwork")) - .WillOnce(Invoke(this, &GcdPrivateWithWifiAPITest::RespondToNetwork)); - } - - void RespondToNetwork(const std::string& network) { - bool success = (network == "SuccessNetwork"); - - wifi_manager_->CallRequestNetworkCredentialsCallback( - success, network, success ? "SuccessPass" : ""); - } - - protected: - local_discovery::wifi::MockWifiManagerFactory wifi_manager_factory_; - local_discovery::wifi::MockWifiManager* wifi_manager_; -}; - -IN_PROC_BROWSER_TEST_F(GcdPrivateWithWifiAPITest, WifiMessage) { - EXPECT_TRUE(RunExtensionSubtest("gcd_private/api", "wifi_message.html")); -} - -IN_PROC_BROWSER_TEST_F(GcdPrivateWithWifiAPITest, WifiPasswords) { - if (ExtensionSubtestsAreSkipped()) - return; - EXPECT_CALL(wifi_manager_factory_, WifiManagerCreated()) - .WillOnce(Invoke(this, &GcdPrivateWithWifiAPITest::OnCreateWifiManager)); - - EXPECT_TRUE(RunExtensionSubtest("gcd_private/api", "wifi_password.html")); -} -#endif // ENABLE_WIFI_BOOTSTRAPPING - } // namespace
diff --git a/chrome/browser/extensions/api/gcm/gcm_api.cc b/chrome/browser/extensions/api/gcm/gcm_api.cc index 60dd292..09275a3 100644 --- a/chrome/browser/extensions/api/gcm/gcm_api.cc +++ b/chrome/browser/extensions/api/gcm/gcm_api.cc
@@ -13,11 +13,11 @@ #include "base/strings/string_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/services/gcm/gcm_profile_service.h" #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" #include "chrome/common/extensions/api/gcm.h" #include "components/gcm_driver/common/gcm_messages.h" #include "components/gcm_driver/gcm_driver.h" +#include "components/gcm_driver/gcm_profile_service.h" #include "extensions/browser/event_router.h" #include "extensions/common/extension.h" @@ -96,7 +96,7 @@ if (profile->IsOffTheRecord()) return false; - return gcm::GCMProfileService::IsGCMEnabled(profile); + return gcm::GCMProfileService::IsGCMEnabled(profile->GetPrefs()); } gcm::GCMDriver* GcmApiFunction::GetGCMDriver() const {
diff --git a/chrome/browser/extensions/api/instance_id/instance_id_apitest.cc b/chrome/browser/extensions/api/instance_id/instance_id_apitest.cc index 1929671..2b5174d 100644 --- a/chrome/browser/extensions/api/instance_id/instance_id_apitest.cc +++ b/chrome/browser/extensions/api/instance_id/instance_id_apitest.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/services/gcm/fake_gcm_profile_service.h" #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" #include "chrome/browser/services/gcm/instance_id/instance_id_profile_service_factory.h" +#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" #include "chrome/test/base/ui_test_utils.h" #include "components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.h" #include "components/version_info/version_info.h" @@ -27,7 +28,10 @@ content::BrowserContext* context) { scoped_ptr<gcm::FakeGCMProfileService> service( new gcm::FakeGCMProfileService(Profile::FromBrowserContext(context))); - service->SetDriverForTesting(new instance_id::FakeGCMDriverForInstanceID()); + service->SetDriverForTesting( + LoginUIServiceFactory::GetShowLoginPopupCallbackForProfile( + Profile::FromBrowserContext(context)), + new instance_id::FakeGCMDriverForInstanceID()); return service.Pass(); }
diff --git a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc index e310f158..705911c 100644 --- a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc +++ b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
@@ -11,6 +11,7 @@ #include "base/containers/hash_tables.h" #include "base/i18n/rtl.h" +#include "base/memory/linked_ptr.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" @@ -30,10 +31,23 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util_collator.h" +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/input_method/input_method_util.h" +#include "ui/base/ime/chromeos/component_extension_ime_manager.h" +#include "ui/base/ime/chromeos/extension_ime_util.h" +#include "ui/base/ime/chromeos/input_method_manager.h" +#endif + namespace extensions { namespace language_settings_private = api::language_settings_private; +#if defined(OS_CHROMEOS) +using chromeos::input_method::InputMethodDescriptors; +using chromeos::input_method::InputMethodManager; +using chromeos::input_method::InputMethodUtil; +#endif + LanguageSettingsPrivateGetLanguageListFunction:: LanguageSettingsPrivateGetLanguageListFunction() { } @@ -278,6 +292,42 @@ chrome_details_.GetProfile()->GetPrefs())))); } +#if defined(OS_CHROMEOS) +// Populates the vector of input methods using information in the list of +// descriptors. Used for languageSettingsPrivate.getInputMethodLists(). +void PopulateInputMethodListFromDescriptors( + const InputMethodDescriptors& descriptors, + std::vector<linked_ptr<language_settings_private::InputMethod>>* + input_methods) { + InputMethodManager* manager = InputMethodManager::Get(); + InputMethodUtil* util = manager->GetInputMethodUtil(); + scoped_refptr<InputMethodManager::State> ime_state = + manager->GetActiveIMEState(); + if (!ime_state.get()) + return; + + // Get the list of enabled IDs and convert to a set for membership testing. + const std::vector<std::string>& active_ids_list = + ime_state->GetActiveInputMethodIds(); + const std::set<std::string> active_ids( + active_ids_list.begin(), active_ids_list.end()); + + for (const auto& descriptor : descriptors) { + linked_ptr<language_settings_private::InputMethod> input_method( + new language_settings_private::InputMethod()); + input_method->id = descriptor.id(); + input_method->display_name = util->GetLocalizedDisplayName(descriptor); + input_method->language_codes = descriptor.language_codes(); + bool enabled = active_ids.find(input_method->id) != active_ids.end(); + if (enabled) + input_method->enabled.reset(new bool(true)); + if (descriptor.options_page_url().is_valid()) + input_method->has_options_page.reset(new bool(true)); + input_methods->push_back(input_method); + } +} +#endif + LanguageSettingsPrivateGetInputMethodListsFunction:: LanguageSettingsPrivateGetInputMethodListsFunction() { } @@ -288,7 +338,31 @@ ExtensionFunction::ResponseAction LanguageSettingsPrivateGetInputMethodListsFunction::Run() { - return RespondNow(OneArgument(new base::DictionaryValue())); +#if !defined(OS_CHROMEOS) + EXTENSION_FUNCTION_VALIDATE(false); + return RespondNow(NoArguments()); +#else + language_settings_private::InputMethodLists input_method_lists; + InputMethodManager* manager = InputMethodManager::Get(); + + chromeos::ComponentExtensionIMEManager* component_extension_manager = + manager->GetComponentExtensionIMEManager(); + PopulateInputMethodListFromDescriptors( + component_extension_manager->GetAllIMEAsInputMethodDescriptor(), + &input_method_lists.component_extension_imes); + + scoped_refptr<InputMethodManager::State> ime_state = + manager->GetActiveIMEState(); + if (ime_state.get()) { + InputMethodDescriptors ext_ime_descriptors; + ime_state->GetInputMethodExtensions(&ext_ime_descriptors); + PopulateInputMethodListFromDescriptors( + ext_ime_descriptors, + &input_method_lists.third_party_extension_imes); + } + + return RespondNow(OneArgument(input_method_lists.ToValue())); +#endif } LanguageSettingsPrivateAddInputMethodFunction::
diff --git a/chrome/browser/extensions/extension_gcm_app_handler.cc b/chrome/browser/extensions/extension_gcm_app_handler.cc index 4d9e2ac..4fc5e29 100644 --- a/chrome/browser/extensions/extension_gcm_app_handler.cc +++ b/chrome/browser/extensions/extension_gcm_app_handler.cc
@@ -12,11 +12,11 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/api/gcm/gcm_api.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/services/gcm/gcm_profile_service.h" #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" #include "chrome/browser/services/gcm/instance_id/instance_id_profile_service.h" #include "chrome/browser/services/gcm/instance_id/instance_id_profile_service_factory.h" #include "components/gcm_driver/gcm_driver.h" +#include "components/gcm_driver/gcm_profile_service.h" #include "components/gcm_driver/instance_id/instance_id_driver.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h"
diff --git a/chrome/browser/extensions/extension_gcm_app_handler_unittest.cc b/chrome/browser/extensions/extension_gcm_app_handler_unittest.cc index 59737ca4..c51beec8 100644 --- a/chrome/browser/extensions/extension_gcm_app_handler_unittest.cc +++ b/chrome/browser/extensions/extension_gcm_app_handler_unittest.cc
@@ -26,8 +26,11 @@ #include "chrome/browser/extensions/test_extension_service.h" #include "chrome/browser/extensions/test_extension_system.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/services/gcm/gcm_profile_service.h" #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" +#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" +#include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" +#include "chrome/common/channel_info.h" #include "chrome/common/chrome_paths.h" #include "chrome/test/base/testing_profile.h" #include "components/gcm_driver/fake_gcm_app_handler.h" @@ -35,7 +38,9 @@ #include "components/gcm_driver/fake_gcm_client_factory.h" #include "components/gcm_driver/gcm_client_factory.h" #include "components/gcm_driver/gcm_driver.h" +#include "components/gcm_driver/gcm_profile_service.h" #include "components/keyed_service/core/keyed_service.h" +#include "components/signin/core/browser/signin_manager.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_browser_thread_bundle.h" @@ -190,13 +195,29 @@ public: static scoped_ptr<KeyedService> BuildGCMProfileService( content::BrowserContext* context) { + Profile* profile = Profile::FromBrowserContext(context); + scoped_refptr<base::SequencedTaskRunner> ui_thread = + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::UI); + scoped_refptr<base::SequencedTaskRunner> io_thread = + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::IO); + base::SequencedWorkerPool* worker_pool = + content::BrowserThread::GetBlockingPool(); + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner( + worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( + worker_pool->GetSequenceToken(), + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); return make_scoped_ptr(new gcm::GCMProfileService( - Profile::FromBrowserContext(context), - scoped_ptr<gcm::GCMClientFactory>(new gcm::FakeGCMClientFactory( - content::BrowserThread::GetMessageLoopProxyForThread( - content::BrowserThread::UI), - content::BrowserThread::GetMessageLoopProxyForThread( - content::BrowserThread::IO))))); + profile->GetPrefs(), profile->GetPath(), profile->GetRequestContext(), + chrome::GetChannel(), + scoped_ptr<ProfileIdentityProvider>(new ProfileIdentityProvider( + SigninManagerFactory::GetForProfile(profile), + ProfileOAuth2TokenServiceFactory::GetForProfile(profile), + LoginUIServiceFactory::GetShowLoginPopupCallbackForProfile( + profile))), + make_scoped_ptr(new gcm::FakeGCMClientFactory(ui_thread, io_thread)), + ui_thread, io_thread, blocking_task_runner)); } ExtensionGCMAppHandlerTest()
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index 0fa7c9e..4753fa0 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc
@@ -60,7 +60,6 @@ #include "chrome/common/url_constants.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/crx_file/id_util.h" -#include "components/startup_metric_utils/startup_metric_utils.h" #include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/render_process_host.h"
diff --git a/chrome/browser/extensions/fake_safe_browsing_database_manager.cc b/chrome/browser/extensions/fake_safe_browsing_database_manager.cc index 0897401..3dc42740 100644 --- a/chrome/browser/extensions/fake_safe_browsing_database_manager.cc +++ b/chrome/browser/extensions/fake_safe_browsing_database_manager.cc
@@ -100,14 +100,14 @@ std::vector<SBFullHash> extension_id_hashes; std::transform(extension_ids_vector.begin(), extension_ids_vector.end(), std::back_inserter(extension_id_hashes), - safe_browsing_util::StringToSBFullHash); + safe_browsing::StringToSBFullHash); scoped_ptr<SafeBrowsingCheck> safe_browsing_check( new SafeBrowsingCheck( std::vector<GURL>(), extension_id_hashes, client, - safe_browsing_util::EXTENSIONBLACKLIST, + safe_browsing::EXTENSIONBLACKLIST, std::vector<SBThreatType>(1, SB_THREAT_TYPE_EXTENSION))); for (size_t i = 0; i < extension_ids_vector.size(); ++i) {
diff --git a/chrome/browser/file_select_helper.cc b/chrome/browser/file_select_helper.cc index f1d15f4..6fa623f 100644 --- a/chrome/browser/file_select_helper.cc +++ b/chrome/browser/file_select_helper.cc
@@ -387,7 +387,9 @@ // FileSelectHelper will keep itself alive until it sends the result message. scoped_refptr<FileSelectHelper> file_select_helper( new FileSelectHelper(profile)); - file_select_helper->RunFileChooser(tab->GetRenderViewHost(), tab, params); + file_select_helper->RunFileChooser( + tab->GetRenderViewHost(), tab, + make_scoped_ptr(new content::FileChooserParams(params))); } // static @@ -404,14 +406,14 @@ void FileSelectHelper::RunFileChooser(RenderViewHost* render_view_host, content::WebContents* web_contents, - const FileChooserParams& params) { + scoped_ptr<FileChooserParams> params) { DCHECK(!render_view_host_); DCHECK(!web_contents_); - DCHECK(params.default_file_name.empty() || - params.mode == FileChooserParams::Save) + DCHECK(params->default_file_name.empty() || + params->mode == FileChooserParams::Save) << "The default_file_name parameter should only be specified for Save " "file choosers"; - DCHECK(params.default_file_name == params.default_file_name.BaseName()) + DCHECK(params->default_file_name == params->default_file_name.BaseName()) << "The default_file_name parameter should not contain path separators"; render_view_host_ = render_view_host; @@ -424,7 +426,8 @@ BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, - base::Bind(&FileSelectHelper::RunFileChooserOnFileThread, this, params)); + base::Bind(&FileSelectHelper::GetFileTypesOnFileThread, this, + base::Passed(¶ms))); // Because this class returns notifications to the RenderViewHost, it is // difficult for callers to know how long to keep a reference to this @@ -434,18 +437,58 @@ AddRef(); } -void FileSelectHelper::RunFileChooserOnFileThread( - const FileChooserParams& params) { - select_file_types_ = GetFileTypesFromAcceptType(params.accept_types); - select_file_types_->support_drive = !params.need_local_path; +void FileSelectHelper::GetFileTypesOnFileThread( + scoped_ptr<FileChooserParams> params) { + select_file_types_ = GetFileTypesFromAcceptType(params->accept_types); + select_file_types_->support_drive = !params->need_local_path; BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(&FileSelectHelper::RunFileChooserOnUIThread, this, params)); + base::Bind(&FileSelectHelper::GetSanitizedFilenameOnUIThread, this, + base::Passed(¶ms))); } +void FileSelectHelper::GetSanitizedFilenameOnUIThread( + scoped_ptr<FileChooserParams> params) { + base::FilePath default_file_path = profile_->last_selected_directory().Append( + GetSanitizedFileName(params->default_file_name)); + +#if defined(FULL_SAFE_BROWSING) + // Note that FileChooserParams::requestor is not considered a trusted field + // since it's provided by the renderer and not validated browserside. + if (params->mode == FileChooserParams::Save && + !params->default_file_name.empty()) { + GURL requestor = params->requestor; + safe_browsing::CheckUnverifiedDownloadPolicy( + requestor, default_file_path, + base::Bind(&FileSelectHelper::ApplyUnverifiedDownloadPolicy, this, + default_file_path, base::Passed(¶ms))); + return; + } +#endif + + RunFileChooserOnUIThread(default_file_path, params.Pass()); +} + +#if defined(FULL_SAFE_BROWSING) +void FileSelectHelper::ApplyUnverifiedDownloadPolicy( + const base::FilePath& default_path, + scoped_ptr<FileChooserParams> params, + safe_browsing::UnverifiedDownloadPolicy policy) { + DCHECK(params); + if (policy == safe_browsing::UnverifiedDownloadPolicy::DISALLOWED) { + NotifyRenderViewHostAndEnd(std::vector<ui::SelectedFileInfo>()); + return; + } + + RunFileChooserOnUIThread(default_path, params.Pass()); +} +#endif + void FileSelectHelper::RunFileChooserOnUIThread( - const FileChooserParams& params) { + const base::FilePath& default_file_path, + scoped_ptr<FileChooserParams> params) { + DCHECK(params); if (!render_view_host_ || !web_contents_ || !IsValidProfile(profile_)) { // If the renderer was destroyed before we started, just cancel the // operation. @@ -453,25 +496,13 @@ return; } - base::FilePath default_file_path = profile_->last_selected_directory().Append( - GetSanitizedFileName(params.default_file_name)); - -#if defined(FULL_SAFE_BROWSING) - if (params.mode == FileChooserParams::Save && - !params.default_file_name.empty() && - !safe_browsing::IsUnverifiedDownloadAllowed(default_file_path)) { - NotifyRenderViewHostAndEnd(std::vector<ui::SelectedFileInfo>()); - return; - } -#endif - select_file_dialog_ = ui::SelectFileDialog::Create( this, new ChromeSelectFilePolicy(web_contents_)); if (!select_file_dialog_.get()) return; - dialog_mode_ = params.mode; - switch (params.mode) { + dialog_mode_ = params->mode; + switch (params->mode) { case FileChooserParams::Open: dialog_type_ = ui::SelectFileDialog::SELECT_OPEN_FILE; break; @@ -496,11 +527,11 @@ #if defined(OS_ANDROID) // Android needs the original MIME types and an additional capture value. std::pair<std::vector<base::string16>, bool> accept_types = - std::make_pair(params.accept_types, params.capture); + std::make_pair(params->accept_types, params->capture); #endif select_file_dialog_->SelectFile( - dialog_type_, params.title, default_file_path, select_file_types_.get(), + dialog_type_, params->title, default_file_path, select_file_types_.get(), select_file_types_.get() && !select_file_types_->extensions.empty() ? 1 : 0, // 1-based index of default extension to show.
diff --git a/chrome/browser/file_select_helper.h b/chrome/browser/file_select_helper.h index f3f1266..3449a3d 100644 --- a/chrome/browser/file_select_helper.h +++ b/chrome/browser/file_select_helper.h
@@ -10,6 +10,7 @@ #include "base/compiler_specific.h" #include "base/gtest_prod_util.h" +#include "base/memory/scoped_ptr.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/web_contents_observer.h" @@ -17,6 +18,10 @@ #include "net/base/directory_lister.h" #include "ui/shell_dialogs/select_file_dialog.h" +#if defined(FULL_SAFE_BROWSING) +#include "chrome/browser/safe_browsing/unverified_download_policy.h" +#endif + class Profile; namespace content { @@ -78,11 +83,18 @@ void RunFileChooser(content::RenderViewHost* render_view_host, content::WebContents* web_contents, - const content::FileChooserParams& params); - void RunFileChooserOnFileThread( - const content::FileChooserParams& params); - void RunFileChooserOnUIThread( - const content::FileChooserParams& params); + scoped_ptr<content::FileChooserParams> params); + void GetFileTypesOnFileThread(scoped_ptr<content::FileChooserParams> params); + void GetSanitizedFilenameOnUIThread( + scoped_ptr<content::FileChooserParams> params); +#if defined(FULL_SAFE_BROWSING) + void ApplyUnverifiedDownloadPolicy( + const base::FilePath& default_path, + scoped_ptr<content::FileChooserParams> params, + safe_browsing::UnverifiedDownloadPolicy policy); +#endif + void RunFileChooserOnUIThread(const base::FilePath& default_path, + scoped_ptr<content::FileChooserParams> params); // Cleans up and releases this instance. This must be called after the last // callback is received from the file chooser dialog.
diff --git a/chrome/browser/first_run/first_run_internal_posix.cc b/chrome/browser/first_run/first_run_internal_posix.cc index 6fb649f..eec6d162 100644 --- a/chrome/browser/first_run/first_run_internal_posix.cc +++ b/chrome/browser/first_run/first_run_internal_posix.cc
@@ -16,7 +16,7 @@ #include "chrome/installer/util/google_update_settings.h" #include "chrome/installer/util/master_preferences.h" #include "components/metrics/metrics_pref_names.h" -#include "components/startup_metric_utils/startup_metric_utils.h" +#include "components/startup_metric_utils/browser/startup_metric_utils.h" namespace first_run { namespace internal {
diff --git a/chrome/browser/geolocation/geolocation_permission_context.cc b/chrome/browser/geolocation/geolocation_permission_context.cc index df90856..bb29c88 100644 --- a/chrome/browser/geolocation/geolocation_permission_context.cc +++ b/chrome/browser/geolocation/geolocation_permission_context.cc
@@ -23,24 +23,25 @@ GeolocationPermissionContext::~GeolocationPermissionContext() { } -void GeolocationPermissionContext::RequestPermission( +void GeolocationPermissionContext::DecidePermission( content::WebContents* web_contents, const PermissionRequestID& id, - const GURL& requesting_frame_origin, + const GURL& requesting_origin, + const GURL& embedding_origin, bool user_gesture, const BrowserPermissionCallback& callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); bool permission_set; bool new_permission; - if (extensions_context_.RequestPermission( - web_contents, id, id.request_id(), requesting_frame_origin, user_gesture, + if (extensions_context_.DecidePermission( + web_contents, id, id.request_id(), requesting_origin, user_gesture, callback, &permission_set, &new_permission)) { if (permission_set) { ContentSetting content_setting = new_permission ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; NotifyPermissionSet(id, - requesting_frame_origin, + requesting_origin, web_contents->GetLastCommittedURL().GetOrigin(), callback, false /* persist */, @@ -49,10 +50,12 @@ return; } - PermissionContextBase::RequestPermission(web_contents, id, - requesting_frame_origin, - user_gesture, - callback); + PermissionContextBase::DecidePermission(web_contents, + id, + requesting_origin, + embedding_origin, + user_gesture, + callback); } void GeolocationPermissionContext::CancelPermissionRequest(
diff --git a/chrome/browser/geolocation/geolocation_permission_context.h b/chrome/browser/geolocation/geolocation_permission_context.h index 2463b1b5..a9e99ed 100644 --- a/chrome/browser/geolocation/geolocation_permission_context.h +++ b/chrome/browser/geolocation/geolocation_permission_context.h
@@ -21,14 +21,15 @@ explicit GeolocationPermissionContext(Profile* profile); ~GeolocationPermissionContext() override; - // In addition to the base class flow the geolocation permission request + // In addition to the base class flow the geolocation permission decision // checks that it is only code from valid iframes. // It also adds special logic when called through an extension. - void RequestPermission(content::WebContents* web_contents, - const PermissionRequestID& id, - const GURL& requesting_frame_origin, - bool user_gesture, - const BrowserPermissionCallback& callback) override; + void DecidePermission(content::WebContents* web_contents, + const PermissionRequestID& id, + const GURL& requesting_origin, + const GURL& embedding_origin, + bool user_gesture, + const BrowserPermissionCallback& callback) override; // Adds special logic when called through an extension. void CancelPermissionRequest(content::WebContents* web_contents,
diff --git a/chrome/browser/geolocation/geolocation_permission_context_extensions.cc b/chrome/browser/geolocation/geolocation_permission_context_extensions.cc index 8208a97..e172eba 100644 --- a/chrome/browser/geolocation/geolocation_permission_context_extensions.cc +++ b/chrome/browser/geolocation/geolocation_permission_context_extensions.cc
@@ -41,7 +41,7 @@ ~GeolocationPermissionContextExtensions() { } -bool GeolocationPermissionContextExtensions::RequestPermission( +bool GeolocationPermissionContextExtensions::DecidePermission( content::WebContents* web_contents, const PermissionRequestID& request_id, int bridge_id,
diff --git a/chrome/browser/geolocation/geolocation_permission_context_extensions.h b/chrome/browser/geolocation/geolocation_permission_context_extensions.h index a7bcaf9..b978717 100644 --- a/chrome/browser/geolocation/geolocation_permission_context_extensions.h +++ b/chrome/browser/geolocation/geolocation_permission_context_extensions.h
@@ -26,14 +26,14 @@ // Returns true if the permission request was handled. In which case, // |permission_set| will be set to true if the permission changed, and the // permission has been set to |new_permission|. - bool RequestPermission(content::WebContents* web_contents, - const PermissionRequestID& request_id, - int bridge_id, - const GURL& requesting_frame, - bool user_gesture, - const base::Callback<void(ContentSetting)>& callback, - bool* permission_set, - bool* new_permission); + bool DecidePermission(content::WebContents* web_contents, + const PermissionRequestID& request_id, + int bridge_id, + const GURL& requesting_frame, + bool user_gesture, + const base::Callback<void(ContentSetting)>& callback, + bool* permission_set, + bool* new_permission); // Returns true if the cancellation request was handled. bool CancelPermissionRequest(content::WebContents* web_contents,
diff --git a/chrome/browser/invalidation/profile_invalidation_provider_factory.cc b/chrome/browser/invalidation/profile_invalidation_provider_factory.cc index e41c7e0..80db3031 100644 --- a/chrome/browser/invalidation/profile_invalidation_provider_factory.cc +++ b/chrome/browser/invalidation/profile_invalidation_provider_factory.cc
@@ -8,12 +8,12 @@ #include "base/prefs/pref_registry.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/services/gcm/gcm_profile_service.h" #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" #include "chrome/common/chrome_content_client.h" +#include "components/gcm_driver/gcm_profile_service.h" #include "components/invalidation/impl/invalidation_prefs.h" #include "components/invalidation/impl/invalidation_state_tracker.h" #include "components/invalidation/impl/invalidator_storage.h"
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index e13d23c9..e4d8c77 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc
@@ -621,7 +621,10 @@ #if defined(OS_ANDROID) external_data_use_observer_.reset( - new chrome::android::ExternalDataUseObserver(data_use_aggregator())); + new chrome::android::ExternalDataUseObserver( + data_use_aggregator(), + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI))); #endif // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466432
diff --git a/chrome/browser/local_discovery/wifi/DEPS b/chrome/browser/local_discovery/wifi/DEPS deleted file mode 100644 index a7f1c25..0000000 --- a/chrome/browser/local_discovery/wifi/DEPS +++ /dev/null
@@ -1,4 +0,0 @@ -include_rules = [ - "+components/onc", - "+components/wifi" -] \ No newline at end of file
diff --git a/chrome/browser/local_discovery/wifi/credential_getter_win.cc b/chrome/browser/local_discovery/wifi/credential_getter_win.cc deleted file mode 100644 index 2730fca..0000000 --- a/chrome/browser/local_discovery/wifi/credential_getter_win.cc +++ /dev/null
@@ -1,74 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/local_discovery/wifi/credential_getter_win.h" - -#include "base/thread_task_runner_handle.h" -#include "chrome/common/extensions/chrome_utility_extensions_messages.h" -#include "chrome/grit/generated_resources.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/utility_process_host.h" -#include "ui/base/l10n/l10n_util.h" - -namespace local_discovery { - -namespace wifi { - -CredentialGetterWin::CredentialGetterWin() { -} - -void CredentialGetterWin::StartGetCredentials( - const std::string& network_guid, - const CredentialsCallback& callback) { - callback_ = callback; - callback_runner_ = base::ThreadTaskRunnerHandle::Get(); - content::BrowserThread::PostTask( - content::BrowserThread::IO, - FROM_HERE, - base::Bind(&CredentialGetterWin::StartOnIOThread, this, network_guid)); -} - -void CredentialGetterWin::StartOnIOThread(const std::string& network_guid) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - content::UtilityProcessHost* host = content::UtilityProcessHost::Create( - this, base::ThreadTaskRunnerHandle::Get()); - host->SetName(l10n_util::GetStringUTF16( - IDS_UTILITY_PROCESS_WIFI_CREDENTIALS_GETTER_NAME)); - host->ElevatePrivileges(); - host->Send(new ChromeUtilityHostMsg_GetWiFiCredentials(network_guid)); -} - -CredentialGetterWin::~CredentialGetterWin() { -} - -bool CredentialGetterWin::OnMessageReceived(const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(CredentialGetterWin, message) - IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GotWiFiCredentials, OnGotCredentials) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - -void CredentialGetterWin::OnProcessCrashed(int exit_code) { - PostCallback(false, ""); -} - -void CredentialGetterWin::OnProcessLaunchFailed() { - PostCallback(false, ""); -} - -void CredentialGetterWin::OnGotCredentials(const std::string& key_data, - bool success) { - PostCallback(success, key_data); -} - -void CredentialGetterWin::PostCallback(bool success, - const std::string& key_data) { - callback_runner_->PostTask(FROM_HERE, - base::Bind(callback_, success, key_data)); -} - -} // namespace wifi -} // namespace local_discovery
diff --git a/chrome/browser/local_discovery/wifi/credential_getter_win.h b/chrome/browser/local_discovery/wifi/credential_getter_win.h deleted file mode 100644 index a0f2161..0000000 --- a/chrome/browser/local_discovery/wifi/credential_getter_win.h +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_CREDENTIAL_GETTER_WIN_H_ -#define CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_CREDENTIAL_GETTER_WIN_H_ - -#include <string> - -#include "base/single_thread_task_runner.h" -#include "content/public/browser/utility_process_host.h" -#include "content/public/browser/utility_process_host_client.h" - -namespace local_discovery { -namespace wifi { - -class CredentialGetterWin : public content::UtilityProcessHostClient { - public: - typedef base::Callback<void(bool success, const std::string& key)> - CredentialsCallback; - - CredentialGetterWin(); - - void StartGetCredentials(const std::string& network_guid, - const CredentialsCallback& callback); - - private: - ~CredentialGetterWin() override; - - // UtilityProcessHostClient - bool OnMessageReceived(const IPC::Message& message) override; - void OnProcessCrashed(int exit_code) override; - void OnProcessLaunchFailed() override; - - // IPC message handlers. - void OnGotCredentials(const std::string& key_data, bool success); - - void StartOnIOThread(const std::string& network_guid); - - void PostCallback(bool success, const std::string& key_data); - - CredentialsCallback callback_; - scoped_refptr<base::SingleThreadTaskRunner> callback_runner_; -}; - -} // namespace wifi -} // namespace local_discovery - -#endif // CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_CREDENTIAL_GETTER_WIN_H_
diff --git a/chrome/browser/local_discovery/wifi/mock_wifi_manager.cc b/chrome/browser/local_discovery/wifi/mock_wifi_manager.cc deleted file mode 100644 index 56aace6..0000000 --- a/chrome/browser/local_discovery/wifi/mock_wifi_manager.cc +++ /dev/null
@@ -1,99 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/local_discovery/wifi/mock_wifi_manager.h" - -namespace local_discovery { - -namespace wifi { - -MockWifiManager::MockWifiManager() : weak_factory_(this) { -} - -MockWifiManager::~MockWifiManager() { -} - -void MockWifiManager::GetSSIDList(const SSIDListCallback& callback) { - ssid_list_callback_ = callback; - GetSSIDListInternal(); -} - -void MockWifiManager::CallSSIDListCallback( - const std::vector<NetworkProperties>& networks) { - ssid_list_callback_.Run(networks); -} - -void MockWifiManager::ConfigureAndConnectNetwork( - const std::string& ssid, - const WifiCredentials& credentials, - const SuccessCallback& callback) { - configure_and_connect_network_callback_ = callback; - ConfigureAndConnectNetworkInternal(ssid, credentials.psk); -} - -void MockWifiManager::CallConfigureAndConnectNetworkCallback(bool success) { - configure_and_connect_network_callback_.Run(success); -} - -void MockWifiManager::ConnectToNetworkByID(const std::string& internal_id, - const SuccessCallback& callback) { - connect_by_id_callback_ = callback; - ConnectToNetworkByIDInternal(internal_id); -} - -void MockWifiManager::CallConnectToNetworkByIDCallback(bool success) { - connect_by_id_callback_.Run(success); -} - -void MockWifiManager::RequestNetworkCredentials( - const std::string& internal_id, - const CredentialsCallback& callback) { - credentials_callback_ = callback; - RequestNetworkCredentialsInternal(internal_id); -} - -void MockWifiManager::CallRequestNetworkCredentialsCallback( - bool success, - const std::string& ssid, - const std::string& password) { - credentials_callback_.Run(success, ssid, password); -} - -void MockWifiManager::CallNetworkListObservers( - const std::vector<NetworkProperties>& ssids) { - FOR_EACH_OBSERVER( - NetworkListObserver, network_observers_, OnNetworkListChanged(ssids)); -} - -void MockWifiManager::AddNetworkListObserver(NetworkListObserver* observer) { - network_observers_.AddObserver(observer); -} - -void MockWifiManager::RemoveNetworkListObserver(NetworkListObserver* observer) { - network_observers_.RemoveObserver(observer); -} - -MockWifiManagerFactory::MockWifiManagerFactory() { - WifiManager::SetFactory(this); -} - -MockWifiManagerFactory::~MockWifiManagerFactory() { - WifiManager::SetFactory(NULL); -} - -scoped_ptr<WifiManager> MockWifiManagerFactory::CreateWifiManager() { - last_created_manager_ = new MockWifiManager(); - - WifiManagerCreated(); - - return scoped_ptr<WifiManager>(last_created_manager_); -} - -MockWifiManager* MockWifiManagerFactory::GetLastCreatedWifiManager() { - return last_created_manager_; -} - -} // namespace wifi - -} // namespace local_discovery
diff --git a/chrome/browser/local_discovery/wifi/mock_wifi_manager.h b/chrome/browser/local_discovery/wifi/mock_wifi_manager.h deleted file mode 100644 index 820f771..0000000 --- a/chrome/browser/local_discovery/wifi/mock_wifi_manager.h +++ /dev/null
@@ -1,95 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_MOCK_WIFI_MANAGER_H_ -#define CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_MOCK_WIFI_MANAGER_H_ - -#include "base/observer_list.h" -#include "chrome/browser/local_discovery/wifi/wifi_manager.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace local_discovery { - -namespace wifi { - -class MockWifiManager : public WifiManager { - public: - MockWifiManager(); - ~MockWifiManager() override; - - MOCK_METHOD0(Start, void()); - - void GetSSIDList(const SSIDListCallback& callback) override; - - MOCK_METHOD0(GetSSIDListInternal, void()); - - void CallSSIDListCallback(const std::vector<NetworkProperties>& networks); - - MOCK_METHOD0(RequestScan, void()); - - void ConfigureAndConnectNetwork( - const std::string& ssid, - const WifiCredentials& credentials, - const SuccessCallback& callback) override; - - MOCK_METHOD2(ConfigureAndConnectNetworkInternal, - void(const std::string& ssid, const std::string& password)); - - void CallConfigureAndConnectNetworkCallback(bool success); - - void ConnectToNetworkByID(const std::string& internal_id, - const SuccessCallback& callback) override; - - MOCK_METHOD1(ConnectToNetworkByIDInternal, - void(const std::string& internal_id)); - - void CallConnectToNetworkByIDCallback(bool success); - - void RequestNetworkCredentials( - const std::string& internal_id, - const CredentialsCallback& callback) override; - - MOCK_METHOD1(RequestNetworkCredentialsInternal, - void(const std::string& internal_id)); - - void CallRequestNetworkCredentialsCallback(bool success, - const std::string& ssid, - const std::string& password); - - void AddNetworkListObserver(NetworkListObserver* observer); - - void RemoveNetworkListObserver(NetworkListObserver* observer); - - void CallNetworkListObservers(const std::vector<NetworkProperties>& ssids); - - private: - SSIDListCallback ssid_list_callback_; - SuccessCallback configure_and_connect_network_callback_; - SuccessCallback connect_by_id_callback_; - CredentialsCallback credentials_callback_; - base::ObserverList<NetworkListObserver> network_observers_; - - base::WeakPtrFactory<MockWifiManager> weak_factory_; -}; - -class MockWifiManagerFactory : public WifiManagerFactory { - public: - MockWifiManagerFactory(); - ~MockWifiManagerFactory() override; - - scoped_ptr<WifiManager> CreateWifiManager() override; - - MockWifiManager* GetLastCreatedWifiManager(); - - MOCK_METHOD0(WifiManagerCreated, void()); - - private: - MockWifiManager* last_created_manager_; -}; - -} // namespace wifi - -} // namespace local_discovery - -#endif // CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_MOCK_WIFI_MANAGER_H_
diff --git a/chrome/browser/local_discovery/wifi/wifi_manager.cc b/chrome/browser/local_discovery/wifi/wifi_manager.cc deleted file mode 100644 index c59c0be..0000000 --- a/chrome/browser/local_discovery/wifi/wifi_manager.cc +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/local_discovery/wifi/wifi_manager.h" - -namespace local_discovery { - -namespace wifi { - -namespace { - -WifiManagerFactory* g_factory = NULL; - -} // namespace - -scoped_ptr<WifiManager> WifiManager::Create() { - if (g_factory) { - return g_factory->CreateWifiManager(); - } - - return CreateDefault(); -} - -void WifiManager::SetFactory(WifiManagerFactory* factory) { - g_factory = factory; -} - -WifiCredentials WifiCredentials::FromPSK(const std::string& psk) { - WifiCredentials return_value; - return_value.psk = psk; - return return_value; -} - -} // namespace wifi - -} // namespace local_discovery
diff --git a/chrome/browser/local_discovery/wifi/wifi_manager.h b/chrome/browser/local_discovery/wifi/wifi_manager.h deleted file mode 100644 index e39c9fa..0000000 --- a/chrome/browser/local_discovery/wifi/wifi_manager.h +++ /dev/null
@@ -1,114 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_WIFI_MANAGER_H_ -#define CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_WIFI_MANAGER_H_ - -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "components/wifi/network_properties.h" - -namespace local_discovery { - -namespace wifi { - -// Convenience definition for users of this header, since ::wifi and -// local_discovery::wifi may conflict. -using ::wifi::NetworkProperties; - -typedef std::vector<NetworkProperties> NetworkPropertiesList; - -// Credentials for WiFi networks. Currently only supports PSK-based networks. -// TODO(noamsml): Support for 802.11X and other authentication methods. -struct WifiCredentials { - static WifiCredentials FromPSK(const std::string& psk); - - std::string psk; -}; - -class WifiManagerFactory; - -// Observer for the network list. Classes may implement this interface and call -// |AddNetworkListObserver| to be notified of changes to the visible network -// list. -class NetworkListObserver { - public: - virtual ~NetworkListObserver() {} - - virtual void OnNetworkListChanged(const NetworkPropertiesList& ssid) = 0; -}; - -// A class to manage listing, connecting to, and getting the credentials of WiFi -// networks. -class WifiManager { - public: - typedef base::Callback<void(const NetworkPropertiesList& ssids)> - SSIDListCallback; - typedef base::Callback<void(bool success)> SuccessCallback; - typedef base::Callback< - void(bool success, const std::string& ssid, const std::string& password)> - CredentialsCallback; - - virtual ~WifiManager() {} - - static scoped_ptr<WifiManager> Create(); - - static void SetFactory(WifiManagerFactory* factory); - - // Start the wifi manager. This must be called before any other method calls. - virtual void Start() = 0; - - // Get the list of visible SSIDs in the vicinity. This does not initiate a - // scan, but merely gets the list of networks from the system. - virtual void GetSSIDList(const SSIDListCallback& callback) = 0; - - // Request a scan for networks nearby. - virtual void RequestScan() = 0; - - // Configure and connect to a network with a given SSID and - // credentials. |callback| will be called once the network is connected or - // after it has failed to connect. - virtual void ConfigureAndConnectNetwork(const std::string& ssid, - const WifiCredentials& credentials, - const SuccessCallback& callback) = 0; - - // Connect to a configured network with a given network ID. |callback| will be - // called once the network is connected or after it has failed to connect. - virtual void ConnectToNetworkByID(const std::string& ssid, - const SuccessCallback& callback) = 0; - - // Reequest the credentials for a network with a given network ID from the - // system. |callback| will be called with credentials if they can be - // retrieved. Depending on platform, this may bring up a confirmation dialog - // or password prompt. - virtual void RequestNetworkCredentials( - const std::string& internal_id, - const CredentialsCallback& callback) = 0; - - // Add a network list observer. This observer will be notified every time the - // network list changes. - virtual void AddNetworkListObserver(NetworkListObserver* observer) = 0; - - // Remove a network list observer. - virtual void RemoveNetworkListObserver(NetworkListObserver* observer) = 0; - - private: - static scoped_ptr<WifiManager> CreateDefault(); -}; - -class WifiManagerFactory { - public: - virtual ~WifiManagerFactory() {} - - virtual scoped_ptr<WifiManager> CreateWifiManager() = 0; -}; - -} // namespace wifi - -} // namespace local_discovery - -#endif // CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_WIFI_MANAGER_H_
diff --git a/chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.cc b/chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.cc deleted file mode 100644 index 531c9247..0000000 --- a/chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.cc +++ /dev/null
@@ -1,572 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.h" - -#include "base/cancelable_callback.h" -#include "base/thread_task_runner_handle.h" -#include "base/threading/sequenced_worker_pool.h" -#include "base/threading/thread.h" -#include "components/onc/onc_constants.h" -#include "components/wifi/wifi_service.h" -#include "content/public/browser/browser_thread.h" -#include "net/base/network_change_notifier.h" - -#if defined(OS_WIN) -#include "chrome/browser/local_discovery/wifi/credential_getter_win.h" -#endif // OS_WIN - -using ::wifi::WiFiService; - -namespace local_discovery { - -namespace wifi { - -namespace { - -const int kConnectionTimeoutSeconds = 10; - -scoped_ptr<base::DictionaryValue> MakeProperties(const std::string& ssid, - const std::string& password) { - scoped_ptr<base::DictionaryValue> properties(new base::DictionaryValue); - - properties->SetString(onc::network_config::kType, onc::network_type::kWiFi); - base::DictionaryValue* wifi = new base::DictionaryValue; - properties->Set(onc::network_config::kWiFi, wifi); - - wifi->SetString(onc::wifi::kSSID, ssid); - if (!password.empty()) { - wifi->SetString(onc::wifi::kPassphrase, password); - // TODO(noamsml): Allow choosing security mechanism in a more fine-grained - // manner. - wifi->SetString(onc::wifi::kSecurity, onc::wifi::kWPA2_PSK); - } else { - wifi->SetString(onc::wifi::kSecurity, onc::wifi::kSecurityNone); - } - - return properties.Pass(); -} - -} // namespace - -class WifiManagerNonChromeos::WifiServiceWrapper - : public net::NetworkChangeNotifier::NetworkChangeObserver { - public: - explicit WifiServiceWrapper( - base::WeakPtr<WifiManagerNonChromeos> wifi_manager); - - ~WifiServiceWrapper() override; - - void Start(); - - void GetSSIDList(const WifiManager::SSIDListCallback& callback); - - void ConfigureAndConnectPskNetwork( - const std::string& ssid, - const std::string& password, - const WifiManager::SuccessCallback& callback); - - base::WeakPtr<WifiManagerNonChromeos::WifiServiceWrapper> AsWeakPtr(); - - void RequestScan(); - - void ConnectToNetworkByID(const std::string& network_guid, - const WifiManager::SuccessCallback& callback); - - void RequestNetworkCredentials( - const std::string& ssid, - const WifiManager::CredentialsCallback& callback); - - private: - // net::NetworkChangeNotifier::NetworkChangeObserver implementation. - void OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) override; - - void GetSSIDListInternal(NetworkPropertiesList* ssid_list); - - void OnNetworkListChangedEvent(const std::vector<std::string>& network_guids); - - void OnNetworksChangedEvent(const std::vector<std::string>& network_guids); - - std::string GetConnectedGUID(); - - bool IsConnected(const std::string& network_guid); - - void OnConnectToNetworkTimeout(); - - void PostClosure(const base::Closure& closure); - - bool FindAndConfigureNetwork(const std::string& ssid, - const std::string& password, - std::string* network_guid); - -#if defined(OS_WIN) - void PostCredentialsCallback(const WifiManager::CredentialsCallback& callback, - const std::string& ssid, - bool success, - const std::string& password); -#endif // OS_WIN - - scoped_ptr<WiFiService> wifi_service_; - - base::WeakPtr<WifiManagerNonChromeos> wifi_manager_; - - WifiManager::SuccessCallback connect_success_callback_; - base::CancelableClosure connect_failure_callback_; - - // SSID of previously connected network. - std::string connected_network_guid_; - - // SSID of network we are connecting to. - std::string connecting_network_guid_; - - scoped_refptr<base::SingleThreadTaskRunner> callback_runner_; - -#if defined(OS_WIN) - scoped_refptr<CredentialGetterWin> credential_getter_; -#endif // OS_WIN - - base::WeakPtrFactory<WifiServiceWrapper> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(WifiServiceWrapper); -}; - -WifiManagerNonChromeos::WifiServiceWrapper::WifiServiceWrapper( - base::WeakPtr<WifiManagerNonChromeos> wifi_manager) - : wifi_manager_(wifi_manager), - callback_runner_(base::ThreadTaskRunnerHandle::Get()), - weak_factory_(this) { -} - -WifiManagerNonChromeos::WifiServiceWrapper::~WifiServiceWrapper() { - net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); -} - -void WifiManagerNonChromeos::WifiServiceWrapper::Start() { - DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); - wifi_service_.reset(WiFiService::Create()); - - wifi_service_->Initialize(base::ThreadTaskRunnerHandle::Get()); - - wifi_service_->SetEventObservers( - base::ThreadTaskRunnerHandle::Get(), - base::Bind(&WifiServiceWrapper::OnNetworksChangedEvent, AsWeakPtr()), - base::Bind(&WifiServiceWrapper::OnNetworkListChangedEvent, AsWeakPtr())); - - net::NetworkChangeNotifier::AddNetworkChangeObserver(this); -} - -void WifiManagerNonChromeos::WifiServiceWrapper::GetSSIDList( - const WifiManager::SSIDListCallback& callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); - - scoped_ptr<NetworkPropertiesList> ssid_list(new NetworkPropertiesList); - GetSSIDListInternal(ssid_list.get()); - - callback_runner_->PostTask( - FROM_HERE, - base::Bind(&WifiManagerNonChromeos::PostSSIDListCallback, - wifi_manager_, - callback, - base::Passed(&ssid_list))); -} - -void WifiManagerNonChromeos::WifiServiceWrapper::ConfigureAndConnectPskNetwork( - const std::string& ssid, - const std::string& password, - const WifiManager::SuccessCallback& callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); - scoped_ptr<base::DictionaryValue> properties = MakeProperties(ssid, password); - - std::string network_guid; - std::string error_string; - // Will fail without changing system state if network already exists. - wifi_service_->CreateNetwork( - false, properties.Pass(), &network_guid, &error_string); - - if (error_string.empty()) { - ConnectToNetworkByID(network_guid, callback); - return; - } - - // If we cannot create the network, attempt to configure and connect to an - // existing network. - if (FindAndConfigureNetwork(ssid, password, &network_guid)) { - ConnectToNetworkByID(network_guid, callback); - } else { - if (!callback.is_null()) - PostClosure(base::Bind(callback, false /* success */)); - } -} - -void WifiManagerNonChromeos::WifiServiceWrapper::OnNetworkListChangedEvent( - const std::vector<std::string>& network_guids) { - DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); - scoped_ptr<NetworkPropertiesList> ssid_list(new NetworkPropertiesList); - GetSSIDListInternal(ssid_list.get()); - callback_runner_->PostTask( - FROM_HERE, - base::Bind(&WifiManagerNonChromeos::OnNetworkListChanged, - wifi_manager_, - base::Passed(&ssid_list))); -} - -void WifiManagerNonChromeos::WifiServiceWrapper::OnNetworksChangedEvent( - const std::vector<std::string>& network_guids) { - DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); - if (connecting_network_guid_.empty() || - !IsConnected(connecting_network_guid_)) { - return; - } - - connecting_network_guid_.clear(); - connect_failure_callback_.Cancel(); - - if (!connect_success_callback_.is_null()) - PostClosure(base::Bind(connect_success_callback_, true)); - - connect_success_callback_.Reset(); -} - -base::WeakPtr<WifiManagerNonChromeos::WifiServiceWrapper> -WifiManagerNonChromeos::WifiServiceWrapper::AsWeakPtr() { - return weak_factory_.GetWeakPtr(); -} - -void WifiManagerNonChromeos::WifiServiceWrapper::RequestScan() { - DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); - wifi_service_->RequestNetworkScan(); -} - -void WifiManagerNonChromeos::WifiServiceWrapper::ConnectToNetworkByID( - const std::string& network_guid, - const WifiManager::SuccessCallback& callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); - - std::string connected_network_id = GetConnectedGUID(); - std::string error_string; - wifi_service_->StartConnect(network_guid, &error_string); - - if (!error_string.empty()) { - LOG(ERROR) << "Could not connect to network by ID: " << error_string; - PostClosure(base::Bind(callback, false /* success */)); - wifi_service_->StartConnect(connected_network_id, &error_string); - return; - } - - if (IsConnected(network_guid)) { - if (!callback.is_null()) - PostClosure(base::Bind(callback, true /* success */)); - return; - } - - connect_success_callback_ = callback; - connecting_network_guid_ = network_guid; - connected_network_guid_ = connected_network_id; - - connect_failure_callback_.Reset(base::Bind( - &WifiServiceWrapper::OnConnectToNetworkTimeout, base::Unretained(this))); - - base::MessageLoop::current()->PostDelayedTask( - FROM_HERE, - connect_failure_callback_.callback(), - base::TimeDelta::FromSeconds(kConnectionTimeoutSeconds)); -} - -void WifiManagerNonChromeos::WifiServiceWrapper::OnConnectToNetworkTimeout() { - bool connected = IsConnected(connecting_network_guid_); - std::string error_string; - - WifiManager::SuccessCallback connect_success_callback = - connect_success_callback_; - - connect_success_callback_.Reset(); - - connecting_network_guid_.clear(); - - // If we did not connect, return to the network the user was originally - // connected to. - if (!connected) - wifi_service_->StartConnect(connected_network_guid_, &error_string); - - PostClosure(base::Bind(connect_success_callback, connected /* success */)); -} - -void WifiManagerNonChromeos::WifiServiceWrapper::RequestNetworkCredentials( - const std::string& ssid, - const WifiManager::CredentialsCallback& callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); - - bool success = true; - std::string guid; - std::string key; - - NetworkPropertiesList network_list; - - GetSSIDListInternal(&network_list); - - for (NetworkPropertiesList::iterator i = network_list.begin(); - i != network_list.end(); - i++) { - if (i->ssid == ssid) { - guid = i->guid; - break; - } - } - - if (guid.empty()) { - success = false; - } - - if (!success) { - PostClosure(base::Bind(callback, success, "", "")); - return; - } - -#if defined(OS_WIN) - credential_getter_ = new CredentialGetterWin(); - credential_getter_->StartGetCredentials( - guid, - base::Bind(&WifiServiceWrapper::PostCredentialsCallback, - AsWeakPtr(), - callback, - ssid)); -#else - if (success) { - std::string error_string; - wifi_service_->GetKeyFromSystem(guid, &key, &error_string); - - if (!error_string.empty()) { - LOG(ERROR) << "Could not get key from system: " << error_string; - success = false; - } - - PostClosure(base::Bind(callback, success, ssid, key)); - } -#endif // OS_WIN -} - -void WifiManagerNonChromeos::WifiServiceWrapper::OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) { - wifi_service_->RequestConnectedNetworkUpdate(); -} - -void WifiManagerNonChromeos::WifiServiceWrapper::GetSSIDListInternal( - NetworkPropertiesList* ssid_list) { - base::ListValue visible_networks; - - wifi_service_->GetVisibleNetworks( - onc::network_type::kWiFi, &visible_networks, true); - - for (size_t i = 0; i < visible_networks.GetSize(); i++) { - const base::DictionaryValue* network_value = NULL; - NetworkProperties network_properties; - - if (!visible_networks.GetDictionary(i, &network_value)) { - NOTREACHED(); - } - - network_properties.UpdateFromValue(*network_value); - - ssid_list->push_back(network_properties); - } -} - -std::string WifiManagerNonChromeos::WifiServiceWrapper::GetConnectedGUID() { - NetworkPropertiesList ssid_list; - GetSSIDListInternal(&ssid_list); - - for (NetworkPropertiesList::const_iterator it = ssid_list.begin(); - it != ssid_list.end(); - ++it) { - if (it->connection_state == onc::connection_state::kConnected) - return it->guid; - } - - return ""; -} - -bool WifiManagerNonChromeos::WifiServiceWrapper::IsConnected( - const std::string& network_guid) { - NetworkPropertiesList ssid_list; - GetSSIDListInternal(&ssid_list); - - for (NetworkPropertiesList::const_iterator it = ssid_list.begin(); - it != ssid_list.end(); - ++it) { - if (it->connection_state == onc::connection_state::kConnected && - it->guid == network_guid) - return true; - } - - return false; -} - -bool WifiManagerNonChromeos::WifiServiceWrapper::FindAndConfigureNetwork( - const std::string& ssid, - const std::string& password, - std::string* network_guid) { - std::string provisional_network_guid; - NetworkPropertiesList network_property_list; - GetSSIDListInternal(&network_property_list); - - for (size_t i = 0; i < network_property_list.size(); i++) { - // TODO(noamsml): Handle case where there are multiple networks with the - // same SSID but different security. - if (network_property_list[i].ssid == ssid) { - provisional_network_guid = network_property_list[i].guid; - break; - } - } - - if (provisional_network_guid.empty()) - return false; - - scoped_ptr<base::DictionaryValue> properties = MakeProperties(ssid, password); - - std::string error_string; - wifi_service_->SetProperties( - provisional_network_guid, properties.Pass(), &error_string); - - if (!error_string.empty()) { - LOG(ERROR) << "Could not set properties on network: " << error_string; - return false; - } - - *network_guid = provisional_network_guid; - return true; -} - -void WifiManagerNonChromeos::WifiServiceWrapper::PostClosure( - const base::Closure& closure) { - callback_runner_->PostTask( - FROM_HERE, - base::Bind(&WifiManagerNonChromeos::PostClosure, wifi_manager_, closure)); -} - -#if defined(OS_WIN) -void WifiManagerNonChromeos::WifiServiceWrapper::PostCredentialsCallback( - const WifiManager::CredentialsCallback& callback, - const std::string& ssid, - bool success, - const std::string& password) { - PostClosure(base::Bind(callback, success, ssid, password)); -} - -#endif // OS_WIN - -scoped_ptr<WifiManager> WifiManager::CreateDefault() { - return scoped_ptr<WifiManager>(new WifiManagerNonChromeos()); -} - -WifiManagerNonChromeos::WifiManagerNonChromeos() - : wifi_wrapper_(NULL), weak_factory_(this) { -} - -WifiManagerNonChromeos::~WifiManagerNonChromeos() { - if (wifi_wrapper_) { - content::BrowserThread::DeleteSoon( - content::BrowserThread::FILE, FROM_HERE, wifi_wrapper_); - } -} - -void WifiManagerNonChromeos::Start() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread( - content::BrowserThread::FILE); - - // Allocated on UI thread, but all initialization is done on file - // thread. Destroyed on file thread, which should be safe since all of the - // thread-unsafe members are created on the file thread. - wifi_wrapper_ = new WifiServiceWrapper(weak_factory_.GetWeakPtr()); - - task_runner_->PostTask( - FROM_HERE, - base::Bind(&WifiServiceWrapper::Start, wifi_wrapper_->AsWeakPtr())); -} - -void WifiManagerNonChromeos::GetSSIDList(const SSIDListCallback& callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - task_runner_->PostTask(FROM_HERE, - base::Bind(&WifiServiceWrapper::GetSSIDList, - wifi_wrapper_->AsWeakPtr(), - callback)); -} - -void WifiManagerNonChromeos::RequestScan() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - task_runner_->PostTask( - FROM_HERE, - base::Bind(&WifiServiceWrapper::RequestScan, wifi_wrapper_->AsWeakPtr())); -} - -void WifiManagerNonChromeos::OnNetworkListChanged( - scoped_ptr<NetworkPropertiesList> ssid_list) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - FOR_EACH_OBSERVER(NetworkListObserver, - network_list_observers_, - OnNetworkListChanged(*ssid_list)); -} - -void WifiManagerNonChromeos::PostClosure(const base::Closure& callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - callback.Run(); -} - -void WifiManagerNonChromeos::PostSSIDListCallback( - const SSIDListCallback& callback, - scoped_ptr<NetworkPropertiesList> ssid_list) { - callback.Run(*ssid_list); -} - -void WifiManagerNonChromeos::ConfigureAndConnectNetwork( - const std::string& ssid, - const WifiCredentials& credentials, - const SuccessCallback& callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - task_runner_->PostTask( - FROM_HERE, - base::Bind(&WifiServiceWrapper::ConfigureAndConnectPskNetwork, - wifi_wrapper_->AsWeakPtr(), - ssid, - credentials.psk, - callback)); -} - -void WifiManagerNonChromeos::ConnectToNetworkByID( - const std::string& internal_id, - const SuccessCallback& callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - task_runner_->PostTask(FROM_HERE, - base::Bind(&WifiServiceWrapper::ConnectToNetworkByID, - wifi_wrapper_->AsWeakPtr(), - internal_id, - callback)); -} - -void WifiManagerNonChromeos::RequestNetworkCredentials( - const std::string& ssid, - const CredentialsCallback& callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - task_runner_->PostTask( - FROM_HERE, - base::Bind(&WifiServiceWrapper::RequestNetworkCredentials, - wifi_wrapper_->AsWeakPtr(), - ssid, - callback)); -} - -void WifiManagerNonChromeos::AddNetworkListObserver( - NetworkListObserver* observer) { - network_list_observers_.AddObserver(observer); -} - -void WifiManagerNonChromeos::RemoveNetworkListObserver( - NetworkListObserver* observer) { - network_list_observers_.RemoveObserver(observer); -} - -} // namespace wifi - -} // namespace local_discovery
diff --git a/chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.h b/chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.h deleted file mode 100644 index e36fc0c..0000000 --- a/chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.h +++ /dev/null
@@ -1,70 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_WIFI_MANAGER_NONCHROMEOS_H_ -#define CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_WIFI_MANAGER_NONCHROMEOS_H_ - -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/observer_list.h" -#include "chrome/browser/local_discovery/wifi/wifi_manager.h" -#include "content/public/browser/browser_thread.h" - -namespace local_discovery { - -namespace wifi { - -class WifiManagerNonChromeos : public WifiManager { - public: - WifiManagerNonChromeos(); - ~WifiManagerNonChromeos() override; - - // WifiManager implementation. - void Start() override; - void GetSSIDList(const SSIDListCallback& callback) override; - void RequestScan() override; - void ConfigureAndConnectNetwork(const std::string& ssid, - const WifiCredentials& credentials, - const SuccessCallback& callback) override; - void ConnectToNetworkByID(const std::string& internal_id, - const SuccessCallback& callback) override; - void RequestNetworkCredentials(const std::string& ssid, - const CredentialsCallback& callback) override; - void AddNetworkListObserver(NetworkListObserver* observer) override; - void RemoveNetworkListObserver(NetworkListObserver* observer) override; - - private: - class WifiServiceWrapper; - - // Called when the network list changes. Used by WifiServiceWrapper. - void OnNetworkListChanged(scoped_ptr<NetworkPropertiesList> ssid_list); - - // Used to post callbacks that take a const& network list without copying the - // vector between threads. - void PostSSIDListCallback(const SSIDListCallback& callback, - scoped_ptr<NetworkPropertiesList> ssid_list); - - // Used to ensure closures posted from the wifi threads aren't called after - // the service client is deleted. - void PostClosure(const base::Closure& callback); - - std::string original_guid_; - scoped_refptr<base::SequencedTaskRunner> task_runner_; - WifiServiceWrapper* wifi_wrapper_; // Owned. Deleted on file thread. - base::ObserverList<NetworkListObserver> network_list_observers_; - - base::WeakPtrFactory<WifiManagerNonChromeos> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(WifiManagerNonChromeos); -}; - -} // namespace wifi - -} // namespace local_discovery - -#endif // CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_WIFI_MANAGER_NONCHROMEOS_H_
diff --git a/chrome/browser/mac/mac_startup_profiler.cc b/chrome/browser/mac/mac_startup_profiler.cc index 37d247b..95aa7d8d 100644 --- a/chrome/browser/mac/mac_startup_profiler.cc +++ b/chrome/browser/mac/mac_startup_profiler.cc
@@ -6,7 +6,7 @@ #include "base/logging.h" #include "base/metrics/histogram.h" -#include "components/startup_metric_utils/startup_metric_utils.h" +#include "components/startup_metric_utils/browser/startup_metric_utils.h" // static MacStartupProfiler* MacStartupProfiler::GetInstance() {
diff --git a/chrome/browser/media/cast_transport_host_filter.cc b/chrome/browser/media/cast_transport_host_filter.cc index cb3e42d..3f140734 100644 --- a/chrome/browser/media/cast_transport_host_filter.cc +++ b/chrome/browser/media/cast_transport_host_filter.cc
@@ -63,12 +63,11 @@ void CastTransportHostFilter::SendRawEvents( int32 channel_id, - const std::vector<media::cast::PacketEvent>& packet_events, - const std::vector<media::cast::FrameEvent>& frame_events) { - if (!packet_events.empty()) - Send(new CastMsg_RawEvents(channel_id, - packet_events, - frame_events)); + scoped_ptr<std::vector<media::cast::FrameEvent>> frame_events, + scoped_ptr<std::vector<media::cast::PacketEvent>> packet_events) { + if (frame_events->empty() && packet_events->empty()) + return; + Send(new CastMsg_RawEvents(channel_id, *packet_events, *frame_events)); } void CastTransportHostFilter::SendRtt(int32 channel_id,
diff --git a/chrome/browser/media/cast_transport_host_filter.h b/chrome/browser/media/cast_transport_host_filter.h index b30e08b..094d7e7f 100644 --- a/chrome/browser/media/cast_transport_host_filter.h +++ b/chrome/browser/media/cast_transport_host_filter.h
@@ -32,8 +32,8 @@ media::cast::CastTransportStatus result); void SendRawEvents( int32 channel_id, - const std::vector<media::cast::PacketEvent>& packet_events, - const std::vector<media::cast::FrameEvent>& frame_events); + scoped_ptr<std::vector<media::cast::FrameEvent>> frame_events, + scoped_ptr<std::vector<media::cast::PacketEvent>> packet_events); void SendRtt(int32 channel_id, uint32 ssrc, base::TimeDelta rtt); void SendCastMessage(int32 channel_id, uint32 ssrc,
diff --git a/chrome/browser/media/media_stream_devices_controller.cc b/chrome/browser/media/media_stream_devices_controller.cc index 34ff8336..d6a122eb 100644 --- a/chrome/browser/media/media_stream_devices_controller.cc +++ b/chrome/browser/media/media_stream_devices_controller.cc
@@ -6,6 +6,7 @@ #include "base/auto_reset.h" #include "base/callback_helpers.h" +#include "base/containers/scoped_ptr_map.h" #include "base/metrics/histogram.h" #include "base/prefs/scoped_user_pref_update.h" #include "base/strings/utf_string_conversions.h" @@ -25,6 +26,8 @@ #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/pref_registry/pref_registry_syncable.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/common/media_stream_request.h" #include "content/public/common/origin_util.h" @@ -69,6 +72,64 @@ return false; } +// This helper class helps to measure the number of media stream requests that +// occur. It ensures that only one request will be recorded per navigation, per +// frame. TODO(raymes): Remove this when https://crbug.com/526324 is fixed. +class MediaPermissionRequestLogger : content::WebContentsObserver { + // Map of <render process id, render frame id> -> + // MediaPermissionRequestLogger. + using RequestMap = + base::ScopedPtrMap<std::pair<int, int>, + scoped_ptr<MediaPermissionRequestLogger>>; + + public: + static void LogRequest(content::WebContents* contents, + int render_process_id, + int render_frame_id, + bool is_secure) { + RequestMap::key_type key = + std::make_pair(render_process_id, render_frame_id); + if (!ContainsKey(GetRequestMap(), key)) { + UMA_HISTOGRAM_BOOLEAN("Pepper.SecureOrigin.MediaStreamRequest", + is_secure); + GetRequestMap().set(key, make_scoped_ptr(new MediaPermissionRequestLogger( + contents, key))); + } + } + + private: + MediaPermissionRequestLogger(content::WebContents* contents, + RequestMap::key_type key) + : WebContentsObserver(contents), key_(key) {} + + void PageChanged(content::RenderFrameHost* render_frame_host) { + if (std::make_pair(render_frame_host->GetProcess()->GetID(), + render_frame_host->GetRoutingID()) == key_) { + GetRequestMap().erase(key_); + } + } + + static RequestMap& GetRequestMap() { + CR_DEFINE_STATIC_LOCAL(RequestMap, request_map, ()); + return request_map; + } + + // content::WebContentsObserver overrides + void DidNavigateAnyFrame( + content::RenderFrameHost* render_frame_host, + const content::LoadCommittedDetails& details, + const content::FrameNavigateParams& params) override { + PageChanged(render_frame_host); + } + + void RenderFrameDeleted( + content::RenderFrameHost* render_frame_host) override { + PageChanged(render_frame_host); + } + + RequestMap::key_type key_; +}; + } // namespace MediaStreamDevicesController::MediaStreamDevicesController( @@ -80,8 +141,9 @@ callback_(callback), persist_permission_changes_(true) { if (request_.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY) { - UMA_HISTOGRAM_BOOLEAN("Pepper.SecureOrigin.MediaStreamRequest", - content::IsOriginSecure(request_.security_origin)); + MediaPermissionRequestLogger::LogRequest( + web_contents, request.render_process_id, request.render_frame_id, + content::IsOriginSecure(request_.security_origin)); } profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext()); content_settings_ = TabSpecificContentSettings::FromWebContents(web_contents);
diff --git a/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc b/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc index f0fc27d..4801accc7 100644 --- a/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc +++ b/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc
@@ -11,41 +11,44 @@ #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" #include "chrome/browser/metrics/chromeos_metrics_provider.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_adapter_client.h" -#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" -#include "chromeos/dbus/fake_bluetooth_device_client.h" -#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h" -#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h" -#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h" -#include "chromeos/dbus/fake_bluetooth_input_client.h" #include "chromeos/dbus/power_manager_client.h" #include "chromeos/login/login_state.h" #include "components/metrics/proto/system_profile.pb.h" #include "components/user_manager/user_manager.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_utils.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_device_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_input_client.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(USE_X11) #include "ui/events/devices/x11/device_data_manager_x11.h" #endif +using bluez::BluetoothAdapterClient; +using bluez::BluetoothAgentManagerClient; +using bluez::BluetoothDeviceClient; +using bluez::BluetoothGattCharacteristicClient; +using bluez::BluetoothGattDescriptorClient; +using bluez::BluetoothGattServiceClient; +using bluez::BluetoothInputClient; +using bluez::BluezDBusManager; +using bluez::BluezDBusManagerSetter; +using bluez::FakeBluetoothAdapterClient; +using bluez::FakeBluetoothAgentManagerClient; +using bluez::FakeBluetoothDeviceClient; +using bluez::FakeBluetoothGattCharacteristicClient; +using bluez::FakeBluetoothGattDescriptorClient; +using bluez::FakeBluetoothGattServiceClient; +using bluez::FakeBluetoothInputClient; using chromeos::DBusThreadManager; using chromeos::DBusThreadManagerSetter; -using chromeos::BluetoothAdapterClient; -using chromeos::BluetoothAgentManagerClient; -using chromeos::BluetoothDeviceClient; -using chromeos::BluetoothGattCharacteristicClient; -using chromeos::BluetoothGattDescriptorClient; -using chromeos::BluetoothGattServiceClient; -using chromeos::BluetoothInputClient; -using chromeos::FakeBluetoothAdapterClient; -using chromeos::FakeBluetoothAgentManagerClient; -using chromeos::FakeBluetoothDeviceClient; -using chromeos::FakeBluetoothGattCharacteristicClient; -using chromeos::FakeBluetoothGattDescriptorClient; -using chromeos::FakeBluetoothGattServiceClient; -using chromeos::FakeBluetoothInputClient; using chromeos::PowerManagerClient; using chromeos::STUB_DBUS_CLIENT_IMPLEMENTATION; @@ -60,37 +63,39 @@ #endif // Set up the fake Bluetooth environment, - scoped_ptr<DBusThreadManagerSetter> dbus_setter = - DBusThreadManager::GetSetterForTesting(); - dbus_setter->SetBluetoothAdapterClient( + scoped_ptr<BluezDBusManagerSetter> bluez_dbus_setter = + BluezDBusManager::GetSetterForTesting(); + bluez_dbus_setter->SetBluetoothAdapterClient( scoped_ptr<BluetoothAdapterClient>(new FakeBluetoothAdapterClient)); - dbus_setter->SetBluetoothDeviceClient( + bluez_dbus_setter->SetBluetoothDeviceClient( scoped_ptr<BluetoothDeviceClient>(new FakeBluetoothDeviceClient)); - dbus_setter->SetBluetoothGattCharacteristicClient( + bluez_dbus_setter->SetBluetoothGattCharacteristicClient( scoped_ptr<BluetoothGattCharacteristicClient>( new FakeBluetoothGattCharacteristicClient)); - dbus_setter->SetBluetoothGattDescriptorClient( + bluez_dbus_setter->SetBluetoothGattDescriptorClient( scoped_ptr<BluetoothGattDescriptorClient>( new FakeBluetoothGattDescriptorClient)); - dbus_setter->SetBluetoothGattServiceClient( + bluez_dbus_setter->SetBluetoothGattServiceClient( scoped_ptr<BluetoothGattServiceClient>( new FakeBluetoothGattServiceClient)); - dbus_setter->SetBluetoothInputClient( + bluez_dbus_setter->SetBluetoothInputClient( scoped_ptr<BluetoothInputClient>(new FakeBluetoothInputClient)); - dbus_setter->SetBluetoothAgentManagerClient( + bluez_dbus_setter->SetBluetoothAgentManagerClient( scoped_ptr<BluetoothAgentManagerClient>( new FakeBluetoothAgentManagerClient)); // Set up a PowerManagerClient instance for PerfProvider. + scoped_ptr<DBusThreadManagerSetter> dbus_setter = + DBusThreadManager::GetSetterForTesting(); dbus_setter->SetPowerManagerClient( scoped_ptr<PowerManagerClient>( PowerManagerClient::Create(STUB_DBUS_CLIENT_IMPLEMENTATION))); // Grab pointers to members of the thread manager for easier testing. fake_bluetooth_adapter_client_ = static_cast<FakeBluetoothAdapterClient*>( - DBusThreadManager::Get()->GetBluetoothAdapterClient()); + BluezDBusManager::Get()->GetBluetoothAdapterClient()); fake_bluetooth_device_client_ = static_cast<FakeBluetoothDeviceClient*>( - DBusThreadManager::Get()->GetBluetoothDeviceClient()); + BluezDBusManager::Get()->GetBluetoothDeviceClient()); // Initialize the login state trackers. if (!chromeos::LoginState::IsInitialized())
diff --git a/chrome/browser/metrics/first_web_contents_profiler.cc b/chrome/browser/metrics/first_web_contents_profiler.cc index 1b3a6800..17662e9 100644 --- a/chrome/browser/metrics/first_web_contents_profiler.cc +++ b/chrome/browser/metrics/first_web_contents_profiler.cc
@@ -17,7 +17,7 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "components/metrics/profiler/tracking_synchronizer.h" #include "components/metrics/proto/profiler_event.pb.h" -#include "components/startup_metric_utils/startup_metric_utils.h" +#include "components/startup_metric_utils/browser/startup_metric_utils.h" #include "content/public/browser/navigation_handle.h" scoped_ptr<FirstWebContentsProfiler>
diff --git a/chrome/browser/password_manager/auto_signin_first_run_infobar_delegate.cc b/chrome/browser/password_manager/auto_signin_first_run_infobar_delegate.cc new file mode 100644 index 0000000..510da49 --- /dev/null +++ b/chrome/browser/password_manager/auto_signin_first_run_infobar_delegate.cc
@@ -0,0 +1,65 @@ +// Copyright 2015 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/password_manager/auto_signin_first_run_infobar_delegate.h" + +#include "chrome/browser/infobars/infobar_service.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/sync/profile_sync_service.h" +#include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/browser/ui/android/infobars/auto_signin_first_run_infobar.h" +#include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" +#include "chrome/grit/chromium_strings.h" +#include "chrome/grit/generated_resources.h" +#include "components/infobars/core/infobar.h" +#include "components/password_manager/core/browser/password_bubble_experiment.h" +#include "content/public/browser/web_contents.h" +#include "ui/base/l10n/l10n_util.h" + +// static +void AutoSigninFirstRunInfoBarDelegate::Create( + content::WebContents* web_contents, + const base::string16& message) { + Profile* profile = + Profile::FromBrowserContext(web_contents->GetBrowserContext()); + bool is_smartlock_branding_enabled = + password_bubble_experiment::IsSmartLockBrandingEnabled( + ProfileSyncServiceFactory::GetForProfile(profile)); + InfoBarService::FromWebContents(web_contents) + ->AddInfoBar(make_scoped_ptr(new AutoSigninFirstRunInfoBar( + make_scoped_ptr(new AutoSigninFirstRunInfoBarDelegate( + web_contents, is_smartlock_branding_enabled, message))))); +} + +AutoSigninFirstRunInfoBarDelegate::AutoSigninFirstRunInfoBarDelegate( + content::WebContents* web_contents, + bool is_smartlock_branding_enabled, + const base::string16& message) + : PasswordManagerInfoBarDelegate(), web_contents_(web_contents) { + gfx::Range explanation_link_range; + GetAutoSigninPromptFirstRunExperienceExplanation( + is_smartlock_branding_enabled, &explanation_, &explanation_link_range); + SetMessageLinkRange(explanation_link_range); + SetMessage(message); +} + +AutoSigninFirstRunInfoBarDelegate::~AutoSigninFirstRunInfoBarDelegate() { + Profile* profile = + Profile::FromBrowserContext(web_contents_->GetBrowserContext()); + password_bubble_experiment::RecordAutoSignInPromptFirstRunExperienceWasShown( + profile->GetPrefs()); +} + +base::string16 AutoSigninFirstRunInfoBarDelegate::GetButtonLabel( + InfoBarButton button) const { + return l10n_util::GetStringUTF16(IDS_ONE_CLICK_SIGNIN_DIALOG_OK_BUTTON); +} + +bool AutoSigninFirstRunInfoBarDelegate::Accept() { + return true; +} + +bool AutoSigninFirstRunInfoBarDelegate::Cancel() { + return true; +}
diff --git a/chrome/browser/password_manager/auto_signin_first_run_infobar_delegate.h b/chrome/browser/password_manager/auto_signin_first_run_infobar_delegate.h new file mode 100644 index 0000000..3355984 --- /dev/null +++ b/chrome/browser/password_manager/auto_signin_first_run_infobar_delegate.h
@@ -0,0 +1,45 @@ +// Copyright 2015 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_PASSWORD_MANAGER_AUTO_SIGNIN_FIRST_RUN_INFOBAR_DELEGATE_H_ +#define CHROME_BROWSER_PASSWORD_MANAGER_AUTO_SIGNIN_FIRST_RUN_INFOBAR_DELEGATE_H_ + +#include "base/macros.h" +#include "chrome/browser/password_manager/password_manager_infobar_delegate.h" + +namespace content { +class WebContents; +} + +// This delegate provides and acts on data for the android only auto sign-in +// first run experience infobar. +class AutoSigninFirstRunInfoBarDelegate + : public PasswordManagerInfoBarDelegate { + public: + static void Create(content::WebContents* web_contents, + const base::string16& message); + + ~AutoSigninFirstRunInfoBarDelegate() override; + + base::string16 GetButtonLabel(InfoBarButton button) const override; + bool Accept() override; + bool Cancel() override; + + base::string16 GetExplanation() { return explanation_; } + + protected: + // Makes a ctor available in tests. + AutoSigninFirstRunInfoBarDelegate(content::WebContents* web_contents, + bool is_smart_lock_branding_available, + const base::string16& message); + + private: + base::string16 explanation_; + + content::WebContents* web_contents_; + + DISALLOW_COPY_AND_ASSIGN(AutoSigninFirstRunInfoBarDelegate); +}; + +#endif // CHROME_BROWSER_PASSWORD_MANAGER_AUTO_SIGNIN_FIRST_RUN_INFOBAR_DELEGATE_H_
diff --git a/chrome/browser/password_manager/auto_signin_infobar_delegate_unittest.cc b/chrome/browser/password_manager/auto_signin_infobar_delegate_unittest.cc new file mode 100644 index 0000000..911c4aa --- /dev/null +++ b/chrome/browser/password_manager/auto_signin_infobar_delegate_unittest.cc
@@ -0,0 +1,79 @@ +// Copyright 2015 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 "base/prefs/pref_service.h" +#include "chrome/browser/password_manager/auto_signin_first_run_infobar_delegate.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "components/password_manager/core/common/password_manager_pref_names.h" +#include "content/public/browser/web_contents.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +class TestAutoSigninFirstRunInfoBarDelegate + : public AutoSigninFirstRunInfoBarDelegate { + public: + explicit TestAutoSigninFirstRunInfoBarDelegate( + content::WebContents* web_contents) + : AutoSigninFirstRunInfoBarDelegate( + web_contents, + true /* is_smartlock_branding_enabled */, + base::string16()) {} + + ~TestAutoSigninFirstRunInfoBarDelegate() override {} +}; + +} // namespace + +class AutoSigninFirstRunInfoBarDelegateTest + : public ChromeRenderViewHostTestHarness { + public: + AutoSigninFirstRunInfoBarDelegateTest() {} + ~AutoSigninFirstRunInfoBarDelegateTest() override {} + + PrefService* prefs(); + + protected: + scoped_ptr<ConfirmInfoBarDelegate> CreateDelegate(); + + private: + DISALLOW_COPY_AND_ASSIGN(AutoSigninFirstRunInfoBarDelegateTest); +}; + +scoped_ptr<ConfirmInfoBarDelegate> +AutoSigninFirstRunInfoBarDelegateTest::CreateDelegate() { + scoped_ptr<ConfirmInfoBarDelegate> delegate( + new TestAutoSigninFirstRunInfoBarDelegate(web_contents())); + return delegate.Pass(); +} + +PrefService* AutoSigninFirstRunInfoBarDelegateTest::prefs() { + Profile* profile = + Profile::FromBrowserContext(web_contents()->GetBrowserContext()); + return profile->GetPrefs(); +} + +TEST_F(AutoSigninFirstRunInfoBarDelegateTest, + CheckResetOfPrefAfterFirstRunMessageWasShownOnCancel) { + prefs()->SetBoolean( + password_manager::prefs::kWasAutoSignInFirstRunExperienceShown, false); + scoped_ptr<ConfirmInfoBarDelegate> infobar(CreateDelegate()); + EXPECT_TRUE(infobar->Cancel()); + infobar.reset(); + EXPECT_TRUE(prefs()->GetBoolean( + password_manager::prefs::kWasAutoSignInFirstRunExperienceShown)); +} + +TEST_F(AutoSigninFirstRunInfoBarDelegateTest, + CheckResetOfPrefAfterFirstRunMessageWasShownOnAccept) { + prefs()->SetBoolean( + password_manager::prefs::kWasAutoSignInFirstRunExperienceShown, false); + scoped_ptr<ConfirmInfoBarDelegate> infobar(CreateDelegate()); + EXPECT_TRUE(infobar->Accept()); + infobar.reset(); + EXPECT_TRUE(prefs()->GetBoolean( + password_manager::prefs::kWasAutoSignInFirstRunExperienceShown)); +}
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc index 03e8e098..f947d47 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -8,6 +8,7 @@ #include "base/bind_helpers.h" #include "base/command_line.h" #include "base/memory/singleton.h" +#include "base/metrics/field_trial.h" #include "base/metrics/histogram.h" #include "base/prefs/pref_service.h" #include "chrome/browser/browsing_data/browsing_data_helper.h" @@ -56,7 +57,7 @@ #if defined(OS_ANDROID) #include "chrome/browser/android/tab_android.h" #include "chrome/browser/password_manager/generated_password_saved_infobar_delegate_android.h" -#include "chrome/browser/ui/android/snackbars/auto_signin_snackbar_controller.h" +#include "chrome/browser/ui/android/snackbars/auto_signin_prompt_controller.h" #endif using password_manager::ContentPasswordManagerDriverFactory; @@ -262,8 +263,7 @@ ScopedVector<autofill::PasswordForm> local_forms) { DCHECK(!local_forms.empty()); #if defined(OS_ANDROID) - TabAndroid *tab = TabAndroid::FromWebContents(web_contents()); - ShowAutoSigninSnackbar(tab, local_forms[0]->username_value); + ShowAutoSigninPrompt(web_contents(), local_forms[0]->username_value); #else ManagePasswordsUIController::FromWebContents(web_contents())-> OnAutoSignin(local_forms.Pass());
diff --git a/chrome/browser/password_manager/password_manager_setting_migrator_service.cc b/chrome/browser/password_manager/password_manager_setting_migrator_service.cc deleted file mode 100644 index b8612b45..0000000 --- a/chrome/browser/password_manager/password_manager_setting_migrator_service.cc +++ /dev/null
@@ -1,234 +0,0 @@ -// Copyright (c) 2015 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/password_manager/password_manager_setting_migrator_service.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/metrics/histogram_macros.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" -#include "components/password_manager/core/browser/password_manager_settings_migration_experiment.h" -#include "components/password_manager/core/common/password_manager_pref_names.h" -#include "components/sync_driver/sync_service.h" -#include "components/syncable_prefs/pref_service_syncable.h" - -namespace { - -bool GetBooleanUserOrDefaultPrefValue(PrefService* prefs, - const std::string& name) { - bool result = false; - const base::Value* value = prefs->GetUserPrefValue(name); - if (!value) - value = prefs->GetDefaultPrefValue(name); - value->GetAsBoolean(&result); - return result; -} - -void ChangeOnePrefBecauseAnotherPrefHasChanged( - PrefService* prefs, - const std::string& other_pref_name, - const std::string& changed_pref_name) { - bool changed_pref = - GetBooleanUserOrDefaultPrefValue(prefs, changed_pref_name); - bool other_pref = GetBooleanUserOrDefaultPrefValue(prefs, other_pref_name); - if (changed_pref != other_pref) - prefs->SetBoolean(other_pref_name, changed_pref); -} - -// Change value of both kPasswordManagerSavingEnabled and -// kCredentialsEnableService to the |new_value|. -void UpdatePreferencesValues(PrefService* prefs, bool new_value) { - prefs->SetBoolean(password_manager::prefs::kPasswordManagerSavingEnabled, - new_value); - prefs->SetBoolean(password_manager::prefs::kCredentialsEnableService, - new_value); -} - -void SaveCurrentPrefState(PrefService* prefs, - bool* new_pref_value, - bool* legacy_pref_value) { - *new_pref_value = GetBooleanUserOrDefaultPrefValue( - prefs, password_manager::prefs::kCredentialsEnableService); - *legacy_pref_value = GetBooleanUserOrDefaultPrefValue( - prefs, password_manager::prefs::kPasswordManagerSavingEnabled); -} - -void TrackInitialAndFinalValues(PrefService* prefs, - bool initial_new_pref_value, - bool initial_legacy_pref_value) { - bool final_new_pref_value = - prefs->GetBoolean(password_manager::prefs::kCredentialsEnableService); - bool final_legacy_pref_value = - prefs->GetBoolean(password_manager::prefs::kPasswordManagerSavingEnabled); - const int kMaxInitValue = 0x10; - int value_to_log = 0; - const int kInitialNewValueMask = 0x8; - const int kInitialLegacyValueMask = 0x4; - const int kFinalNewValueMask = 0x2; - const int kFinalLegacyValueMask = 0x1; - if (initial_new_pref_value) - value_to_log |= kInitialNewValueMask; - if (initial_legacy_pref_value) - value_to_log |= kInitialLegacyValueMask; - if (final_new_pref_value) - value_to_log |= kFinalNewValueMask; - if (final_legacy_pref_value) - value_to_log |= kFinalLegacyValueMask; - UMA_HISTOGRAM_ENUMERATION( - "PasswordManager.SettingsReconciliation.InitialAndFinalValues", - value_to_log, kMaxInitValue); -} - -} // namespace - -namespace password_manager { - -PasswordManagerSettingMigratorService::PasswordManagerSettingMigratorService( - syncable_prefs::PrefServiceSyncable* prefs) - : prefs_(prefs), sync_service_(nullptr) { - SaveCurrentPrefState(prefs_, &initial_new_pref_value_, - &initial_legacy_pref_value_); -} - -PasswordManagerSettingMigratorService:: - ~PasswordManagerSettingMigratorService() {} - -void PasswordManagerSettingMigratorService::InitializeMigration( - sync_driver::SyncService* sync_service) { - SaveCurrentPrefState(prefs_, &initial_new_pref_value_, - &initial_legacy_pref_value_); - const int kMaxInitialValues = 4; - UMA_HISTOGRAM_ENUMERATION( - "PasswordManager.SettingsReconciliation.InitialValues", - (static_cast<int>(initial_new_pref_value_) << 1 | - static_cast<int>(initial_legacy_pref_value_)), - kMaxInitialValues); - if (!password_manager::IsSettingsMigrationActive()) { - return; - } - sync_service_ = sync_service; - if (!sync_service_ || !CanSyncStart()) { - MigrateOffState(prefs_); - TrackInitialAndFinalValues(prefs_, initial_new_pref_value_, - initial_legacy_pref_value_); - } - InitObservers(); -} - -void PasswordManagerSettingMigratorService::InitObservers() { - pref_change_registrar_.Init(prefs_); - pref_change_registrar_.Add( - password_manager::prefs::kCredentialsEnableService, - base::Bind(&PasswordManagerSettingMigratorService:: - OnCredentialsEnableServicePrefChanged, - base::Unretained(this))); - pref_change_registrar_.Add( - password_manager::prefs::kPasswordManagerSavingEnabled, - base::Bind(&PasswordManagerSettingMigratorService:: - OnPasswordManagerSavingEnabledPrefChanged, - base::Unretained(this))); - // This causes OnIsSyncingChanged to be called when the value of - // PrefService::IsSyncing() changes. - prefs_->AddObserver(this); -} - -bool PasswordManagerSettingMigratorService::CanSyncStart() { - return sync_service_ && sync_service_->CanSyncStart() && - syncer::UserSelectableTypes().Has(syncer::PREFERENCES); -} - -void PasswordManagerSettingMigratorService::Shutdown() { - prefs_->RemoveObserver(this); -} - -void PasswordManagerSettingMigratorService:: - OnCredentialsEnableServicePrefChanged( - const std::string& changed_pref_name) { - sync_data_.push_back(GetBooleanUserOrDefaultPrefValue( - prefs_, password_manager::prefs::kCredentialsEnableService)); - ChangeOnePrefBecauseAnotherPrefHasChanged( - prefs_, password_manager::prefs::kPasswordManagerSavingEnabled, - password_manager::prefs::kCredentialsEnableService); -} - -void PasswordManagerSettingMigratorService:: - OnPasswordManagerSavingEnabledPrefChanged( - const std::string& changed_pref_name) { - sync_data_.push_back(GetBooleanUserOrDefaultPrefValue( - prefs_, password_manager::prefs::kPasswordManagerSavingEnabled)); - ChangeOnePrefBecauseAnotherPrefHasChanged( - prefs_, password_manager::prefs::kCredentialsEnableService, - password_manager::prefs::kPasswordManagerSavingEnabled); -} - -void PasswordManagerSettingMigratorService::OnIsSyncingChanged() { - if (WasModelAssociationStepPerformed()) { - // Initial sync has finished. - MigrateAfterModelAssociation(prefs_); - } - - if (prefs_->IsSyncing() == prefs_->IsPrioritySyncing()) { - // Sync is not in model association step. - SaveCurrentPrefState(prefs_, &initial_new_pref_value_, - &initial_legacy_pref_value_); - sync_data_.clear(); - } -} - -bool PasswordManagerSettingMigratorService::WasModelAssociationStepPerformed() { -#if defined(OS_ANDROID) - return prefs_->IsPrioritySyncing(); -#else - return prefs_->IsSyncing() && prefs_->IsPrioritySyncing(); -#endif -} - -void PasswordManagerSettingMigratorService::MigrateOffState( - PrefService* prefs) { - bool new_pref_value = GetBooleanUserOrDefaultPrefValue( - prefs_, password_manager::prefs::kCredentialsEnableService); - bool legacy_pref_value = GetBooleanUserOrDefaultPrefValue( - prefs_, password_manager::prefs::kPasswordManagerSavingEnabled); - UpdatePreferencesValues(prefs, new_pref_value && legacy_pref_value); -} - -void PasswordManagerSettingMigratorService::MigrateAfterModelAssociation( - PrefService* prefs) { - if (sync_data_.empty()) { - MigrateOffState(prefs); - } else if (sync_data_.size() == 1) { -#if defined(OS_ANDROID) - if (initial_new_pref_value_ != initial_legacy_pref_value_) { - // Treat special case for mobile clients where only priority pref - // arrives on the client. - if (!initial_new_pref_value_ && initial_legacy_pref_value_) - UpdatePreferencesValues(prefs, true); - else - UpdatePreferencesValues(prefs, false); - } else { - UpdatePreferencesValues(prefs, sync_data_[0]); - } -#else - // Only one value came from sync. This value should be assigned to both - // preferences. - UpdatePreferencesValues(prefs, sync_data_[0]); -#endif - } else { - bool sync_new_pref_value = sync_data_[0]; - bool sync_legacy_pref_value = sync_data_.back(); - if (sync_legacy_pref_value && sync_new_pref_value) { - UpdatePreferencesValues(prefs, true); - } else if (!sync_legacy_pref_value && !sync_new_pref_value) { - UpdatePreferencesValues(prefs, false); - } else if (!initial_legacy_pref_value_ && !initial_new_pref_value_) { - UpdatePreferencesValues(prefs, true); - } else { - UpdatePreferencesValues(prefs, false); - } - } - TrackInitialAndFinalValues(prefs, initial_new_pref_value_, - initial_legacy_pref_value_); -} - -} // namespace password_manager
diff --git a/chrome/browser/password_manager/password_manager_setting_migrator_service.h b/chrome/browser/password_manager/password_manager_setting_migrator_service.h deleted file mode 100644 index ce389dee..0000000 --- a/chrome/browser/password_manager/password_manager_setting_migrator_service.h +++ /dev/null
@@ -1,154 +0,0 @@ -// Copyright (c) 2015 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_PASSWORD_MANAGER_PASSWORD_MANAGER_SETTING_MIGRATOR_SERVICE_H_ -#define CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_MANAGER_SETTING_MIGRATOR_SERVICE_H_ - -#include <vector> - -#include "base/memory/singleton.h" -#include "base/prefs/pref_change_registrar.h" -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" -#include "components/keyed_service/core/keyed_service.h" -#include "components/syncable_prefs/pref_service_syncable_observer.h" - -namespace sync_driver { -class SyncService; -} - -namespace syncable_prefs { -class PrefServiceSyncable; -} - -namespace password_manager { - -// Service that is responsible for reconciling the legacy "Offer to save your -// web passwords" setting (henceforth denoted 'L', for legacy) with the new -// "Enable Smart Lock for Passwords" setting (henceforth denoted 'N', for new). -// -// It works as follows. -// -// Users who are not syncing (this is checked on start-up of the service -// calling to SyncService:CanSyncStart()) are migrated on startup of the -// service. These users can be in following states: -// 1. N = 0, L = 0 -// 2. N = 1, L = 1 -// 3. N = 1, L = 0 -// 4. N = 0, L = 1 -// -// Nothing should be done in case 1 and 2 since settings are already in sync; -// in case 3,4 we change value of N to 0. -// -// For users who are syncing we save the values for the new and legacy -// preference on service startup (|inital_values_|) and the values that come -// from sync during models association step (|sync_data_|). Propagating change -// of one preference to another preference without having this special treatment -// will not always work. Here is an example which illustrates possible corner -// case: the client executes the migration code for the first time, legacy -// preference has a value 1, new preference was registered for the -// first time and has default value which is also 1, the sync data snapshot -// which user has on a client contains new preference equal to 0 and old -// preference equal to 1, if we blindly propagate these values we first get -// both preferences equal to 0 after priority pref model was associated and -// then both preferences equal to 1 after preferences model was associated. -// But the correct final value in this case is 0. -// -// At the end of model association step we derive the new values for both -// settings using the following table (first column contains local values for -// the preferences, first row contains values which came from sync, where _ -// means that the value did not come): -// -// NL* 0_ 1_ _0 _1 00 01 10 11 -// -// 00 00 11 00 11 00 11 11 11 -// 01 00* 11* x x 00 00 00 11 -// 10 00* 00* x x 00 00 00 11 -// 11 00 11 00 11 00 00 00 11 -// -// *these cases only possible on mobile platforms, where we sync only priority -// preference data type. -// -// The service observes changes to both preferences (e.g. changes from sync, -// changes from UI) and propagates the change to the other preference if needed. -// -// Note: componetization of this service currently is impossible, because it -// depends on PrefServiceSyncable https://crbug.com/522536. -class PasswordManagerSettingMigratorService - : public KeyedService, - public syncable_prefs::PrefServiceSyncableObserver { - public: - explicit PasswordManagerSettingMigratorService( - syncable_prefs::PrefServiceSyncable* prefs); - ~PasswordManagerSettingMigratorService() override; - - void Shutdown() override; - - // PrefServiceSyncableObserver: - void OnIsSyncingChanged() override; - - void InitializeMigration(sync_driver::SyncService* sync_service); - - private: - // Initializes the observers: preferences observers and sync status observers. - void InitObservers(); - - // Returns true if sync is expected to start for the user. - bool CanSyncStart(); - - // Called when the value of the |kCredentialsEnableService| preference - // changes, and updates the value of |kPasswordManagerSavingEnabled| - // preference accordingly. - void OnCredentialsEnableServicePrefChanged( - const std::string& changed_pref_name); - - // Called when the value of the |kPasswordManagerSavingEnabled| preference - // changes, and updates the value of |kCredentialsEnableService| preference - // accordingly. - void OnPasswordManagerSavingEnabledPrefChanged( - const std::string& changed_pref_name); - - // Determines if model association step was performed. For desktop platforms, - // the condition is that for both priority preferences and regular preferences - // types association step was finished. For mobile platforms, the association - // only for priority prefs is required. - bool WasModelAssociationStepPerformed(); - - // Turns off one pref if another pref is off. - void MigrateOffState(PrefService* prefs); - - // Performs a migration after sync associates models. Migration is performed - // based on initial values for both preferences and values received from - // sync. - void MigrateAfterModelAssociation(PrefService* prefs); - - // Contains values which have come from sync during model association step. - // The vector minimum size is 0 and the vector maximum size is 4: - // * sync_data_ has length equal to 0, when no change to the preferences has - // came from sync. - // * sync_data has length equal to 1, when change to only one preference - // came from sync and another pref already had this value, e.g local state - // 01 and N=1 came from sync. - // * sync_data has length equals to 4, changes to both preference has came - // from sync, e.g. local state is 11 and 01 came from sync. - // This way index 0 corresponds to kCredentialsEnableService, last index - // corresponds to kPasswordManagerSavingEnabled if size of sync_data_ equals - // to 4, otherwise the vector contains the value only for one preference. - std::vector<bool> sync_data_; - - // The initial value for kCredentialsEnableService. - bool initial_new_pref_value_; - // The initial value for kPasswordManagerSavingEnabled. - bool initial_legacy_pref_value_; - - syncable_prefs::PrefServiceSyncable* prefs_; - sync_driver::SyncService* sync_service_; - - PrefChangeRegistrar pref_change_registrar_; - - DISALLOW_COPY_AND_ASSIGN(PasswordManagerSettingMigratorService); -}; - -} // namespace password_manager - -#endif // CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_MANAGER_SETTING_MIGRATOR_SERVICE_H_
diff --git a/chrome/browser/password_manager/password_manager_setting_migrator_service_factory.cc b/chrome/browser/password_manager/password_manager_setting_migrator_service_factory.cc index 6cc99f8..ae8786a5 100644 --- a/chrome/browser/password_manager/password_manager_setting_migrator_service_factory.cc +++ b/chrome/browser/password_manager/password_manager_setting_migrator_service_factory.cc
@@ -4,12 +4,12 @@ #include "chrome/browser/password_manager/password_manager_setting_migrator_service_factory.h" -#include "chrome/browser/password_manager/password_manager_setting_migrator_service.h" #include "chrome/browser/prefs/pref_service_syncable_util.h" #include "chrome/browser/profiles/incognito_helpers.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "components/password_manager/sync/browser/password_manager_setting_migrator_service.h" // static PasswordManagerSettingMigratorServiceFactory*
diff --git a/chrome/browser/password_manager/password_manager_setting_migrator_service_unittest.cc b/chrome/browser/password_manager/password_manager_setting_migrator_service_unittest.cc deleted file mode 100644 index fb0786a..0000000 --- a/chrome/browser/password_manager/password_manager_setting_migrator_service_unittest.cc +++ /dev/null
@@ -1,469 +0,0 @@ -// Copyright (c) 2015 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 "base/json/json_writer.h" -#include "base/metrics/field_trial.h" -#include "base/prefs/pref_service.h" -#include "base/test/histogram_tester.h" -#include "base/values.h" -#include "chrome/browser/password_manager/password_manager_setting_migrator_service.h" -#include "components/password_manager/core/browser/password_manager.h" -#include "components/password_manager/core/common/password_manager_pref_names.h" -#include "components/pref_registry/testing_pref_service_syncable.h" -#include "components/sync_driver/fake_sync_service.h" -#include "components/syncable_prefs/pref_model_associator_client.h" -#include "components/syncable_prefs/pref_service_mock_factory.h" -#include "components/syncable_prefs/pref_service_syncable.h" -#include "sync/api/fake_sync_change_processor.h" -#include "sync/api/sync_error_factory.h" -#include "sync/api/sync_error_factory_mock.h" -#include "sync/internal_api/public/attachments/attachment_service_proxy_for_test.h" -#include "sync/protocol/sync.pb.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -const char kFieldTrialName[] = "PasswordManagerSettingsMigration"; -const char kEnabledGroupName[] = "Enable"; -const char kDisabledGroupName[] = "Disable"; - -const char kInitialValuesHistogramName[] = - "PasswordManager.SettingsReconciliation.InitialValues"; - -const char kInitialAndFinalValuesHistogramName[] = - "PasswordManager.SettingsReconciliation.InitialAndFinalValues"; - -enum BooleanPrefState { - OFF, - ON, - EMPTY, // datatype bucket is empty -}; - -// Enum used for histogram tracking of the initial values for the legacy and new -// preferences. -enum PasswordManagerPreferencesInitialValues { - N0L0, - N0L1, - N1L0, - N1L1, - NUM_INITIAL_VALUES, -}; - -// Enum used for histogram tracking of the combined initial values and final -// values for the legacy and new preferences. -enum PasswordManagerPreferencesInitialAndFinalValues { - I00F00, - I00F01, - I00F10, - I00F11, - I01F00, - I01F01, - I01F10, - I01F11, - I10F00, - I10F01, - I10F10, - I10F11, - I11F00, - I11F01, - I11F10, - I11F11, - NUM_INITIAL_AND_FINAL_VALUES, -}; - -syncer::SyncData CreatePrefSyncData(const std::string& name, bool value) { - base::FundamentalValue bool_value(value); - std::string serialized; - base::JSONWriter::Write(bool_value, &serialized); - sync_pb::EntitySpecifics specifics; - sync_pb::PreferenceSpecifics* pref = nullptr; - if (name == password_manager::prefs::kPasswordManagerSavingEnabled) - pref = specifics.mutable_preference(); - else if (name == password_manager::prefs::kCredentialsEnableService) - pref = specifics.mutable_priority_preference()->mutable_preference(); - else - NOTREACHED() << "Wrong preference name: " << name; - pref->set_name(name); - pref->set_value(serialized); - return syncer::SyncData::CreateRemoteData( - 1, specifics, base::Time(), syncer::AttachmentIdList(), - syncer::AttachmentServiceProxyForTest::Create()); -} - -// Emulates start of the syncing for the specific sync type. If |name| is -// kPasswordManagerSavingEnabled preference, then it's PREFERENCE data type. -// If |name| is kCredentialsEnableService pref, then it's PRIORITY_PREFERENCE -// data type. -void StartSyncingPref(syncable_prefs::PrefServiceSyncable* prefs, - const std::string& name, - BooleanPrefState pref_state_in_sync) { - syncer::SyncDataList sync_data_list; - if (pref_state_in_sync == EMPTY) { - sync_data_list = syncer::SyncDataList(); - } else { - sync_data_list.push_back( - CreatePrefSyncData(name, pref_state_in_sync == ON)); - } - - syncer::ModelType type = syncer::UNSPECIFIED; - if (name == password_manager::prefs::kPasswordManagerSavingEnabled) - type = syncer::PREFERENCES; - else if (name == password_manager::prefs::kCredentialsEnableService) - type = syncer::PRIORITY_PREFERENCES; - ASSERT_NE(syncer::UNSPECIFIED, type) << "Wrong preference name: " << name; - syncer::SyncableService* sync = prefs->GetSyncableService(type); - sync->MergeDataAndStartSyncing( - type, sync_data_list, scoped_ptr<syncer::SyncChangeProcessor>( - new syncer::FakeSyncChangeProcessor), - scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock)); -} - -class SyncServiceMock : public sync_driver::FakeSyncService { - public: - bool HasSyncSetupCompleted() const override { return true; } - - bool CanSyncStart() const override { return can_sync_start_; } - - void SetCanSyncStart(bool can_sync_start) { - can_sync_start_ = can_sync_start; - } - - private: - bool can_sync_start_ = true; -}; - -class TestPrefModelAssociatorClient - : public syncable_prefs::PrefModelAssociatorClient { - public: - TestPrefModelAssociatorClient() {} - ~TestPrefModelAssociatorClient() override {} - - // PrefModelAssociatorClient implementation. - bool IsMergeableListPreference(const std::string& pref_name) const override { - return false; - } - - bool IsMergeableDictionaryPreference( - const std::string& pref_name) const override { - return false; - } - - bool IsMigratedPreference(const std::string& new_pref_name, - std::string* old_pref_name) const override { - return false; - } - - bool IsOldMigratedPreference(const std::string& old_pref_name, - std::string* new_pref_name) const override { - return false; - } - - private: - DISALLOW_COPY_AND_ASSIGN(TestPrefModelAssociatorClient); -}; - -} // namespace - -namespace password_manager { - -class PasswordManagerSettingMigratorServiceTest : public testing::Test { - protected: - PasswordManagerSettingMigratorServiceTest() {} - ~PasswordManagerSettingMigratorServiceTest() override {} - - void SetUp() override { - SetupPreferenceMigrationEnvironment(); - EnforcePasswordManagerSettingMigrationExperiment(kEnabledGroupName); - } - - void SetupLocalPrefState(const std::string& name, BooleanPrefState state) { - if (state == ON) - prefs()->SetBoolean(name, true); - else if (state == OFF) - prefs()->SetBoolean(name, false); - else if (state == EMPTY) - ASSERT_TRUE(prefs()->FindPreference(name)->IsDefaultValue()); - } - - syncable_prefs::PrefServiceSyncable* prefs() { return pref_service_.get(); } - - void SetupPreferenceMigrationEnvironment() { - syncable_prefs::PrefServiceMockFactory factory; - factory.SetPrefModelAssociatorClient(&client_); - scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry( - new user_prefs::PrefRegistrySyncable); - password_manager::PasswordManager::RegisterProfilePrefs( - pref_registry.get()); - scoped_ptr<syncable_prefs::PrefServiceSyncable> pref_service_syncable = - factory.CreateSyncable(pref_registry.get()); - migration_service_.reset( - new PasswordManagerSettingMigratorService(pref_service_syncable.get())); - pref_service_.reset(pref_service_syncable.release()); - } - - void ExpectValuesForBothPrefValues(bool new_pref_value, bool old_pref_value) { - EXPECT_EQ(new_pref_value, - prefs()->GetBoolean(prefs::kCredentialsEnableService)); - EXPECT_EQ(old_pref_value, - prefs()->GetBoolean(prefs::kPasswordManagerSavingEnabled)); - } - - SyncServiceMock* profile_sync_service() { return &sync_service_; } - - void NotifyProfileAdded() { - migration_service_->InitializeMigration(&sync_service_); - } - - void EnforcePasswordManagerSettingMigrationExperiment(const char* name) { - // The existing instance of FieldTrialList should be deleted before creating - // new one, so reset() is called in order to do so. - field_trial_list_.reset(); - field_trial_list_.reset(new base::FieldTrialList(nullptr)); - base::FieldTrialList::CreateFieldTrial(kFieldTrialName, name); - } - - private: - scoped_ptr<base::FieldTrialList> field_trial_list_; - TestPrefModelAssociatorClient client_; - SyncServiceMock sync_service_; - scoped_ptr<syncable_prefs::PrefServiceSyncable> pref_service_; - scoped_ptr<PasswordManagerSettingMigratorService> migration_service_; - - DISALLOW_COPY_AND_ASSIGN(PasswordManagerSettingMigratorServiceTest); -}; - -TEST_F(PasswordManagerSettingMigratorServiceTest, TestMigrationOnLocalChanges) { - const struct { - const char* group; - const char* pref_name; - bool pref_value; - bool expected_new_pref_value; - bool expected_old_pref_value; - } kTestingTable[] = { - {kEnabledGroupName, prefs::kPasswordManagerSavingEnabled, true, true, - true}, - {kEnabledGroupName, prefs::kPasswordManagerSavingEnabled, false, false, - false}, - {kEnabledGroupName, prefs::kCredentialsEnableService, true, true, true}, - {kEnabledGroupName, prefs::kCredentialsEnableService, false, false, - false}, - {kDisabledGroupName, prefs::kPasswordManagerSavingEnabled, false, true, - false}, - {kDisabledGroupName, prefs::kCredentialsEnableService, false, false, - true}}; - - for (const auto& test_case : kTestingTable) { - SetupPreferenceMigrationEnvironment(); - EnforcePasswordManagerSettingMigrationExperiment(test_case.group); - prefs()->SetBoolean(prefs::kCredentialsEnableService, - !test_case.pref_value); - prefs()->SetBoolean(prefs::kPasswordManagerSavingEnabled, - !test_case.pref_value); - NotifyProfileAdded(); - base::HistogramTester tester; - prefs()->SetBoolean(test_case.pref_name, test_case.pref_value); - ExpectValuesForBothPrefValues(test_case.expected_new_pref_value, - test_case.expected_old_pref_value); - EXPECT_THAT(tester.GetAllSamples(kInitialValuesHistogramName), - testing::IsEmpty()); - } -} - -TEST_F(PasswordManagerSettingMigratorServiceTest, - ReconcileWhenWhenBothPrefsTypesArrivesFromSync) { - const struct { - BooleanPrefState new_pref_local_value; - BooleanPrefState old_pref_local_value; - BooleanPrefState new_pref_sync_value; - BooleanPrefState old_pref_sync_value; - bool result_value; - PasswordManagerPreferencesInitialValues histogram_initial_value; - PasswordManagerPreferencesInitialAndFinalValues histogram_initial_and_final; - } kTestingTable[] = { -#if defined(OS_ANDROID) - {ON, OFF, ON, EMPTY, false, N1L0, I10F00}, - {ON, OFF, OFF, EMPTY, false, N1L0, I10F00}, - {ON, OFF, EMPTY, EMPTY, false, N1L0, I10F00}, - {ON, ON, ON, EMPTY, true, N1L1, I11F11}, - {ON, ON, OFF, EMPTY, false, N1L1, I11F00}, - {OFF, OFF, ON, EMPTY, true, N0L0, I00F11}, - {OFF, OFF, OFF, EMPTY, false, N0L0, I00F00}, - {OFF, ON, ON, EMPTY, true, N0L1, I01F11}, - {OFF, ON, OFF, EMPTY, false, N0L1, I01F00}, - {OFF, ON, EMPTY, EMPTY, false, N0L1, I01F00}, -#else - {EMPTY, EMPTY, EMPTY, EMPTY, true, N1L1, I11F11}, - {EMPTY, EMPTY, EMPTY, OFF, false, N1L1, I11F00}, - {EMPTY, EMPTY, EMPTY, ON, true, N1L1, I11F11}, - {EMPTY, EMPTY, OFF, EMPTY, false, N1L1, I11F00}, - {EMPTY, EMPTY, ON, EMPTY, true, N1L1, I11F11}, - {OFF, OFF, EMPTY, EMPTY, false, N0L0, I00F00}, - {OFF, OFF, OFF, OFF, false, N0L0, I00F00}, - {OFF, OFF, OFF, ON, true, N0L0, I00F11}, - {OFF, OFF, ON, OFF, true, N0L0, I00F11}, - {OFF, ON, OFF, ON, false, N0L1, I01F00}, - {OFF, ON, ON, OFF, false, N0L1, I01F00}, - {OFF, ON, ON, ON, true, N0L1, I01F11}, - {ON, OFF, EMPTY, EMPTY, false, N1L0, I10F00}, - {ON, OFF, OFF, ON, false, N1L0, I10F00}, - {ON, OFF, ON, OFF, false, N1L0, I10F00}, - {ON, OFF, ON, ON, true, N1L0, I10F11}, - {ON, ON, EMPTY, OFF, false, N1L1, I11F00}, - {ON, ON, EMPTY, ON, true, N1L1, I11F11}, - {ON, ON, OFF, EMPTY, false, N1L1, I11F00}, - {ON, ON, OFF, OFF, false, N1L1, I11F00}, - {ON, ON, OFF, ON, false, N1L1, I11F00}, - {ON, ON, ON, EMPTY, true, N1L1, I11F11}, - {ON, ON, ON, OFF, false, N1L1, I11F00}, - {ON, ON, ON, ON, true, N1L1, I11F11}, -#endif - }; - - for (const auto& test_case : kTestingTable) { - SetupPreferenceMigrationEnvironment(); - EnforcePasswordManagerSettingMigrationExperiment(kEnabledGroupName); - SCOPED_TRACE(testing::Message("Local data = ") - << test_case.new_pref_local_value << " " - << test_case.old_pref_local_value); - SCOPED_TRACE(testing::Message("Sync data = ") - << test_case.new_pref_sync_value << " " - << test_case.old_pref_sync_value); - SetupLocalPrefState(prefs::kPasswordManagerSavingEnabled, - test_case.old_pref_local_value); - SetupLocalPrefState(prefs::kCredentialsEnableService, - test_case.new_pref_local_value); - base::HistogramTester tester; - NotifyProfileAdded(); - StartSyncingPref(prefs(), prefs::kCredentialsEnableService, - test_case.new_pref_sync_value); -#if !defined(OS_ANDROID) - StartSyncingPref(prefs(), prefs::kPasswordManagerSavingEnabled, - test_case.old_pref_sync_value); -#endif - ExpectValuesForBothPrefValues(test_case.result_value, - test_case.result_value); - EXPECT_THAT(tester.GetAllSamples(kInitialValuesHistogramName), - testing::ElementsAre( - base::Bucket(test_case.histogram_initial_value, 1))); - EXPECT_THAT(tester.GetAllSamples(kInitialAndFinalValuesHistogramName), - testing::ElementsAre( - base::Bucket(test_case.histogram_initial_and_final, 1))); - } -} - -TEST_F(PasswordManagerSettingMigratorServiceTest, - DoNotReconcileWhenWhenBothPrefsTypesArrivesFromSync) { - const struct { - BooleanPrefState new_pref_local_value; - BooleanPrefState old_pref_local_value; - BooleanPrefState new_pref_sync_value; - BooleanPrefState old_pref_sync_value; - bool result_new_pref_value; - bool result_old_pref_value; - PasswordManagerPreferencesInitialValues histogram_initial_value; - } kTestingTable[] = { -#if defined(OS_ANDROID) - {ON, OFF, ON, EMPTY, true, false, N1L0}, - {ON, OFF, OFF, EMPTY, false, false, N1L0}, - {ON, OFF, EMPTY, EMPTY, true, false, N1L0}, - {ON, ON, ON, EMPTY, true, true, N1L1}, - {ON, ON, OFF, EMPTY, false, true, N1L1}, - {OFF, OFF, ON, EMPTY, true, false, N0L0}, - {OFF, OFF, OFF, EMPTY, false, false, N0L0}, - {OFF, ON, ON, EMPTY, true, true, N0L1}, - {OFF, ON, OFF, EMPTY, false, true, N0L1}, - {OFF, ON, EMPTY, EMPTY, false, true, N0L1}, -#else - {OFF, OFF, OFF, ON, false, true, N0L0}, - {OFF, OFF, ON, OFF, true, false, N0L0}, - {OFF, OFF, ON, ON, true, true, N0L0}, - {OFF, ON, EMPTY, OFF, false, false, N0L1}, - {OFF, ON, EMPTY, ON, false, true, N0L1}, - {OFF, ON, OFF, EMPTY, false, true, N0L1}, - {OFF, ON, OFF, OFF, false, false, N0L1}, - {OFF, ON, OFF, ON, false, true, N0L1}, - {OFF, ON, ON, EMPTY, true, true, N0L1}, - {OFF, ON, ON, OFF, true, false, N0L1}, - {OFF, ON, ON, ON, true, true, N0L1}, - {ON, OFF, OFF, ON, false, true, N1L0}, - {ON, OFF, ON, OFF, true, false, N1L0}, - {ON, OFF, ON, ON, true, true, N1L0}, - {ON, ON, EMPTY, OFF, true, false, N1L1}, - {ON, ON, EMPTY, ON, true, true, N1L1}, - {ON, ON, OFF, EMPTY, false, true, N1L1}, - {ON, ON, OFF, OFF, false, false, N1L1}, - {ON, ON, OFF, ON, false, true, N1L1}, - {ON, ON, ON, EMPTY, true, true, N1L1}, - {ON, ON, ON, OFF, true, false, N1L1}, - {ON, ON, ON, ON, true, true, N1L1}, -#endif - }; - - for (const auto& test_case : kTestingTable) { - SetupPreferenceMigrationEnvironment(); - EnforcePasswordManagerSettingMigrationExperiment(kDisabledGroupName); - SCOPED_TRACE(testing::Message("Local data = ") - << test_case.new_pref_local_value << " " - << test_case.old_pref_local_value); - SCOPED_TRACE(testing::Message("Sync data = ") - << test_case.new_pref_sync_value << " " - << test_case.old_pref_sync_value); - SetupLocalPrefState(prefs::kPasswordManagerSavingEnabled, - test_case.old_pref_local_value); - SetupLocalPrefState(prefs::kCredentialsEnableService, - test_case.new_pref_local_value); - base::HistogramTester tester; - NotifyProfileAdded(); - StartSyncingPref(prefs(), prefs::kCredentialsEnableService, - test_case.new_pref_sync_value); -#if !defined(OS_ANDROID) - StartSyncingPref(prefs(), prefs::kPasswordManagerSavingEnabled, - test_case.old_pref_sync_value); -#endif - ExpectValuesForBothPrefValues(test_case.result_new_pref_value, - test_case.result_old_pref_value); - EXPECT_THAT(tester.GetAllSamples(kInitialValuesHistogramName), - testing::ElementsAre( - base::Bucket(test_case.histogram_initial_value, 1))); - EXPECT_THAT(tester.GetAllSamples(kInitialAndFinalValuesHistogramName), - testing::IsEmpty()); - } -} - -TEST_F(PasswordManagerSettingMigratorServiceTest, - ReconcileWhenSyncIsNotExpectedPasswordManagerEnabledOff) { - prefs()->SetBoolean(prefs::kPasswordManagerSavingEnabled, false); - profile_sync_service()->SetCanSyncStart(false); - base::HistogramTester tester; - NotifyProfileAdded(); - ExpectValuesForBothPrefValues(false, false); - EXPECT_THAT(tester.GetAllSamples(kInitialAndFinalValuesHistogramName), - testing::ElementsAre(base::Bucket(I10F00, 1))); -} - -TEST_F(PasswordManagerSettingMigratorServiceTest, - ReconcileWhenSyncIsNotExpectedPasswordManagerEnabledOn) { - prefs()->SetBoolean(prefs::kPasswordManagerSavingEnabled, true); - ASSERT_EQ(prefs()->GetBoolean(prefs::kCredentialsEnableService), true); - profile_sync_service()->SetCanSyncStart(false); - base::HistogramTester tester; - NotifyProfileAdded(); - ExpectValuesForBothPrefValues(true, true); - EXPECT_THAT(tester.GetAllSamples(kInitialAndFinalValuesHistogramName), - testing::ElementsAre(base::Bucket(I11F11, 1))); -} - -TEST_F(PasswordManagerSettingMigratorServiceTest, - ReconcileWhenSyncIsNotExpectedDefaultValuesForPrefs) { - ASSERT_EQ(prefs()->GetBoolean(prefs::kCredentialsEnableService), true); - profile_sync_service()->SetCanSyncStart(false); - base::HistogramTester tester; - NotifyProfileAdded(); - ExpectValuesForBothPrefValues(true, true); - EXPECT_THAT(tester.GetAllSamples(kInitialAndFinalValuesHistogramName), - testing::ElementsAre(base::Bucket(I11F11, 1))); -} - -} // namespace password_manager
diff --git a/chrome/browser/password_manager/password_store_factory.cc b/chrome/browser/password_manager/password_store_factory.cc index 3b9ea6d..f4873fe 100644 --- a/chrome/browser/password_manager/password_store_factory.cc +++ b/chrome/browser/password_manager/password_store_factory.cc
@@ -45,7 +45,6 @@ #include "chrome/browser/password_manager/native_backend_gnome_x.h" #endif #if defined(USE_LIBSECRET) -#include "base/metrics/field_trial.h" #include "chrome/browser/password_manager/native_backend_libsecret.h" #endif #include "chrome/browser/password_manager/native_backend_kwallet_x.h" @@ -61,11 +60,6 @@ static_cast<LocalProfileId>(0); #endif -#if defined(USE_LIBSECRET) -const char kLibsecretFieldTrialName[] = "Libsecret"; -const char kLibsecretFieldTrialDisabledGroupName[] = "Disabled"; -#endif - } // namespace // static @@ -224,16 +218,13 @@ used_desktop_env == base::nix::DESKTOP_ENVIRONMENT_UNITY || used_desktop_env == base::nix::DESKTOP_ENVIRONMENT_XFCE) { #if defined(USE_LIBSECRET) - if (base::FieldTrialList::FindFullName(kLibsecretFieldTrialName) != - kLibsecretFieldTrialDisabledGroupName) { - VLOG(1) << "Trying libsecret for password storage."; - backend.reset(new NativeBackendLibsecret(id)); - if (backend->Init()) { - VLOG(1) << "Using libsecret keyring for password storage."; - used_backend = LIBSECRET; - } else { - backend.reset(); - } + VLOG(1) << "Trying libsecret for password storage."; + backend.reset(new NativeBackendLibsecret(id)); + if (backend->Init()) { + VLOG(1) << "Using libsecret keyring for password storage."; + used_backend = LIBSECRET; + } else { + backend.reset(); } #endif // defined(USE_LIBSECRET) if (!backend.get()) {
diff --git a/chrome/browser/permissions/permission_bubble_request_impl.cc b/chrome/browser/permissions/permission_bubble_request_impl.cc index 8d78048..f438678 100644 --- a/chrome/browser/permissions/permission_bubble_request_impl.cc +++ b/chrome/browser/permissions/permission_bubble_request_impl.cc
@@ -5,7 +5,7 @@ #include "chrome/browser/permissions/permission_bubble_request_impl.h" #include "chrome/browser/permissions/permission_context_base.h" -#include "chrome/browser/permissions/permission_context_uma_util.h" +#include "chrome/browser/permissions/permission_uma_util.h" #include "chrome/grit/generated_resources.h" #include "components/url_formatter/elide_url.h" #include "grit/theme_resources.h" @@ -33,7 +33,7 @@ PermissionBubbleRequestImpl::~PermissionBubbleRequestImpl() { DCHECK(is_finished_); if (!action_taken_) - PermissionContextUmaUtil::PermissionIgnored(type_, request_origin_); + PermissionUmaUtil::PermissionIgnored(type_, request_origin_); } gfx::VectorIconId PermissionBubbleRequestImpl::GetVectorIconId() const {
diff --git a/chrome/browser/permissions/permission_context_base.cc b/chrome/browser/permissions/permission_context_base.cc index 9367f916..dd22cd56 100644 --- a/chrome/browser/permissions/permission_context_base.cc +++ b/chrome/browser/permissions/permission_context_base.cc
@@ -7,8 +7,8 @@ #include "base/logging.h" #include "base/prefs/pref_service.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/permissions/permission_context_uma_util.h" #include "chrome/browser/permissions/permission_request_id.h" +#include "chrome/browser/permissions/permission_uma_util.h" #include "chrome/browser/permissions/permission_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" @@ -164,7 +164,7 @@ return; } - PermissionContextUmaUtil::PermissionRequested( + PermissionUmaUtil::PermissionRequested( permission_type_, requesting_origin, embedding_origin, profile_); #if !defined(OS_ANDROID) @@ -215,15 +215,12 @@ DCHECK(content_setting == CONTENT_SETTING_ALLOW || content_setting == CONTENT_SETTING_BLOCK); if (content_setting == CONTENT_SETTING_ALLOW) - PermissionContextUmaUtil::PermissionGranted(permission_type_, - requesting_origin); + PermissionUmaUtil::PermissionGranted(permission_type_, requesting_origin); else - PermissionContextUmaUtil::PermissionDenied(permission_type_, - requesting_origin); + PermissionUmaUtil::PermissionDenied(permission_type_, requesting_origin); } else { DCHECK_EQ(content_setting, CONTENT_SETTING_DEFAULT); - PermissionContextUmaUtil::PermissionDismissed(permission_type_, - requesting_origin); + PermissionUmaUtil::PermissionDismissed(permission_type_, requesting_origin); } #endif
diff --git a/chrome/browser/permissions/permission_context_base_unittest.cc b/chrome/browser/permissions/permission_context_base_unittest.cc index 3c3bf99f..5be49577 100644 --- a/chrome/browser/permissions/permission_context_base_unittest.cc +++ b/chrome/browser/permissions/permission_context_base_unittest.cc
@@ -10,7 +10,6 @@ #include "base/test/mock_entropy_provider.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/infobars/infobar_service.h" -#include "chrome/browser/permissions/permission_context_uma_util.h" #include "chrome/browser/permissions/permission_queue_controller.h" #include "chrome/browser/permissions/permission_request_id.h" #include "chrome/browser/permissions/permission_util.h"
diff --git a/chrome/browser/permissions/permission_context_uma_util.cc b/chrome/browser/permissions/permission_context_uma_util.cc deleted file mode 100644 index a503ec0..0000000 --- a/chrome/browser/permissions/permission_context_uma_util.cc +++ /dev/null
@@ -1,309 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/permissions/permission_context_uma_util.h" - -#include "base/metrics/histogram_macros.h" -#include "base/strings/stringprintf.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/permissions/permission_manager.h" -#include "chrome/browser/permissions/permission_util.h" -#include "chrome/browser/profiles/profile.h" -#include "components/rappor/rappor_service.h" -#include "components/rappor/rappor_utils.h" -#include "content/public/browser/permission_type.h" -#include "content/public/common/origin_util.h" -#include "url/gurl.h" - -// UMA keys need to be statically initialized so plain function would not -// work. Use a Macro instead. -#define PERMISSION_ACTION_UMA(secure_origin, permission, permission_secure, \ - permission_insecure, action) \ - UMA_HISTOGRAM_ENUMERATION(permission, action, PERMISSION_ACTION_NUM); \ - if (secure_origin) { \ - UMA_HISTOGRAM_ENUMERATION(permission_secure, action, \ - PERMISSION_ACTION_NUM); \ - } else { \ - UMA_HISTOGRAM_ENUMERATION(permission_insecure, action, \ - PERMISSION_ACTION_NUM); \ - } - -using content::PermissionType; - -namespace { - -// Enum for UMA purposes, make sure you update histograms.xml if you add new -// permission actions. Never delete or reorder an entry; only add new entries -// immediately before PERMISSION_NUM -enum PermissionAction { - GRANTED = 0, - DENIED = 1, - DISMISSED = 2, - IGNORED = 3, - REVOKED = 4, - REENABLED = 5, - REQUESTED = 6, - - // Always keep this at the end. - PERMISSION_ACTION_NUM, -}; - -// Deprecated. This method is used for the single-dimensional RAPPOR metrics -// that are being replaced by the multi-dimensional ones. -const std::string GetRapporMetric(ContentSettingsType permission, - PermissionAction action) { - std::string action_str; - switch (action) { - case GRANTED: - action_str = "Granted"; - break; - case DENIED: - action_str = "Denied"; - break; - case DISMISSED: - action_str = "Dismissed"; - break; - case IGNORED: - action_str = "Ignored"; - break; - default: - NOTREACHED(); - break; - } - - std::string permission_str = - PermissionUtil::GetPermissionString(permission); - if (permission_str.empty()) - return ""; - return base::StringPrintf("ContentSettings.PermissionActions_%s.%s.Url", - permission_str.c_str(), action_str.c_str()); -} - -void RecordPermissionAction(ContentSettingsType permission, - PermissionAction action, - const GURL& requesting_origin) { - bool secure_origin = content::IsOriginSecure(requesting_origin); - - switch (permission) { - case CONTENT_SETTINGS_TYPE_GEOLOCATION: - PERMISSION_ACTION_UMA( - secure_origin, - "ContentSettings.PermissionActions_Geolocation", - "ContentSettings.PermissionActionsSecureOrigin_Geolocation", - "ContentSettings.PermissionActionsInsecureOrigin_Geolocation", - action); - break; - case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: - PERMISSION_ACTION_UMA( - secure_origin, - "ContentSettings.PermissionActions_Notifications", - "ContentSettings.PermissionActionsSecureOrigin_Notifications", - "ContentSettings.PermissionActionsInsecureOrigin_Notifications", - action); - break; - case CONTENT_SETTINGS_TYPE_MIDI_SYSEX: - PERMISSION_ACTION_UMA( - secure_origin, - "ContentSettings.PermissionActions_MidiSysEx", - "ContentSettings.PermissionActionsSecureOrigin_MidiSysEx", - "ContentSettings.PermissionActionsInsecureOrigin_MidiSysEx", - action); - break; - case CONTENT_SETTINGS_TYPE_PUSH_MESSAGING: - PERMISSION_ACTION_UMA( - secure_origin, - "ContentSettings.PermissionActions_PushMessaging", - "ContentSettings.PermissionActionsSecureOrigin_PushMessaging", - "ContentSettings.PermissionActionsInsecureOrigin_PushMessaging", - action); - break; -#if defined(OS_ANDROID) || defined(OS_CHROMEOS) - case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER: - PERMISSION_ACTION_UMA( - secure_origin, - "ContentSettings.PermissionActions_ProtectedMedia", - "ContentSettings.PermissionActionsSecureOrigin_ProtectedMedia", - "ContentSettings.PermissionActionsInsecureOrigin_ProtectedMedia", - action); - break; -#endif - case CONTENT_SETTINGS_TYPE_DURABLE_STORAGE: - PERMISSION_ACTION_UMA( - secure_origin, "ContentSettings.PermissionActions_DurableStorage", - "ContentSettings.PermissionActionsSecureOrigin_DurableStorage", - "ContentSettings.PermissionActionsInsecureOrigin_DurableStorage", - action); - break; - default: - NOTREACHED() << "PERMISSION " << permission << " not accounted for"; - } - - // There are two sets of semi-redundant RAPPOR metrics being reported: - // The soon-to-be-deprecated single dimensional ones, and the new - // multi-dimensional ones. - rappor::RapporService* rappor_service = g_browser_process->rappor_service(); - const std::string rappor_metric = GetRapporMetric(permission, action); - if (!rappor_metric.empty()) - rappor::SampleDomainAndRegistryFromGURL( - rappor_service, rappor_metric, requesting_origin); - - // Add multi-dimensional RAPPOR reporting for safe-browsing users. - std::string permission_str = - PermissionUtil::GetPermissionString(permission); - if (!rappor_service || permission_str.empty()) - return; - - scoped_ptr<rappor::Sample> sample = - rappor_service->CreateSample(rappor::SAFEBROWSING_RAPPOR_TYPE); - sample->SetStringField("Scheme", requesting_origin.scheme()); - sample->SetStringField("Host", requesting_origin.host()); - sample->SetStringField("Port", requesting_origin.port()); - sample->SetStringField("Domain", - rappor::GetDomainAndRegistrySampleFromGURL(requesting_origin)); - sample->SetFlagsField("Actions", - 1 << action, - PermissionAction::PERMISSION_ACTION_NUM); - rappor_service->RecordSampleObj("Permissions.Action." + - permission_str, sample.Pass()); -} - -std::string PermissionTypeToString(PermissionType permission_type) { - switch (permission_type) { - case PermissionType::MIDI_SYSEX: - return "MidiSysex"; - case PermissionType::PUSH_MESSAGING: - return "PushMessaging"; - case PermissionType::NOTIFICATIONS: - return "Notifications"; - case PermissionType::GEOLOCATION: - return "Geolocation"; - case PermissionType::PROTECTED_MEDIA_IDENTIFIER: - return "ProtectedMediaIdentifier"; - case PermissionType::DURABLE_STORAGE: - return "DurableStorage"; - case PermissionType::MIDI: - return "Midi"; - case PermissionType::AUDIO_CAPTURE: - return "AudioRecording"; - case PermissionType::VIDEO_CAPTURE: - return "VideoRecording"; - case PermissionType::NUM: - break; - } - NOTREACHED(); - return std::string(); -} - -void RecordPermissionRequest(ContentSettingsType permission, - const GURL& requesting_origin, - const GURL& embedding_origin, - Profile* profile) { - bool secure_origin = content::IsOriginSecure(requesting_origin); - PermissionType type; - switch (permission) { - case CONTENT_SETTINGS_TYPE_GEOLOCATION: - type = PermissionType::GEOLOCATION; - rappor::SampleDomainAndRegistryFromGURL( - g_browser_process->rappor_service(), - "ContentSettings.PermissionRequested.Geolocation.Url", - requesting_origin); - break; - case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: - type = PermissionType::NOTIFICATIONS; - rappor::SampleDomainAndRegistryFromGURL( - g_browser_process->rappor_service(), - "ContentSettings.PermissionRequested.Notifications.Url", - requesting_origin); - break; - case CONTENT_SETTINGS_TYPE_MIDI_SYSEX: - type = PermissionType::MIDI_SYSEX; - break; - case CONTENT_SETTINGS_TYPE_PUSH_MESSAGING: - type = PermissionType::PUSH_MESSAGING; - break; -#if defined(OS_ANDROID) || defined(OS_CHROMEOS) - case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER: - type = PermissionType::PROTECTED_MEDIA_IDENTIFIER; - break; -#endif - case CONTENT_SETTINGS_TYPE_DURABLE_STORAGE: - type = content::PermissionType::DURABLE_STORAGE; - break; - default: - NOTREACHED() << "PERMISSION " << permission << " not accounted for"; - return; - } - UMA_HISTOGRAM_ENUMERATION( - "ContentSettings.PermissionRequested", - static_cast<base::HistogramBase::Sample>(type), - static_cast<base::HistogramBase::Sample>(PermissionType::NUM)); - if (secure_origin) { - UMA_HISTOGRAM_ENUMERATION( - "ContentSettings.PermissionRequested_SecureOrigin", - static_cast<base::HistogramBase::Sample>(type), - static_cast<base::HistogramBase::Sample>(PermissionType::NUM)); - } else { - UMA_HISTOGRAM_ENUMERATION( - "ContentSettings.PermissionRequested_InsecureOrigin", - static_cast<base::HistogramBase::Sample>(type), - static_cast<base::HistogramBase::Sample>(PermissionType::NUM)); - } - - // In order to gauge the compatibility risk of implementing an improved - // iframe permissions security model, we would like to know the ratio of - // same-origin to cross-origin permission requests. Our estimate of this - // ratio could be somewhat biased by repeated requests coming from a - // single frame, but we expect this to be insignificant. - if (requesting_origin.GetOrigin() != embedding_origin.GetOrigin()) { - content::PermissionManager* manager = profile->GetPermissionManager(); - if (!manager) - return; - content::PermissionStatus embedding_permission_status = - manager->GetPermissionStatus(type, embedding_origin, embedding_origin); - - base::HistogramBase* histogram = base::LinearHistogram::FactoryGet( - "Permissions.Requested.CrossOrigin_" + PermissionTypeToString(type), 1, - content::PERMISSION_STATUS_LAST, content::PERMISSION_STATUS_LAST + 1, - base::HistogramBase::kUmaTargetedHistogramFlag); - histogram->Add(embedding_permission_status); - } else { - UMA_HISTOGRAM_ENUMERATION( - "Permissions.Requested.SameOrigin", - static_cast<base::HistogramBase::Sample>(type), - static_cast<base::HistogramBase::Sample>(PermissionType::NUM)); - } -} - -} // namespace - -// Make sure you update histograms.xml permission histogram_suffix if you -// add new permission -void PermissionContextUmaUtil::PermissionRequested( - ContentSettingsType permission, - const GURL& requesting_origin, - const GURL& embedding_origin, - Profile* profile) { - RecordPermissionRequest(permission, requesting_origin, embedding_origin, - profile); -} - -void PermissionContextUmaUtil::PermissionGranted( - ContentSettingsType permission, const GURL& requesting_origin) { - RecordPermissionAction(permission, GRANTED, requesting_origin); -} - -void PermissionContextUmaUtil::PermissionDenied( - ContentSettingsType permission, const GURL& requesting_origin) { - RecordPermissionAction(permission, DENIED, requesting_origin); -} - -void PermissionContextUmaUtil::PermissionDismissed( - ContentSettingsType permission, const GURL& requesting_origin) { - RecordPermissionAction(permission, DISMISSED, requesting_origin); -} - -void PermissionContextUmaUtil::PermissionIgnored( - ContentSettingsType permission, const GURL& requesting_origin) { - RecordPermissionAction(permission, IGNORED, requesting_origin); -}
diff --git a/chrome/browser/permissions/permission_context_uma_util.h b/chrome/browser/permissions/permission_context_uma_util.h deleted file mode 100644 index 05130ba..0000000 --- a/chrome/browser/permissions/permission_context_uma_util.h +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_PERMISSIONS_PERMISSION_CONTEXT_UMA_UTIL_H_ -#define CHROME_BROWSER_PERMISSIONS_PERMISSION_CONTEXT_UMA_UTIL_H_ - -#include "base/logging.h" -#include "components/content_settings/core/common/content_settings_types.h" - -class GURL; -class Profile; - -// Provides a convenient way of logging UMA for permission related -// operations. -class PermissionContextUmaUtil { - public: - static void PermissionRequested(ContentSettingsType permission, - const GURL& requesting_origin, - const GURL& embedding_origin, - Profile* profile); - static void PermissionGranted(ContentSettingsType permission, - const GURL& requesting_origin); - static void PermissionDenied(ContentSettingsType permission, - const GURL& requesting_origin); - static void PermissionDismissed(ContentSettingsType permission, - const GURL& requesting_origin); - static void PermissionIgnored(ContentSettingsType permission, - const GURL& requesting_origin); - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(PermissionContextUmaUtil); -}; - -#endif // CHROME_BROWSER_PERMISSIONS_PERMISSION_CONTEXT_UMA_UTIL_H_
diff --git a/chrome/browser/permissions/permission_infobar_delegate.cc b/chrome/browser/permissions/permission_infobar_delegate.cc index f91c995..00b45e48 100644 --- a/chrome/browser/permissions/permission_infobar_delegate.cc +++ b/chrome/browser/permissions/permission_infobar_delegate.cc
@@ -4,14 +4,14 @@ #include "chrome/browser/permissions/permission_infobar_delegate.h" -#include "chrome/browser/permissions/permission_context_uma_util.h" +#include "chrome/browser/permissions/permission_uma_util.h" #include "chrome/grit/generated_resources.h" #include "components/infobars/core/infobar.h" #include "ui/base/l10n/l10n_util.h" PermissionInfobarDelegate::~PermissionInfobarDelegate() { if (!action_taken_) - PermissionContextUmaUtil::PermissionIgnored(type_, requesting_origin_); + PermissionUmaUtil::PermissionIgnored(type_, requesting_origin_); } PermissionInfobarDelegate::PermissionInfobarDelegate(
diff --git a/chrome/browser/permissions/permission_queue_controller.cc b/chrome/browser/permissions/permission_queue_controller.cc index 9f45d7c..ac7e3f6 100644 --- a/chrome/browser/permissions/permission_queue_controller.cc +++ b/chrome/browser/permissions/permission_queue_controller.cc
@@ -12,8 +12,8 @@ #include "chrome/browser/media/midi_permission_infobar_delegate_android.h" #include "chrome/browser/media/protected_media_identifier_infobar_delegate_android.h" #include "chrome/browser/notifications/notification_permission_infobar_delegate.h" -#include "chrome/browser/permissions/permission_context_uma_util.h" #include "chrome/browser/permissions/permission_request_id.h" +#include "chrome/browser/permissions/permission_uma_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/storage/durable_storage_permission_infobar_delegate_android.h" #include "chrome/browser/tab_contents/tab_util.h" @@ -219,11 +219,11 @@ if (update_content_setting) { UpdateContentSetting(requesting_frame, embedder, allowed); if (allowed) - PermissionContextUmaUtil::PermissionGranted(type_, requesting_frame); + PermissionUmaUtil::PermissionGranted(type_, requesting_frame); else - PermissionContextUmaUtil::PermissionDenied(type_, requesting_frame); + PermissionUmaUtil::PermissionDenied(type_, requesting_frame); } else { - PermissionContextUmaUtil::PermissionDismissed(type_, requesting_frame); + PermissionUmaUtil::PermissionDismissed(type_, requesting_frame); } // Cancel this request first, then notify listeners. TODO(pkasting): Why
diff --git a/chrome/browser/permissions/permission_uma_util.cc b/chrome/browser/permissions/permission_uma_util.cc new file mode 100644 index 0000000..f7fbd6a --- /dev/null +++ b/chrome/browser/permissions/permission_uma_util.cc
@@ -0,0 +1,309 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/permissions/permission_uma_util.h" + +#include "base/metrics/histogram_macros.h" +#include "base/strings/stringprintf.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/permissions/permission_manager.h" +#include "chrome/browser/permissions/permission_util.h" +#include "chrome/browser/profiles/profile.h" +#include "components/rappor/rappor_service.h" +#include "components/rappor/rappor_utils.h" +#include "content/public/browser/permission_type.h" +#include "content/public/common/origin_util.h" +#include "url/gurl.h" + +// UMA keys need to be statically initialized so plain function would not +// work. Use a Macro instead. +#define PERMISSION_ACTION_UMA(secure_origin, permission, permission_secure, \ + permission_insecure, action) \ + UMA_HISTOGRAM_ENUMERATION(permission, action, PERMISSION_ACTION_NUM); \ + if (secure_origin) { \ + UMA_HISTOGRAM_ENUMERATION(permission_secure, action, \ + PERMISSION_ACTION_NUM); \ + } else { \ + UMA_HISTOGRAM_ENUMERATION(permission_insecure, action, \ + PERMISSION_ACTION_NUM); \ + } + +using content::PermissionType; + +namespace { + +// Enum for UMA purposes, make sure you update histograms.xml if you add new +// permission actions. Never delete or reorder an entry; only add new entries +// immediately before PERMISSION_NUM +enum PermissionAction { + GRANTED = 0, + DENIED = 1, + DISMISSED = 2, + IGNORED = 3, + REVOKED = 4, + REENABLED = 5, + REQUESTED = 6, + + // Always keep this at the end. + PERMISSION_ACTION_NUM, +}; + +// Deprecated. This method is used for the single-dimensional RAPPOR metrics +// that are being replaced by the multi-dimensional ones. +const std::string GetRapporMetric(ContentSettingsType permission, + PermissionAction action) { + std::string action_str; + switch (action) { + case GRANTED: + action_str = "Granted"; + break; + case DENIED: + action_str = "Denied"; + break; + case DISMISSED: + action_str = "Dismissed"; + break; + case IGNORED: + action_str = "Ignored"; + break; + default: + NOTREACHED(); + break; + } + + std::string permission_str = + PermissionUtil::GetPermissionString(permission); + if (permission_str.empty()) + return ""; + return base::StringPrintf("ContentSettings.PermissionActions_%s.%s.Url", + permission_str.c_str(), action_str.c_str()); +} + +void RecordPermissionAction(ContentSettingsType permission, + PermissionAction action, + const GURL& requesting_origin) { + bool secure_origin = content::IsOriginSecure(requesting_origin); + + switch (permission) { + case CONTENT_SETTINGS_TYPE_GEOLOCATION: + PERMISSION_ACTION_UMA( + secure_origin, + "ContentSettings.PermissionActions_Geolocation", + "ContentSettings.PermissionActionsSecureOrigin_Geolocation", + "ContentSettings.PermissionActionsInsecureOrigin_Geolocation", + action); + break; + case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: + PERMISSION_ACTION_UMA( + secure_origin, + "ContentSettings.PermissionActions_Notifications", + "ContentSettings.PermissionActionsSecureOrigin_Notifications", + "ContentSettings.PermissionActionsInsecureOrigin_Notifications", + action); + break; + case CONTENT_SETTINGS_TYPE_MIDI_SYSEX: + PERMISSION_ACTION_UMA( + secure_origin, + "ContentSettings.PermissionActions_MidiSysEx", + "ContentSettings.PermissionActionsSecureOrigin_MidiSysEx", + "ContentSettings.PermissionActionsInsecureOrigin_MidiSysEx", + action); + break; + case CONTENT_SETTINGS_TYPE_PUSH_MESSAGING: + PERMISSION_ACTION_UMA( + secure_origin, + "ContentSettings.PermissionActions_PushMessaging", + "ContentSettings.PermissionActionsSecureOrigin_PushMessaging", + "ContentSettings.PermissionActionsInsecureOrigin_PushMessaging", + action); + break; +#if defined(OS_ANDROID) || defined(OS_CHROMEOS) + case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER: + PERMISSION_ACTION_UMA( + secure_origin, + "ContentSettings.PermissionActions_ProtectedMedia", + "ContentSettings.PermissionActionsSecureOrigin_ProtectedMedia", + "ContentSettings.PermissionActionsInsecureOrigin_ProtectedMedia", + action); + break; +#endif + case CONTENT_SETTINGS_TYPE_DURABLE_STORAGE: + PERMISSION_ACTION_UMA( + secure_origin, "ContentSettings.PermissionActions_DurableStorage", + "ContentSettings.PermissionActionsSecureOrigin_DurableStorage", + "ContentSettings.PermissionActionsInsecureOrigin_DurableStorage", + action); + break; + default: + NOTREACHED() << "PERMISSION " << permission << " not accounted for"; + } + + // There are two sets of semi-redundant RAPPOR metrics being reported: + // The soon-to-be-deprecated single dimensional ones, and the new + // multi-dimensional ones. + rappor::RapporService* rappor_service = g_browser_process->rappor_service(); + const std::string rappor_metric = GetRapporMetric(permission, action); + if (!rappor_metric.empty()) + rappor::SampleDomainAndRegistryFromGURL( + rappor_service, rappor_metric, requesting_origin); + + // Add multi-dimensional RAPPOR reporting for safe-browsing users. + std::string permission_str = + PermissionUtil::GetPermissionString(permission); + if (!rappor_service || permission_str.empty()) + return; + + scoped_ptr<rappor::Sample> sample = + rappor_service->CreateSample(rappor::SAFEBROWSING_RAPPOR_TYPE); + sample->SetStringField("Scheme", requesting_origin.scheme()); + sample->SetStringField("Host", requesting_origin.host()); + sample->SetStringField("Port", requesting_origin.port()); + sample->SetStringField("Domain", + rappor::GetDomainAndRegistrySampleFromGURL(requesting_origin)); + sample->SetFlagsField("Actions", + 1 << action, + PermissionAction::PERMISSION_ACTION_NUM); + rappor_service->RecordSampleObj("Permissions.Action." + + permission_str, sample.Pass()); +} + +std::string PermissionTypeToString(PermissionType permission_type) { + switch (permission_type) { + case PermissionType::MIDI_SYSEX: + return "MidiSysex"; + case PermissionType::PUSH_MESSAGING: + return "PushMessaging"; + case PermissionType::NOTIFICATIONS: + return "Notifications"; + case PermissionType::GEOLOCATION: + return "Geolocation"; + case PermissionType::PROTECTED_MEDIA_IDENTIFIER: + return "ProtectedMediaIdentifier"; + case PermissionType::DURABLE_STORAGE: + return "DurableStorage"; + case PermissionType::MIDI: + return "Midi"; + case PermissionType::AUDIO_CAPTURE: + return "AudioRecording"; + case PermissionType::VIDEO_CAPTURE: + return "VideoRecording"; + case PermissionType::NUM: + break; + } + NOTREACHED(); + return std::string(); +} + +void RecordPermissionRequest(ContentSettingsType permission, + const GURL& requesting_origin, + const GURL& embedding_origin, + Profile* profile) { + bool secure_origin = content::IsOriginSecure(requesting_origin); + PermissionType type; + switch (permission) { + case CONTENT_SETTINGS_TYPE_GEOLOCATION: + type = PermissionType::GEOLOCATION; + rappor::SampleDomainAndRegistryFromGURL( + g_browser_process->rappor_service(), + "ContentSettings.PermissionRequested.Geolocation.Url", + requesting_origin); + break; + case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: + type = PermissionType::NOTIFICATIONS; + rappor::SampleDomainAndRegistryFromGURL( + g_browser_process->rappor_service(), + "ContentSettings.PermissionRequested.Notifications.Url", + requesting_origin); + break; + case CONTENT_SETTINGS_TYPE_MIDI_SYSEX: + type = PermissionType::MIDI_SYSEX; + break; + case CONTENT_SETTINGS_TYPE_PUSH_MESSAGING: + type = PermissionType::PUSH_MESSAGING; + break; +#if defined(OS_ANDROID) || defined(OS_CHROMEOS) + case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER: + type = PermissionType::PROTECTED_MEDIA_IDENTIFIER; + break; +#endif + case CONTENT_SETTINGS_TYPE_DURABLE_STORAGE: + type = content::PermissionType::DURABLE_STORAGE; + break; + default: + NOTREACHED() << "PERMISSION " << permission << " not accounted for"; + return; + } + UMA_HISTOGRAM_ENUMERATION( + "ContentSettings.PermissionRequested", + static_cast<base::HistogramBase::Sample>(type), + static_cast<base::HistogramBase::Sample>(PermissionType::NUM)); + if (secure_origin) { + UMA_HISTOGRAM_ENUMERATION( + "ContentSettings.PermissionRequested_SecureOrigin", + static_cast<base::HistogramBase::Sample>(type), + static_cast<base::HistogramBase::Sample>(PermissionType::NUM)); + } else { + UMA_HISTOGRAM_ENUMERATION( + "ContentSettings.PermissionRequested_InsecureOrigin", + static_cast<base::HistogramBase::Sample>(type), + static_cast<base::HistogramBase::Sample>(PermissionType::NUM)); + } + + // In order to gauge the compatibility risk of implementing an improved + // iframe permissions security model, we would like to know the ratio of + // same-origin to cross-origin permission requests. Our estimate of this + // ratio could be somewhat biased by repeated requests coming from a + // single frame, but we expect this to be insignificant. + if (requesting_origin.GetOrigin() != embedding_origin.GetOrigin()) { + content::PermissionManager* manager = profile->GetPermissionManager(); + if (!manager) + return; + content::PermissionStatus embedding_permission_status = + manager->GetPermissionStatus(type, embedding_origin, embedding_origin); + + base::HistogramBase* histogram = base::LinearHistogram::FactoryGet( + "Permissions.Requested.CrossOrigin_" + PermissionTypeToString(type), 1, + content::PERMISSION_STATUS_LAST, content::PERMISSION_STATUS_LAST + 1, + base::HistogramBase::kUmaTargetedHistogramFlag); + histogram->Add(embedding_permission_status); + } else { + UMA_HISTOGRAM_ENUMERATION( + "Permissions.Requested.SameOrigin", + static_cast<base::HistogramBase::Sample>(type), + static_cast<base::HistogramBase::Sample>(PermissionType::NUM)); + } +} + +} // namespace + +// Make sure you update histograms.xml permission histogram_suffix if you +// add new permission +void PermissionUmaUtil::PermissionRequested( + ContentSettingsType permission, + const GURL& requesting_origin, + const GURL& embedding_origin, + Profile* profile) { + RecordPermissionRequest(permission, requesting_origin, embedding_origin, + profile); +} + +void PermissionUmaUtil::PermissionGranted( + ContentSettingsType permission, const GURL& requesting_origin) { + RecordPermissionAction(permission, GRANTED, requesting_origin); +} + +void PermissionUmaUtil::PermissionDenied( + ContentSettingsType permission, const GURL& requesting_origin) { + RecordPermissionAction(permission, DENIED, requesting_origin); +} + +void PermissionUmaUtil::PermissionDismissed( + ContentSettingsType permission, const GURL& requesting_origin) { + RecordPermissionAction(permission, DISMISSED, requesting_origin); +} + +void PermissionUmaUtil::PermissionIgnored( + ContentSettingsType permission, const GURL& requesting_origin) { + RecordPermissionAction(permission, IGNORED, requesting_origin); +}
diff --git a/chrome/browser/permissions/permission_uma_util.h b/chrome/browser/permissions/permission_uma_util.h new file mode 100644 index 0000000..ce5cb11 --- /dev/null +++ b/chrome/browser/permissions/permission_uma_util.h
@@ -0,0 +1,34 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_PERMISSIONS_PERMISSION_UMA_UTIL_H_ +#define CHROME_BROWSER_PERMISSIONS_PERMISSION_UMA_UTIL_H_ + +#include "base/logging.h" +#include "components/content_settings/core/common/content_settings_types.h" + +class GURL; +class Profile; + +// Provides a convenient way of logging UMA for permission related operations. +class PermissionUmaUtil { + public: + static void PermissionRequested(ContentSettingsType permission, + const GURL& requesting_origin, + const GURL& embedding_origin, + Profile* profile); + static void PermissionGranted(ContentSettingsType permission, + const GURL& requesting_origin); + static void PermissionDenied(ContentSettingsType permission, + const GURL& requesting_origin); + static void PermissionDismissed(ContentSettingsType permission, + const GURL& requesting_origin); + static void PermissionIgnored(ContentSettingsType permission, + const GURL& requesting_origin); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(PermissionUmaUtil); +}; + +#endif // CHROME_BROWSER_PERMISSIONS_PERMISSION_UMA_UTIL_H_
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc index 82324f08..a9a6c014 100644 --- a/chrome/browser/prerender/prerender_browsertest.cc +++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -755,7 +755,7 @@ std::vector<GURL>(1, gurl), std::vector<SBFullHash>(), client, - safe_browsing_util::MALWARE, + safe_browsing::MALWARE, expected_threats); sb_check.url_results[0] = threat_type_; sb_check.OnSafeBrowsingResult();
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index a9c64e2..5312e9a 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -64,7 +64,6 @@ #include "chrome/browser/push_messaging/push_messaging_service_factory.h" #include "chrome/browser/push_messaging/push_messaging_service_impl.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" -#include "chrome/browser/services/gcm/gcm_profile_service.h" #include "chrome/browser/sessions/session_service_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/signin/signin_ui_util.h" @@ -82,6 +81,7 @@ #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/domain_reliability/monitor.h" #include "components/domain_reliability/service.h" +#include "components/gcm_driver/gcm_profile_service.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/metrics/metrics_service.h" #include "components/omnibox/browser/autocomplete_classifier.h"
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc index 31b1a9b..77784e0 100644 --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc
@@ -30,7 +30,6 @@ #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h" #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h" #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h" -#include "chrome/browser/password_manager/password_manager_setting_migrator_service.h" #include "chrome/browser/password_manager/password_manager_setting_migrator_service_factory.h" #include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" @@ -66,6 +65,7 @@ #include "components/invalidation/impl/profile_invalidation_provider.h" #include "components/invalidation/public/invalidation_service.h" #include "components/password_manager/core/browser/password_store.h" +#include "components/password_manager/sync/browser/password_manager_setting_migrator_service.h" #include "components/signin/core/browser/account_fetcher_service.h" #include "components/signin/core/browser/account_tracker_service.h" #include "components/signin/core/browser/gaia_cookie_manager_service.h"
diff --git a/chrome/browser/push_messaging/push_messaging_permission_context.cc b/chrome/browser/push_messaging/push_messaging_permission_context.cc index b1a2c3c3..3a6d246 100644 --- a/chrome/browser/push_messaging/push_messaging_permission_context.cc +++ b/chrome/browser/push_messaging/push_messaging_permission_context.cc
@@ -7,8 +7,8 @@ #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/notifications/notification_permission_context.h" #include "chrome/browser/notifications/notification_permission_context_factory.h" -#include "chrome/browser/permissions/permission_context_uma_util.h" #include "chrome/browser/permissions/permission_request_id.h" +#include "chrome/browser/permissions/permission_uma_util.h" #include "chrome/browser/profiles/profile.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "content/public/browser/browser_thread.h" @@ -125,8 +125,7 @@ if (push_content_setting == CONTENT_SETTING_BLOCK) { DVLOG(1) << "Push permission was explicitly blocked."; - PermissionContextUmaUtil::PermissionDenied(kPushSettingType, - requesting_origin); + PermissionUmaUtil::PermissionDenied(kPushSettingType, requesting_origin); NotifyPermissionSet(id, requesting_origin, embedding_origin, callback, true /* persist */, CONTENT_SETTING_BLOCK); return; @@ -139,8 +138,7 @@ return; } - PermissionContextUmaUtil::PermissionGranted(kPushSettingType, - requesting_origin); + PermissionUmaUtil::PermissionGranted(kPushSettingType, requesting_origin); NotifyPermissionSet(id, requesting_origin, embedding_origin, callback, true /* persist */, CONTENT_SETTING_ALLOW); }
diff --git a/chrome/browser/push_messaging/push_messaging_service_impl.cc b/chrome/browser/push_messaging/push_messaging_service_impl.cc index e0c02f2..124f883 100644 --- a/chrome/browser/push_messaging/push_messaging_service_impl.cc +++ b/chrome/browser/push_messaging/push_messaging_service_impl.cc
@@ -21,7 +21,6 @@ #include "chrome/browser/push_messaging/push_messaging_app_identifier.h" #include "chrome/browser/push_messaging/push_messaging_constants.h" #include "chrome/browser/push_messaging/push_messaging_service_factory.h" -#include "chrome/browser/services/gcm/gcm_profile_service.h" #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/common/chrome_switches.h" @@ -29,6 +28,7 @@ #include "chrome/grit/generated_resources.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/gcm_driver/gcm_driver.h" +#include "components/gcm_driver/gcm_profile_service.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/rappor/rappor_utils.h" #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js index a8dd3f3..cc5c9fd 100644 --- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js +++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
@@ -270,8 +270,8 @@ var idleDuration = Date.now() - self.mostRecentUserActivity_; if (idleDuration > IDLE_TIME_UNTIL_EXIT_OFFLINE_IN_MILLISECONDS) { - self.isLocal = false; self.monitorOfflineIdle(false); + Oobe.resetSigninUI(true); } }, IDLE_TIME_CHECK_FREQUENCY); }
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/css/wallpaper_manager.css b/chrome/browser/resources/chromeos/wallpaper_manager/css/wallpaper_manager.css index 391ea71..c38868a 100644 --- a/chrome/browser/resources/chromeos/wallpaper_manager/css/wallpaper_manager.css +++ b/chrome/browser/resources/chromeos/wallpaper_manager/css/wallpaper_manager.css
@@ -143,7 +143,7 @@ #wallpaper-set-by-message { -webkit-padding-end: 5px; -webkit-padding-start: 15px; - height: 17px; + height: 30px; } #wallpaper-set-by-message:empty { @@ -170,6 +170,10 @@ display: block; } +.image-picker.small { + height: 275px; +} + .image-picker > * { display: inline-block; margin: 0; @@ -242,7 +246,6 @@ -webkit-box-orient: horizontal; -webkit-box-pack: end; display: -webkit-box; - height: 40px; padding: 11px 15px 8px 15px; }
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js b/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js index 759b33b7..ea66985 100644 --- a/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js +++ b/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js
@@ -288,6 +288,9 @@ if (loadTimeData.valueExists('wallpaperAppName')) { $('wallpaper-set-by-message').textContent = loadTimeData.getStringF( 'currentWallpaperSetByMessage', str('wallpaperAppName')); + $('wallpaper-grid').classList.add('small'); + } else { + $('wallpaper-grid').classList.remove('small'); } if (this.enableOnlineWallpaper_) { @@ -547,6 +550,7 @@ this.currentWallpaper_ = currentWallpaperURL; // Hides the wallpaper set by message. $('wallpaper-set-by-message').textContent = ''; + $('wallpaper-grid').classList.remove('small'); }; /**
diff --git a/chrome/browser/resources/md_downloads/item.html b/chrome/browser/resources/md_downloads/item.html index 91fbd4f..7837490 100644 --- a/chrome/browser/resources/md_downloads/item.html +++ b/chrome/browser/resources/md_downloads/item.html
@@ -98,7 +98,7 @@ <paper-button id="danger-remove" on-tap="onDiscardDangerousTap_" class="discard">[[i18n_.remove]]</paper-button> <paper-button id="restore" on-tap="onSaveDangerousTap_" - class="keep">[[i18n_.restore]</paper-button> + class="keep">[[i18n_.restore]]</paper-button> </template> </div> </template>
diff --git a/chrome/browser/resources/md_downloads/toolbar.css b/chrome/browser/resources/md_downloads/toolbar.css index a05f66b..ba94b688 100644 --- a/chrome/browser/resources/md_downloads/toolbar.css +++ b/chrome/browser/resources/md_downloads/toolbar.css
@@ -8,7 +8,7 @@ color: white; content-sizing: padding-box; display: flex; - height: 56px; + min-height: 56px; } #title h1 {
diff --git a/chrome/browser/resources/md_downloads/vulcanized.html b/chrome/browser/resources/md_downloads/vulcanized.html index be7dbe1..3257c473 100644 --- a/chrome/browser/resources/md_downloads/vulcanized.html +++ b/chrome/browser/resources/md_downloads/vulcanized.html
@@ -2491,7 +2491,7 @@ <template is="dom-if" if="[[isMalware_]]"> <paper-button id="danger-remove" on-tap="onDiscardDangerousTap_" class="discard">[[i18n_.remove]]</paper-button> - <paper-button id="restore" on-tap="onSaveDangerousTap_" class="keep">[[i18n_.restore]</paper-button> + <paper-button id="restore" on-tap="onSaveDangerousTap_" class="keep">[[i18n_.restore]]</paper-button> </template> </div> </template> @@ -3362,7 +3362,7 @@ color: white; content-sizing: padding-box; display: flex; - height: 56px; + min-height: 56px; } #title h1 {
diff --git a/chrome/browser/resources/md_extensions/compiled_resources.gyp b/chrome/browser/resources/md_extensions/compiled_resources.gyp index d947ed44..50f7a41f 100644 --- a/chrome/browser/resources/md_extensions/compiled_resources.gyp +++ b/chrome/browser/resources/md_extensions/compiled_resources.gyp
@@ -13,11 +13,15 @@ '../../../../ui/webui/resources/js/cr.js', '../../../../ui/webui/resources/js/i18n_behavior.js', 'item.js', + 'manager.js', + 'service.js', + 'sidebar.js', 'toolbar.js', ], 'externs': [ '<(EXTERNS_DIR)/chrome_send.js', '<(EXTERNS_DIR)/developer_private.js', + '<(EXTERNS_DIR)/management.js', ], }, 'includes': ['../../../../third_party/closure_compiler/compile_js.gypi'],
diff --git a/chrome/browser/resources/md_extensions/item.js b/chrome/browser/resources/md_extensions/item.js index b2d00abf6..df6e718 100644 --- a/chrome/browser/resources/md_extensions/item.js +++ b/chrome/browser/resources/md_extensions/item.js
@@ -7,9 +7,7 @@ var ItemDelegate = function() {}; ItemDelegate.prototype = { - /** - * @param {string} id - */ + /** @param {string} id */ deleteItem: assertNotReached, /** @@ -18,9 +16,7 @@ */ setItemEnabled: assertNotReached, - /** - * @param {string} id - */ + /** @param {string} id */ showItemDetails: assertNotReached, /** @@ -28,6 +24,9 @@ * @param {boolean} isAllowedIncognito */ setItemAllowedIncognito: assertNotReached, + + /** @return {boolean} */ + isInDevMode: assertNotReached, }; var Item = Polymer({ @@ -73,7 +72,9 @@ */ factoryImpl: function(data, delegate) { this.data = data; + this.id = data.id; this.delegate_ = delegate; + this.inDevMode = delegate.isInDevMode(); }, /** @private */
diff --git a/chrome/browser/resources/md_extensions/manager.css b/chrome/browser/resources/md_extensions/manager.css index 3890cde..418fe5f 100644 --- a/chrome/browser/resources/md_extensions/manager.css +++ b/chrome/browser/resources/md_extensions/manager.css
@@ -15,3 +15,8 @@ #item-list { -webkit-margin-start: 250px; } + +extensions-item { + display: inline-block; + margin-top: 20px; +}
diff --git a/chrome/browser/resources/md_extensions/manager.html b/chrome/browser/resources/md_extensions/manager.html index 4a8c1ddc..c991723 100644 --- a/chrome/browser/resources/md_extensions/manager.html +++ b/chrome/browser/resources/md_extensions/manager.html
@@ -2,6 +2,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-header-panel/paper-header-panel.html"> <link rel="import" href="chrome://extensions/item.html"> +<link rel="import" href="chrome://extensions/service.html"> <link rel="import" href="chrome://extensions/sidebar.html"> <link rel="import" href="chrome://extensions/toolbar.html">
diff --git a/chrome/browser/resources/md_extensions/manager.js b/chrome/browser/resources/md_extensions/manager.js index 729ee73..3ff4a3b 100644 --- a/chrome/browser/resources/md_extensions/manager.js +++ b/chrome/browser/resources/md_extensions/manager.js
@@ -4,7 +4,60 @@ cr.define('extensions', function() { var Manager = Polymer({ - is: 'extensions-manager' + is: 'extensions-manager', + + properties: { + sidebar: { + type: Object, + } + }, + + ready: function() { + this.sidebar = this.$$('extensions-sidebar'); + extensions.Service.getInstance().managerReady(this); + }, + + /** + * Creates and adds a new extensions-item element to the list. + * @param {!chrome.developerPrivate.ExtensionInfo} extension The extension + * the item is representing. + * @param {!extensions.ItemDelegate} delegate The delegate for the item. + * @param {!number=} opt_index The index at which to place the item. If + * not present, the item is appended to the end of the list. + */ + addItem: function(extension, delegate, opt_index) { + var extensionItem = new extensions.Item(extension, delegate); + var itemList = this.$['item-list']; + var refNode = opt_index !== undefined ? + itemList.children[opt_index] : undefined; + itemList.insertBefore(extensionItem, refNode); + }, + + /** + * @param {string} id The id of the extension to get the item for. + * @return {?extensions.Item} + */ + getItem: function(id) { + return this.$$('#' + id); + }, + + /** @param {string} id The id of the item to remove. */ + removeItem: function(id) { + var item = this.getItem(id); + if (item) + item.parentNode.removeChild(item); + }, + + /** + * Applies a function to each item present in the DOM. + * @param {!function(extensions.Item):void} callback The function to apply. + */ + forEachItem: function(callback) { + Array.prototype.forEach.call( + /** @type {Array<extensions.Item>} */( + Polymer.dom(this.root).querySelectorAll('extensions-item')), + callback); + }, }); return {Manager: Manager};
diff --git a/chrome/browser/resources/md_extensions/service.html b/chrome/browser/resources/md_extensions/service.html new file mode 100644 index 0000000..fe1be3f --- /dev/null +++ b/chrome/browser/resources/md_extensions/service.html
@@ -0,0 +1,5 @@ +<link rel="import" href="chrome://resources/html/assert.html"> +<link rel="import" href="chrome://resources/html/cr.html"> +<link rel="import" href="chrome://extensions/service.html"> +<link rel="import" href="chrome://extensions/item.html"> +<script src="chrome://extensions/service.js"></script>
diff --git a/chrome/browser/resources/md_extensions/service.js b/chrome/browser/resources/md_extensions/service.js new file mode 100644 index 0000000..368c41d4 --- /dev/null +++ b/chrome/browser/resources/md_extensions/service.js
@@ -0,0 +1,175 @@ +// Copyright 2015 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. + +cr.define('extensions', function() { + 'use strict'; + + /** + * Compares two extensions to determine which should come first in the list. + * @param {chrome.developerPrivate.ExtensionInfo} a + * @param {chrome.developerPrivate.ExtensionInfo} b + * @return {number} + */ + var compareExtensions = function(a, b) { + function compare(x, y) { + return x < y ? -1 : (x > y ? 1 : 0); + } + function compareLocation(x, y) { + if (x.location == y.location) + return 0; + if (x.location == chrome.developerPrivate.Location.UNPACKED) + return -1; + if (y.location == chrome.developerPrivate.Location.UNPACKED) + return 1; + return 0; + } + return compareLocation(a, b) || + compare(a.name.toLowerCase(), b.name.toLowerCase()) || + compare(a.id, b.id); + }; + + /** + * @constructor + * @implements {extensions.ItemDelegate} + * @implements {extensions.SidebarDelegate} + */ + function Service() {} + + Service.prototype = { + /** @private {boolean} */ + promptIsShowing_: false, + + /** @param {extensions.Manager} manager */ + managerReady: function(manager) { + this.manager_ = manager; + this.sidebar_ = manager.sidebar; + this.sidebar_.setDelegate(this); + chrome.developerPrivate.onProfileStateChanged.addListener( + this.onProfileStateChanged_.bind(this)); + chrome.developerPrivate.onItemStateChanged.addListener( + this.onItemStateChanged_.bind(this)); + chrome.developerPrivate.getExtensionsInfo( + {includeDisabled: true, includeTerminated: true}, + function(extensions) { + extensions.sort(compareExtensions); + this.extensions_ = extensions; + for (let extension of extensions) + this.manager_.addItem(extension, this); + }.bind(this)); + chrome.developerPrivate.getProfileConfiguration( + this.onProfileStateChanged_.bind(this)); + }, + + /** + * @param {chrome.developerPrivate.ProfileInfo} profileInfo + * @private + */ + onProfileStateChanged_: function(profileInfo) { + this.profileInfo_ = profileInfo; + this.sidebar_.inDevMode = profileInfo.inDeveloperMode; + this.manager_.forEachItem(function(item) { + item.inDevMode = profileInfo.inDeveloperMode; + }); + }, + + /** + * @param {chrome.developerPrivate.EventData} eventData + * @private + */ + onItemStateChanged_: function(eventData) { + var EventType = chrome.developerPrivate.EventType; + switch (eventData.event_type) { + case EventType.VIEW_REGISTERED: + case EventType.VIEW_UNREGISTERED: + case EventType.INSTALLED: + case EventType.LOADED: + case EventType.UNLOADED: + case EventType.ERROR_ADDED: + case EventType.ERRORS_REMOVED: + case EventType.PREFS_CHANGED: + // |extensionInfo| can be undefined in the case of an extension + // being unloaded right before uninstallation. There's nothing to do + // here. + if (!eventData.extensionInfo) + break; + + var existing = this.manager_.getItem(eventData.extensionInfo.id); + if (existing) { + existing.data = eventData.extensionInfo; + } else { + // If there's no existing item in the list, there shouldn't be an + // extension with the same id in the data. + var currentIndex = this.extensions_.findIndex(function(extension) { + return extension.id == eventData.extensionInfo.id; + }); + assert(currentIndex == -1); + var newIndex = this.extensions_.findIndex(function(extension) { + return compareExtensions(extension, + assert(eventData.extensionInfo)) > 0; + }); + newIndex = newIndex == -1 ? this.extensions_.length : newIndex; + this.extensions_.splice(newIndex, 0, eventData.extensionInfo); + this.manager_.addItem(eventData.extensionInfo, this, newIndex); + } + break; + case EventType.UNINSTALLED: + var currentIndex = this.extensions_.findIndex(function(extension) { + return extension.id == eventData.item_id; + }); + this.extensions_.splice(currentIndex, 1); + this.manager_.removeItem(eventData.item_id); + break; + default: + assertNotReached(); + } + }, + + /** @override */ + deleteItem: function(id) { + if (this.promptIsShowing_) + return; + this.promptIsShowing_ = true; + chrome.management.uninstall(id, {showConfirmDialog: true}, function() { + // The "last error" was almost certainly the user canceling the dialog. + // Do nothing. We only check it so we don't get noisy logs. + /** @suppress {suspiciousCode} */ + chrome.runtime.lastError; + this.promptIsShowing_ = false; + }.bind(this)); + }, + + /** @override */ + setItemEnabled: function(id, isEnabled) { + chrome.management.setEnabled(id, isEnabled); + }, + + /** @override */ + showItemDetails: function(id) {}, + + /** @override */ + setItemAllowedIncognito: function(id, isAllowedIncognito) { + chrome.developerPrivate.updateExtensionConfiguration({ + extensionId: id, + incognitoAccess: isAllowedIncognito, + }); + }, + + /** @override */ + isInDevMode: function() { + // It's possible this could be called before the profileInfo is + // initialized; that's fine, because we'll update the items when it is. + return !!this.profileInfo_ && this.profileInfo_.inDeveloperMode; + }, + + /** @override */ + setProfileInDevMode: function(inDevMode) { + chrome.developerPrivate.updateProfileConfiguration( + {inDeveloperMode: inDevMode}); + }, + }; + + cr.addSingletonGetter(Service); + + return {Service: Service}; +});
diff --git a/chrome/browser/resources/md_extensions/sidebar.html b/chrome/browser/resources/md_extensions/sidebar.html index 9bb9b02..765eaa7 100644 --- a/chrome/browser/resources/md_extensions/sidebar.html +++ b/chrome/browser/resources/md_extensions/sidebar.html
@@ -22,7 +22,9 @@ </paper-menu> <paper-item id="developer-mode"> <span i18n-content="developerMode"></span> - <paper-checkbox id="developer-mode-checkbox"></paper-checkbox> + <paper-checkbox id="developer-mode-checkbox" + checked="[[inDevMode]]" + on-change="onDevModeChange_"></paper-checkbox> </paper-item> <paper-item id="more-extensions" i18n-content="getMoreExtensions"> </paper-item>
diff --git a/chrome/browser/resources/md_extensions/sidebar.js b/chrome/browser/resources/md_extensions/sidebar.js index 10dfdf6..45bb7d3 100644 --- a/chrome/browser/resources/md_extensions/sidebar.js +++ b/chrome/browser/resources/md_extensions/sidebar.js
@@ -3,10 +3,41 @@ // found in the LICENSE file. cr.define('extensions', function() { + /** @interface */ + var SidebarDelegate = function() {}; + + SidebarDelegate.prototype = { + /** + * Toggles whether or not the profile is in developer mode. + * @param {boolean} inDevMode + */ + setProfileInDevMode: assertNotReached, + }; + var Sidebar = Polymer({ is: 'extensions-sidebar', + + properties: { + inDevMode: { + type: Boolean, + value: false, + }, + }, + + /** @param {extensions.SidebarDelegate} delegate */ + setDelegate: function(delegate) { + this.delegate_ = delegate; + }, + + onDevModeChange_: function() { + this.delegate_.setProfileInDevMode( + this.$['developer-mode-checkbox'].checked); + }, }); - return {Sidebar: Sidebar}; + return { + Sidebar: Sidebar, + SidebarDelegate: SidebarDelegate, + }; });
diff --git a/chrome/browser/resources/options/clear_browser_data_overlay.css b/chrome/browser/resources/options/clear_browser_data_overlay.css index 100ddb2e..fabf1f2 100644 --- a/chrome/browser/resources/options/clear_browser_data_overlay.css +++ b/chrome/browser/resources/options/clear_browser_data_overlay.css
@@ -36,6 +36,10 @@ color: #999; } +.clear-browser-data-counter::before { + content: '–\00a0\00a0'; +} + input[type=checkbox]:not(:checked) ~ .clear-browser-data-counter { display: none; }
diff --git a/chrome/browser/resources/options/password_manager_list.js b/chrome/browser/resources/options/password_manager_list.js index c4af28d4..85cf0aef 100644 --- a/chrome/browser/resources/options/password_manager_list.js +++ b/chrome/browser/resources/options/password_manager_list.js
@@ -75,6 +75,7 @@ 'title', getTitleForPasswordOrigin(this.url, this.isUrlSecure)); var urlLink = this.ownerDocument.createElement('a'); urlLink.href = this.url; + urlLink.setAttribute('target', '_blank'); urlLink.textContent = this.shownUrl.split('').reverse().join(''); urlDiv.appendChild(urlLink); urlDiv.style.backgroundImage = getFaviconImageSet( @@ -323,6 +324,7 @@ var urlLink = this.ownerDocument.createElement('a'); urlLink.href = this.url; urlLink.textContent = this.shownUrl.split('').reverse().join(''); + urlLink.setAttribute('target', '_blank'); urlDiv.appendChild(urlLink); urlDiv.style.backgroundImage = getFaviconImageSet( 'origin/' + this.url, 16);
diff --git a/chrome/browser/resources/print_preview/native_layer.js b/chrome/browser/resources/print_preview/native_layer.js index 98a61fc0..7bda60e 100644 --- a/chrome/browser/resources/print_preview/native_layer.js +++ b/chrome/browser/resources/print_preview/native_layer.js
@@ -67,8 +67,8 @@ this.onEnableManipulateSettingsForTest_.bind(this); global.printPresetOptionsFromDocument = this.onPrintPresetOptionsFromDocument_.bind(this); - global.detectDistillablePage = - this.detectDistillablePage_.bind(this); + global.allowDistillPage = + this.allowDistillPage_.bind(this); global.onProvisionalPrinterResolved = this.onProvisionalDestinationResolved_.bind(this); global.failedToResolveProvisionalPrinter = @@ -742,13 +742,10 @@ }, /** - * Updates the interface to show the "Distill Page" option - * when PrintPreviewHandler::HandleIsPageDistillableResult - * determines that this page can be distilled with the - * DOM Distiller. + * Updates the interface to show the "Simplify Page" option. * @private */ - detectDistillablePage_: function() { + allowDistillPage_: function() { var allowDistillPageEvent = new Event( NativeLayer.EventType.ALLOW_DISTILL_PAGE); this.dispatchEvent(allowDistillPageEvent);
diff --git a/chrome/browser/resources/settings/advanced_page/advanced_page.html b/chrome/browser/resources/settings/advanced_page/advanced_page.html index a0f438c2..dffffdb 100644 --- a/chrome/browser/resources/settings/advanced_page/advanced_page.html +++ b/chrome/browser/resources/settings/advanced_page/advanced_page.html
@@ -27,7 +27,7 @@ <site-settings-category id="locationCategory" prefs="{{prefs}}" current-route="{{currentRoute}}"> </site-settings-category> - </cr-settings-section> + </settings-section> <settings-section i18n-values="page-title:privacyPageTitle" current-route="[[currentRoute]]" section="privacy">
diff --git a/chrome/browser/safe_browsing/database_manager.h b/chrome/browser/safe_browsing/database_manager.h index cc0840b8..8a438c7 100644 --- a/chrome/browser/safe_browsing/database_manager.h +++ b/chrome/browser/safe_browsing/database_manager.h
@@ -15,7 +15,7 @@ #include <vector> #include "base/memory/ref_counted.h" -#include "chrome/browser/safe_browsing/safe_browsing_util.h" +#include "components/safe_browsing_db/util.h" #include "content/public/common/resource_type.h" #include "url/gurl.h"
diff --git a/chrome/browser/safe_browsing/download_protection_service.cc b/chrome/browser/safe_browsing/download_protection_service.cc index 82f9eac..6e04dce 100644 --- a/chrome/browser/safe_browsing/download_protection_service.cc +++ b/chrome/browser/safe_browsing/download_protection_service.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/safe_browsing/download_protection_service.h" #include "base/bind.h" +#include "base/command_line.h" #include "base/compiler_specific.h" #include "base/format_macros.h" #include "base/memory/scoped_ptr.h" @@ -16,6 +17,7 @@ #include "base/sequenced_task_runner_helpers.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/task/cancelable_task_tracker.h" @@ -30,6 +32,7 @@ #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" @@ -70,18 +73,16 @@ namespace { void RecordFileExtensionType(const base::FilePath& file) { - UMA_HISTOGRAM_ENUMERATION( + UMA_HISTOGRAM_SPARSE_SLOWLY( "SBClientDownload.DownloadExtensions", - download_protection_util::GetSBClientDownloadExtensionValueForUMA(file), - download_protection_util::kSBClientDownloadExtensionsMax); + download_protection_util::GetSBClientDownloadExtensionValueForUMA(file)); } void RecordArchivedArchiveFileExtensionType(const base::FilePath& file_name) { - UMA_HISTOGRAM_ENUMERATION( + UMA_HISTOGRAM_SPARSE_SLOWLY( "SBClientDownload.ArchivedArchiveExtensions", download_protection_util::GetSBClientDownloadExtensionValueForUMA( - file_name), - download_protection_util::kSBClientDownloadExtensionsMax); + file_name)); } // Enumerate for histogramming purposes. @@ -672,6 +673,15 @@ // the server if we're not on one of those platforms. // TODO(noelutz): change this code once the UI is done for Linux. #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS) + // User can manually blacklist a sha256 via flag, for testing. + // In this case we don't actually send the request. + if (item_ && service_ && + service_->IsHashManuallyBlacklisted(item_->GetHash())) { + DVLOG(1) << "Download verdict overridden to DANGEROUS by flag."; + PostFinishTask(DANGEROUS, REASON_MANUAL_BLACKLIST); + return; + } + // The URLFetcher is owned by the UI thread, so post a message to // start the pingback. BrowserThread::PostTask( @@ -837,6 +847,7 @@ return; } finished_ = true; + // Ensure the timeout task is cancelled while we still have a non-zero // refcount. (crbug.com/240449) weakptr_factory_.InvalidateWeakPtrs(); @@ -970,6 +981,7 @@ if (sb_service) { ui_manager_ = sb_service->ui_manager(); database_manager_ = sb_service->database_manager(); + ParseManualBlacklistFlag(); } } @@ -989,6 +1001,31 @@ } } +void DownloadProtectionService::ParseManualBlacklistFlag() { + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (!command_line->HasSwitch(switches::kSbManualDownloadBlacklist)) + return; + + std::string flag_val = + command_line->GetSwitchValueASCII(switches::kSbManualDownloadBlacklist); + for (const std::string& hash_hex : base::SplitString( + flag_val, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { + std::vector<uint8> bytes; + if (base::HexStringToBytes(hash_hex, &bytes) && bytes.size() == 32) { + manual_blacklist_hashes_.insert( + std::string(bytes.begin(), bytes.end())); + } else { + LOG(FATAL) << "Bad sha256 hex value '" << hash_hex << "' found in --" + << switches::kSbManualDownloadBlacklist; + } + } +} + +bool DownloadProtectionService::IsHashManuallyBlacklisted( + const std::string& sha256_hash) const { + return manual_blacklist_hashes_.count(sha256_hash) > 0; +} + void DownloadProtectionService::CheckClientDownload( content::DownloadItem* item, const CheckDownloadCallback& callback) {
diff --git a/chrome/browser/safe_browsing/download_protection_service.h b/chrome/browser/safe_browsing/download_protection_service.h index c208c72c..d1c7310 100644 --- a/chrome/browser/safe_browsing/download_protection_service.h +++ b/chrome/browser/safe_browsing/download_protection_service.h
@@ -80,6 +80,13 @@ virtual ~DownloadProtectionService(); + // Parse a flag of blacklisted sha256 hashes to check at each download. + // This is used for testing, to hunt for safe-browsing by-pass bugs. + virtual void ParseManualBlacklistFlag(); + + // Return true if this hash value is blacklisted via flag (for testing). + virtual bool IsHashManuallyBlacklisted(const std::string& sha256_hash) const; + // Checks whether the given client download is likely to be malicious or not. // The result is delivered asynchronously via the given callback. This // method must be called on the UI thread, and the callback will also be @@ -158,12 +165,14 @@ REASON_DOWNLOAD_DANGEROUS_HOST, REASON_DOWNLOAD_POTENTIALLY_UNWANTED, REASON_UNSUPPORTED_URL_SCHEME, + REASON_MANUAL_BLACKLIST, REASON_MAX // Always add new values before this one. }; private: class CheckClientDownloadRequest; // Per-request state friend class DownloadProtectionServiceTest; + FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest, CheckClientDownloadWhitelistedUrl); FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest, @@ -184,6 +193,9 @@ TestDownloadRequestTimeout); FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest, CheckClientCrxDownloadSuccess); + FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceFlagTest, + CheckClientDownloadOverridenByFlag); + static const char kDownloadRequestUrl[]; // Cancels all requests in |download_requests_|, and empties it, releasing @@ -231,6 +243,10 @@ // ClientDownloadRequest has been formed. ClientDownloadRequestCallbackList client_download_request_callbacks_; + // List of 8-byte hashes that are blacklisted manually by flag. + // Normally empty. + std::set<std::string> manual_blacklist_hashes_; + DISALLOW_COPY_AND_ASSIGN(DownloadProtectionService); }; } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/download_protection_service_unittest.cc b/chrome/browser/safe_browsing/download_protection_service_unittest.cc index 33fcc41..cbe556e 100644 --- a/chrome/browser/safe_browsing/download_protection_service_unittest.cc +++ b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
@@ -11,6 +11,7 @@ #include "base/base_paths.h" #include "base/bind.h" #include "base/callback.h" +#include "base/command_line.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -28,6 +29,7 @@ #include "chrome/browser/safe_browsing/local_database_manager.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/safe_browsing/test_database_manager.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/test/base/testing_profile.h" @@ -202,7 +204,7 @@ arg0, std::vector<SBFullHash>(), arg1, - safe_browsing_util::BINURL, + safe_browsing::BINURL, std::vector<SBThreatType>(1, SB_THREAT_TYPE_BINARY_MALWARE_URL)); for (size_t i = 0; i < check->url_results.size(); ++i) check->url_results[i] = threat_type; @@ -423,12 +425,14 @@ base::FilePath a_exe(FILE_PATH_LITERAL("a.exe")); std::vector<GURL> url_chain; GURL referrer("http://www.google.com/"); + std::string hash = "hash"; content::MockDownloadItem item; EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp)); EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe)); EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); + EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); EXPECT_CALL(item, GetTabReferrerUrl()) .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); @@ -446,6 +450,7 @@ EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe)); EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); + EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); EXPECT_CALL(item, GetTabReferrerUrl()) .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); @@ -463,6 +468,7 @@ base::FilePath a_txt(FILE_PATH_LITERAL("a.txt")); std::vector<GURL> url_chain; GURL referrer("http://www.google.com/"); + std::string hash = "hash"; content::MockDownloadItem item; url_chain.push_back(GURL("http://www.example.com/foo")); @@ -470,6 +476,7 @@ EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_txt)); EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); + EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); EXPECT_CALL(item, GetTabReferrerUrl()) .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); @@ -1958,4 +1965,76 @@ &mock_page_navigator); } +// ------------ class DownloadProtectionServiceFlagTest ---------------- +class DownloadProtectionServiceFlagTest : public DownloadProtectionServiceTest { + protected: + DownloadProtectionServiceFlagTest() + : blacklisted_hash_("abcdefghijklmnopqrstuvwxyz012345") {} + + void SetUp() override { + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + switches::kSbManualDownloadBlacklist, + base::HexEncode(blacklisted_hash_.c_str(), blacklisted_hash_.size())); + DownloadProtectionServiceTest::SetUp(); + } + + // Binary 32 bytes + const std::string blacklisted_hash_; +}; + +TEST_F(DownloadProtectionServiceFlagTest, CheckClientDownloadOverridenByFlag) { + ClientDownloadResponse response; + response.set_verdict(ClientDownloadResponse::SAFE); + net::FakeURLFetcherFactory factory(NULL); + // Empty response means SAFE. + factory.SetFakeResponse( + DownloadProtectionService::GetDownloadRequestUrl(), + response.SerializeAsString(), + net::HTTP_OK, net::URLRequestStatus::SUCCESS); + + base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp")); + base::FilePath a_exe(FILE_PATH_LITERAL("a.exe")); + std::vector<GURL> url_chain; + url_chain.push_back(GURL("http://www.evil.com/a.exe")); + GURL referrer("http://www.google.com/"); + + content::MockDownloadItem item; + EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp)); + EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe)); + EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); + EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); + EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); + EXPECT_CALL(item, GetTabReferrerUrl()) + .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); + EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(blacklisted_hash_)); + EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100)); + EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true)); + EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return("")); + + EXPECT_CALL(*sb_service_->mock_database_manager(), + MatchDownloadWhitelistUrl(_)) + .WillRepeatedly(Return(false)); + EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _)); + EXPECT_CALL(*binary_feature_extractor_.get(), + ExtractImageFeatures( + a_tmp, BinaryFeatureExtractor::kDefaultOptions, _, _)); + + download_service_->CheckClientDownload( + &item, + base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, + base::Unretained(this))); + MessageLoop::current()->Run(); + + EXPECT_FALSE(HasClientDownloadRequest()); +#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS) + // Overriden by flag: + EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS)); +#else + // On !(OS_WIN || OS_MACOSX || OS_CHROMEOS), + // no file types are currently supported. Hence all + // requests to CheckClientDownload() result in a verdict of UNKNOWN. + EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN)); +#endif +} + } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/local_database_manager.cc b/chrome/browser/safe_browsing/local_database_manager.cc index f50e0989..9f23af35 100644 --- a/chrome/browser/safe_browsing/local_database_manager.cc +++ b/chrome/browser/safe_browsing/local_database_manager.cc
@@ -32,6 +32,7 @@ #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" +#include "components/safe_browsing_db/util.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h" #include "url/url_constants.h" @@ -47,7 +48,7 @@ // |true| if there were any prefix hits in |full_hashes|. void RecordGetHashCheckStatus( bool hit, - safe_browsing_util::ListType check_type, + safe_browsing::ListType check_type, const std::vector<SBFullHashResult>& full_hashes) { SafeBrowsingProtocolManager::ResultType result; if (full_hashes.empty()) { @@ -57,7 +58,7 @@ } else { result = SafeBrowsingProtocolManager::GET_HASH_FULL_HASH_MISS; } - bool is_download = check_type == safe_browsing_util::BINURL; + bool is_download = check_type == safe_browsing::BINURL; SafeBrowsingProtocolManager::RecordGetHashResult(is_download, result); } @@ -71,32 +72,32 @@ // Return the severest list id from the results in |full_hashes| which matches // |hash|, or INVALID if none match. -safe_browsing_util::ListType GetHashSeverestThreatListType( +safe_browsing::ListType GetHashSeverestThreatListType( const SBFullHash& hash, const std::vector<SBFullHashResult>& full_hashes, size_t* index) { - safe_browsing_util::ListType pending_threat = safe_browsing_util::INVALID; + safe_browsing::ListType pending_threat = safe_browsing::INVALID; for (size_t i = 0; i < full_hashes.size(); ++i) { - if (SBFullHashEqual(hash, full_hashes[i].hash)) { - const safe_browsing_util::ListType threat = - static_cast<safe_browsing_util::ListType>(full_hashes[i].list_id); + if (safe_browsing::SBFullHashEqual(hash, full_hashes[i].hash)) { + const safe_browsing::ListType threat = + static_cast<safe_browsing::ListType>(full_hashes[i].list_id); switch (threat) { - case safe_browsing_util::INVALID: + case safe_browsing::INVALID: // |full_hashes| should never contain INVALID as a |list_id|. NOTREACHED(); break; - case safe_browsing_util::MALWARE: // Falls through. - case safe_browsing_util::PHISH: // Falls through. - case safe_browsing_util::BINURL: // Falls through. - case safe_browsing_util::CSDWHITELIST: // Falls through. - case safe_browsing_util::DOWNLOADWHITELIST: // Falls through. - case safe_browsing_util::INCLUSIONWHITELIST: // Falls through. - case safe_browsing_util::EXTENSIONBLACKLIST: // Falls through. - case safe_browsing_util::IPBLACKLIST: + case safe_browsing::MALWARE: // Falls through. + case safe_browsing::PHISH: // Falls through. + case safe_browsing::BINURL: // Falls through. + case safe_browsing::CSDWHITELIST: // Falls through. + case safe_browsing::DOWNLOADWHITELIST: // Falls through. + case safe_browsing::INCLUSIONWHITELIST: // Falls through. + case safe_browsing::EXTENSIONBLACKLIST: // Falls through. + case safe_browsing::IPBLACKLIST: if (index) *index = i; return threat; - case safe_browsing_util::UNWANTEDURL: + case safe_browsing::UNWANTEDURL: // UNWANTEDURL is considered less severe than other threats, keep // looking. pending_threat = threat; @@ -112,34 +113,34 @@ // Given a URL, compare all the possible host + path full hashes to the set of // provided full hashes. Returns the list id of the severest matching result // from |full_hashes|, or INVALID if none match. -safe_browsing_util::ListType GetUrlSeverestThreatListType( +safe_browsing::ListType GetUrlSeverestThreatListType( const GURL& url, const std::vector<SBFullHashResult>& full_hashes, size_t* index) { if (full_hashes.empty()) - return safe_browsing_util::INVALID; + return safe_browsing::INVALID; std::vector<std::string> patterns; - safe_browsing_util::GeneratePatternsToCheck(url, &patterns); + safe_browsing::GeneratePatternsToCheck(url, &patterns); - safe_browsing_util::ListType pending_threat = safe_browsing_util::INVALID; + safe_browsing::ListType pending_threat = safe_browsing::INVALID; for (size_t i = 0; i < patterns.size(); ++i) { - safe_browsing_util::ListType threat = GetHashSeverestThreatListType( - SBFullHashForString(patterns[i]), full_hashes, index); + safe_browsing::ListType threat = GetHashSeverestThreatListType( + safe_browsing::SBFullHashForString(patterns[i]), full_hashes, index); switch (threat) { - case safe_browsing_util::INVALID: + case safe_browsing::INVALID: // Ignore patterns with no matching threat. break; - case safe_browsing_util::MALWARE: // Falls through. - case safe_browsing_util::PHISH: // Falls through. - case safe_browsing_util::BINURL: // Falls through. - case safe_browsing_util::CSDWHITELIST: // Falls through. - case safe_browsing_util::DOWNLOADWHITELIST: // Falls through. - case safe_browsing_util::INCLUSIONWHITELIST: // Falls through. - case safe_browsing_util::EXTENSIONBLACKLIST: // Falls through. - case safe_browsing_util::IPBLACKLIST: + case safe_browsing::MALWARE: // Falls through. + case safe_browsing::PHISH: // Falls through. + case safe_browsing::BINURL: // Falls through. + case safe_browsing::CSDWHITELIST: // Falls through. + case safe_browsing::DOWNLOADWHITELIST: // Falls through. + case safe_browsing::INCLUSIONWHITELIST: // Falls through. + case safe_browsing::EXTENSIONBLACKLIST: // Falls through. + case safe_browsing::IPBLACKLIST: return threat; - case safe_browsing_util::UNWANTEDURL: + case safe_browsing::UNWANTEDURL: // UNWANTEDURL is considered less severe than other threats, keep // looking. pending_threat = threat; @@ -149,17 +150,17 @@ return pending_threat; } -SBThreatType GetThreatTypeFromListType(safe_browsing_util::ListType list_type) { +SBThreatType GetThreatTypeFromListType(safe_browsing::ListType list_type) { switch (list_type) { - case safe_browsing_util::PHISH: + case safe_browsing::PHISH: return SB_THREAT_TYPE_URL_PHISHING; - case safe_browsing_util::MALWARE: + case safe_browsing::MALWARE: return SB_THREAT_TYPE_URL_MALWARE; - case safe_browsing_util::UNWANTEDURL: + case safe_browsing::UNWANTEDURL: return SB_THREAT_TYPE_URL_UNWANTED; - case safe_browsing_util::BINURL: + case safe_browsing::BINURL: return SB_THREAT_TYPE_BINARY_MALWARE_URL; - case safe_browsing_util::EXTENSIONBLACKLIST: + case safe_browsing::EXTENSIONBLACKLIST: return SB_THREAT_TYPE_EXTENSION; default: DVLOG(1) << "Unknown safe browsing list id " << list_type; @@ -190,7 +191,7 @@ const std::vector<GURL>& urls, const std::vector<SBFullHash>& full_hashes, Client* client, - safe_browsing_util::ListType check_type, + safe_browsing::ListType check_type, const std::vector<SBThreatType>& expected_threats) : urls(urls), url_results(urls.size(), SB_THREAT_TYPE_SAFE), @@ -218,14 +219,14 @@ if (!urls.empty()) { DCHECK(full_hashes.empty()); switch (check_type) { - case safe_browsing_util::MALWARE: - case safe_browsing_util::PHISH: - case safe_browsing_util::UNWANTEDURL: + case safe_browsing::MALWARE: + case safe_browsing::PHISH: + case safe_browsing::UNWANTEDURL: DCHECK_EQ(1u, urls.size()); client->OnCheckBrowseUrlResult(urls[0], url_results[0], url_metadata[0]); break; - case safe_browsing_util::BINURL: + case safe_browsing::BINURL: DCHECK_EQ(urls.size(), url_results.size()); client->OnCheckDownloadUrlResult( urls, *std::max_element(url_results.begin(), url_results.end())); @@ -235,11 +236,11 @@ } } else if (!full_hashes.empty()) { switch (check_type) { - case safe_browsing_util::EXTENSIONBLACKLIST: { + case safe_browsing::EXTENSIONBLACKLIST: { std::set<std::string> unsafe_extension_ids; for (size_t i = 0; i < full_hashes.size(); ++i) { std::string extension_id = - safe_browsing_util::SBFullHashToString(full_hashes[i]); + safe_browsing::SBFullHashToString(full_hashes[i]); if (full_hash_results[i] == SB_THREAT_TYPE_EXTENSION) unsafe_extension_ids.insert(extension_id); } @@ -338,7 +339,7 @@ new SafeBrowsingCheck(url_chain, std::vector<SBFullHash>(), client, - safe_browsing_util::BINURL, + safe_browsing::BINURL, std::vector<SBThreatType>(1, SB_THREAT_TYPE_BINARY_MALWARE_URL)); std::vector<SBPrefix> prefixes; @@ -361,7 +362,7 @@ std::vector<SBFullHash> extension_id_hashes; std::transform(extension_ids.begin(), extension_ids.end(), std::back_inserter(extension_id_hashes), - safe_browsing_util::StringToSBFullHash); + safe_browsing::StringToSBFullHash); std::vector<SBPrefix> prefixes; for (const SBFullHash& hash : extension_id_hashes) prefixes.push_back(hash.prefix); @@ -370,7 +371,7 @@ std::vector<GURL>(), extension_id_hashes, client, - safe_browsing_util::EXTENSIONBLACKLIST, + safe_browsing::EXTENSIONBLACKLIST, std::vector<SBThreatType>(1, SB_THREAT_TYPE_EXTENSION)); StartSafeBrowsingCheck( check, @@ -458,7 +459,7 @@ const base::TimeTicks start = base::TimeTicks::Now(); if (!MakeDatabaseAvailable()) { - QueuedCheck queued_check(safe_browsing_util::MALWARE, // or PHISH + QueuedCheck queued_check(safe_browsing::MALWARE, // or PHISH client, url, expected_threats, @@ -509,7 +510,7 @@ SafeBrowsingCheck* check = new SafeBrowsingCheck(std::vector<GURL>(1, url), std::vector<SBFullHash>(), client, - safe_browsing_util::MALWARE, + safe_browsing::MALWARE, expected_threats); check->need_get_hash = cache_hits.empty(); check->prefix_hits.swap(prefix_hits); @@ -671,7 +672,7 @@ } LocalSafeBrowsingDatabaseManager::QueuedCheck::QueuedCheck( - const safe_browsing_util::ListType check_type, + const safe_browsing::ListType check_type, Client* client, const GURL& url, const std::vector<SBThreatType>& expected_threats, @@ -871,7 +872,7 @@ if (!enabled_) return; - bool is_download = check->check_type == safe_browsing_util::BINURL; + bool is_download = check->check_type == safe_browsing::BINURL; sb_service_->protocol_manager()->GetFullHash( check->prefix_hits, base::Bind(&LocalSafeBrowsingDatabaseManager::HandleGetHashResults, @@ -1024,7 +1025,7 @@ SafeBrowsingCheck* check, const std::vector<SBFullHashResult>& full_hashes) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - safe_browsing_util::ListType check_type = check->check_type; + safe_browsing::ListType check_type = check->check_type; SBPrefix prefix = check->prefix_hits[0]; GetHashRequests::iterator it = gethash_requests_.find(prefix); if (check->prefix_hits.size() > 1 || it == gethash_requests_.end()) {
diff --git a/chrome/browser/safe_browsing/local_database_manager.h b/chrome/browser/safe_browsing/local_database_manager.h index 509a6041..a848f1a6 100644 --- a/chrome/browser/safe_browsing/local_database_manager.h +++ b/chrome/browser/safe_browsing/local_database_manager.h
@@ -24,7 +24,7 @@ #include "base/time/time.h" #include "chrome/browser/safe_browsing/database_manager.h" #include "chrome/browser/safe_browsing/protocol_manager.h" -#include "chrome/browser/safe_browsing/safe_browsing_util.h" +#include "components/safe_browsing_db/util.h" #include "url/gurl.h" class SafeBrowsingService; @@ -57,7 +57,7 @@ SafeBrowsingCheck(const std::vector<GURL>& urls, const std::vector<SBFullHash>& full_hashes, Client* client, - safe_browsing_util::ListType check_type, + safe_browsing::ListType check_type, const std::vector<SBThreatType>& expected_threats); ~SafeBrowsingCheck(); @@ -74,7 +74,7 @@ bool is_extended_reporting; bool need_get_hash; base::TimeTicks start; // When check was sent to SB service. - safe_browsing_util::ListType check_type; // See comment in constructor. + safe_browsing::ListType check_type; // See comment in constructor. std::vector<SBThreatType> expected_threats; std::vector<SBPrefix> prefix_hits; std::vector<SBFullHashResult> cache_hits; @@ -154,13 +154,13 @@ // Clients that we've queued up for checking later once the database is ready. struct QueuedCheck { - QueuedCheck(const safe_browsing_util::ListType check_type, + QueuedCheck(const safe_browsing::ListType check_type, Client* client, const GURL& url, const std::vector<SBThreatType>& expected_threats, const base::TimeTicks& start); ~QueuedCheck(); - safe_browsing_util::ListType check_type; + safe_browsing::ListType check_type; Client* client; GURL url; std::vector<SBThreatType> expected_threats;
diff --git a/chrome/browser/safe_browsing/local_database_manager_unittest.cc b/chrome/browser/safe_browsing/local_database_manager_unittest.cc index de8dc96..b4bbc30 100644 --- a/chrome/browser/safe_browsing/local_database_manager_unittest.cc +++ b/chrome/browser/safe_browsing/local_database_manager_unittest.cc
@@ -40,7 +40,7 @@ class SafeBrowsingDatabaseManagerTest : public PlatformTest { public: - bool RunSBHashTest(const safe_browsing_util::ListType list_type, + bool RunSBHashTest(const safe_browsing::ListType list_type, const std::vector<SBThreatType>& expected_threats, const std::string& result_list); @@ -49,7 +49,7 @@ }; bool SafeBrowsingDatabaseManagerTest::RunSBHashTest( - const safe_browsing_util::ListType list_type, + const safe_browsing::ListType list_type, const std::vector<SBThreatType>& expected_threats, const std::string& result_list) { scoped_refptr<SafeBrowsingService> sb_service_( @@ -69,7 +69,7 @@ const SBFullHashResult full_hash_result = { same_full_hash, - safe_browsing_util::GetListId(result_list) + safe_browsing::GetListId(result_list) }; std::vector<SBFullHashResult> fake_results(1, full_hash_result); @@ -82,23 +82,23 @@ TEST_F(SafeBrowsingDatabaseManagerTest, CheckCorrespondsListType) { std::vector<SBThreatType> malware_threat(1, SB_THREAT_TYPE_BINARY_MALWARE_URL); - EXPECT_FALSE(RunSBHashTest(safe_browsing_util::BINURL, + EXPECT_FALSE(RunSBHashTest(safe_browsing::BINURL, malware_threat, - safe_browsing_util::kMalwareList)); - EXPECT_TRUE(RunSBHashTest(safe_browsing_util::BINURL, + safe_browsing::kMalwareList)); + EXPECT_TRUE(RunSBHashTest(safe_browsing::BINURL, malware_threat, - safe_browsing_util::kBinUrlList)); + safe_browsing::kBinUrlList)); // Check for multiple threats std::vector<SBThreatType> multiple_threats; multiple_threats.push_back(SB_THREAT_TYPE_URL_MALWARE); multiple_threats.push_back(SB_THREAT_TYPE_URL_PHISHING); - EXPECT_FALSE(RunSBHashTest(safe_browsing_util::MALWARE, + EXPECT_FALSE(RunSBHashTest(safe_browsing::MALWARE, multiple_threats, - safe_browsing_util::kBinUrlList)); - EXPECT_TRUE(RunSBHashTest(safe_browsing_util::MALWARE, + safe_browsing::kBinUrlList)); + EXPECT_TRUE(RunSBHashTest(safe_browsing::MALWARE, multiple_threats, - safe_browsing_util::kMalwareList)); + safe_browsing::kMalwareList)); } TEST_F(SafeBrowsingDatabaseManagerTest, GetUrlSeverestThreatType) { @@ -111,31 +111,35 @@ "http://www.unwantedandmalware.com/page.html"); const GURL kSafeUrl("http://www.safe.com/page.html"); - const SBFullHash kMalwareHostHash = SBFullHashForString("malware.com/"); - const SBFullHash kPhishingHostHash = SBFullHashForString("phishing.com/"); - const SBFullHash kUnwantedHostHash = SBFullHashForString("unwanted.com/"); + const SBFullHash kMalwareHostHash = + safe_browsing::SBFullHashForString("malware.com/"); + const SBFullHash kPhishingHostHash = + safe_browsing::SBFullHashForString("phishing.com/"); + const SBFullHash kUnwantedHostHash = + safe_browsing::SBFullHashForString("unwanted.com/"); const SBFullHash kUnwantedAndMalwareHostHash = - SBFullHashForString("unwantedandmalware.com/"); - const SBFullHash kSafeHostHash = SBFullHashForString("www.safe.com/"); + safe_browsing::SBFullHashForString("unwantedandmalware.com/"); + const SBFullHash kSafeHostHash = + safe_browsing::SBFullHashForString("www.safe.com/"); { SBFullHashResult full_hash; full_hash.hash = kMalwareHostHash; - full_hash.list_id = static_cast<int>(safe_browsing_util::MALWARE); + full_hash.list_id = static_cast<int>(safe_browsing::MALWARE); full_hashes.push_back(full_hash); } { SBFullHashResult full_hash; full_hash.hash = kPhishingHostHash; - full_hash.list_id = static_cast<int>(safe_browsing_util::PHISH); + full_hash.list_id = static_cast<int>(safe_browsing::PHISH); full_hashes.push_back(full_hash); } { SBFullHashResult full_hash; full_hash.hash = kUnwantedHostHash; - full_hash.list_id = static_cast<int>(safe_browsing_util::UNWANTEDURL); + full_hash.list_id = static_cast<int>(safe_browsing::UNWANTEDURL); full_hashes.push_back(full_hash); } @@ -144,13 +148,12 @@ // kUnwantedAndMalwareHostHash. SBFullHashResult full_hash_malware; full_hash_malware.hash = kUnwantedAndMalwareHostHash; - full_hash_malware.list_id = static_cast<int>(safe_browsing_util::MALWARE); + full_hash_malware.list_id = static_cast<int>(safe_browsing::MALWARE); full_hashes.push_back(full_hash_malware); SBFullHashResult full_hash_unwanted; full_hash_unwanted.hash = kUnwantedAndMalwareHostHash; - full_hash_unwanted.list_id = - static_cast<int>(safe_browsing_util::UNWANTEDURL); + full_hash_unwanted.list_id = static_cast<int>(safe_browsing::UNWANTEDURL); full_hashes.push_back(full_hash_unwanted); }
diff --git a/chrome/browser/safe_browsing/protocol_manager.cc b/chrome/browser/safe_browsing/protocol_manager.cc index 745a9d7f..658453b 100644 --- a/chrome/browser/safe_browsing/protocol_manager.cc +++ b/chrome/browser/safe_browsing/protocol_manager.cc
@@ -18,6 +18,7 @@ #include "base/timer/timer.h" #include "chrome/browser/safe_browsing/protocol_parser.h" #include "chrome/common/env_vars.h" +#include "components/safe_browsing_db/util.h" #include "components/variations/variations_associated_data.h" #include "google_apis/google_api_keys.h" #include "net/base/escape.h" @@ -631,10 +632,10 @@ bool found_phishing = false; for (size_t i = 0; i < lists.size(); ++i) { update_list_data_.append(safe_browsing::FormatList(lists[i])); - if (lists[i].name == safe_browsing_util::kPhishingList) + if (lists[i].name == safe_browsing::kPhishingList) found_phishing = true; - if (lists[i].name == safe_browsing_util::kMalwareList) + if (lists[i].name == safe_browsing::kMalwareList) found_malware = true; } @@ -645,11 +646,11 @@ // removed. if (!found_phishing) { update_list_data_.append(safe_browsing::FormatList( - SBListChunkRanges(safe_browsing_util::kPhishingList))); + SBListChunkRanges(safe_browsing::kPhishingList))); } if (!found_malware) { update_list_data_.append(safe_browsing::FormatList( - SBListChunkRanges(safe_browsing_util::kMalwareList))); + SBListChunkRanges(safe_browsing::kMalwareList))); } // Large requests are (probably) a sign of database corruption.
diff --git a/chrome/browser/safe_browsing/protocol_manager_unittest.cc b/chrome/browser/safe_browsing/protocol_manager_unittest.cc index 31b18f9..d1705df 100644 --- a/chrome/browser/safe_browsing/protocol_manager_unittest.cc +++ b/chrome/browser/safe_browsing/protocol_manager_unittest.cc
@@ -408,7 +408,7 @@ net::TestURLFetcherFactory url_fetcher_factory; std::vector<SBListChunkRanges> ranges; - SBListChunkRanges range_phish(safe_browsing_util::kPhishingList); + SBListChunkRanges range_phish(safe_browsing::kPhishingList); range_phish.adds = "adds_phish"; range_phish.subs = "subs_phish"; ranges.push_back(range_phish);
diff --git a/chrome/browser/safe_browsing/protocol_parser.cc b/chrome/browser/safe_browsing/protocol_parser.cc index 05378c46..135e76f6 100644 --- a/chrome/browser/safe_browsing/protocol_parser.cc +++ b/chrome/browser/safe_browsing/protocol_parser.cc
@@ -199,7 +199,7 @@ return false; SBFullHashResult full_hash; - full_hash.list_id = safe_browsing_util::GetListId(cmd_parts[0]); + full_hash.list_id = safe_browsing::GetListId(cmd_parts[0]); size_t hash_len; if (!base::StringToSizeT(cmd_parts[1], &hash_len))
diff --git a/chrome/browser/safe_browsing/protocol_parser_unittest.cc b/chrome/browser/safe_browsing/protocol_parser_unittest.cc index 70872b3e..d145b81 100644 --- a/chrome/browser/safe_browsing/protocol_parser_unittest.cc +++ b/chrome/browser/safe_browsing/protocol_parser_unittest.cc
@@ -88,8 +88,10 @@ EXPECT_TRUE(chunks[0]->IsFullHash()); ASSERT_EQ(2U, chunks[0]->FullHashCount()); - EXPECT_TRUE(SBFullHashEqual(chunks[0]->FullHashAt(0), full_hash1)); - EXPECT_TRUE(SBFullHashEqual(chunks[0]->FullHashAt(1), full_hash2)); + EXPECT_TRUE( + safe_browsing::SBFullHashEqual(chunks[0]->FullHashAt(0), full_hash1)); + EXPECT_TRUE( + safe_browsing::SBFullHashEqual(chunks[0]->FullHashAt(1), full_hash2)); } // Test parsing multiple add chunks. We'll use the same chunk as above, and add @@ -282,9 +284,11 @@ EXPECT_TRUE(chunks[0]->IsFullHash()); ASSERT_EQ(2U, chunks[0]->FullHashCount()); - EXPECT_TRUE(SBFullHashEqual(chunks[0]->FullHashAt(0), full_hash1)); + EXPECT_TRUE( + safe_browsing::SBFullHashEqual(chunks[0]->FullHashAt(0), full_hash1)); EXPECT_EQ(7, chunks[0]->AddChunkNumberAt(0)); - EXPECT_TRUE(SBFullHashEqual(chunks[0]->FullHashAt(1), full_hash2)); + EXPECT_TRUE( + safe_browsing::SBFullHashEqual(chunks[0]->FullHashAt(1), full_hash2)); EXPECT_EQ(9, chunks[0]->AddChunkNumberAt(1)); } @@ -396,15 +400,15 @@ EXPECT_EQ(memcmp(&full_hashes[0].hash, "00112233445566778899aabbccddeeff", sizeof(SBFullHash)), 0); - EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[0].list_id); + EXPECT_EQ(safe_browsing::PHISH, full_hashes[0].list_id); EXPECT_EQ(memcmp(&full_hashes[1].hash, "00001111222233334444555566667777", sizeof(SBFullHash)), 0); - EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[1].list_id); + EXPECT_EQ(safe_browsing::PHISH, full_hashes[1].list_id); EXPECT_EQ(memcmp(&full_hashes[2].hash, "ffffeeeeddddccccbbbbaaaa99998888", sizeof(SBFullHash)), 0); - EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[2].list_id); + EXPECT_EQ(safe_browsing::PHISH, full_hashes[2].list_id); // Test multiple lists in the GetHash results. const std::string get_hash2(base::StringPrintf( @@ -423,15 +427,15 @@ EXPECT_EQ(memcmp(&full_hashes[0].hash, "00112233445566778899aabbccddeeff", sizeof(SBFullHash)), 0); - EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[0].list_id); + EXPECT_EQ(safe_browsing::PHISH, full_hashes[0].list_id); EXPECT_EQ(memcmp(&full_hashes[1].hash, "cafebeefcafebeefdeaddeaddeaddead", sizeof(SBFullHash)), 0); - EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[1].list_id); + EXPECT_EQ(safe_browsing::MALWARE, full_hashes[1].list_id); EXPECT_EQ(memcmp(&full_hashes[2].hash, "zzzzyyyyxxxxwwwwvvvvuuuuttttssss", sizeof(SBFullHash)), 0); - EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[2].list_id); + EXPECT_EQ(safe_browsing::MALWARE, full_hashes[2].list_id); // Test metadata parsing. const std::string get_hash3(base::StringPrintf( @@ -451,17 +455,17 @@ EXPECT_EQ(memcmp(&full_hashes[0].hash, "zzzzyyyyxxxxwwwwvvvvuuuuttttssss", sizeof(SBFullHash)), 0); - EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[0].list_id); + EXPECT_EQ(safe_browsing::MALWARE, full_hashes[0].list_id); EXPECT_EQ(std::string("ab"), full_hashes[0].metadata); EXPECT_EQ(memcmp(&full_hashes[1].hash, "00112233445566778899aabbccddeeff", sizeof(SBFullHash)), 0); - EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[1].list_id); + EXPECT_EQ(safe_browsing::MALWARE, full_hashes[1].list_id); EXPECT_EQ(std::string("xy"), full_hashes[1].metadata); EXPECT_EQ(memcmp(&full_hashes[2].hash, "cafebeefcafebeefdeaddeaddeaddead", sizeof(SBFullHash)), 0); - EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[2].list_id); + EXPECT_EQ(safe_browsing::PHISH, full_hashes[2].list_id); EXPECT_EQ(std::string(), full_hashes[2].metadata); } @@ -483,7 +487,7 @@ ASSERT_EQ(1U, full_hashes.size()); EXPECT_EQ(memcmp("12345678901234567890123456789012", &full_hashes[0].hash, sizeof(SBFullHash)), 0); - EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[0].list_id); + EXPECT_EQ(safe_browsing::PHISH, full_hashes[0].list_id); hash_response += base::StringPrintf( "%s:32:1\n" @@ -498,10 +502,10 @@ EXPECT_EQ(2U, full_hashes.size()); EXPECT_EQ(memcmp("12345678901234567890123456789012", &full_hashes[0].hash, sizeof(SBFullHash)), 0); - EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[0].list_id); + EXPECT_EQ(safe_browsing::PHISH, full_hashes[0].list_id); EXPECT_EQ(memcmp("abcdefghijklmnopqrstuvwxyz123457", &full_hashes[1].hash, sizeof(SBFullHash)), 0); - EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[1].list_id); + EXPECT_EQ(safe_browsing::MALWARE, full_hashes[1].list_id); } TEST(SafeBrowsingProtocolParsingTest, TestGetHashWithUnknownListAndMetadata) { @@ -523,7 +527,7 @@ EXPECT_EQ(memcmp(&full_hashes[0].hash, "0123456789hashhashhashhashhashha", sizeof(SBFullHash)), 0); - EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[0].list_id); + EXPECT_EQ(safe_browsing::MALWARE, full_hashes[0].list_id); EXPECT_EQ(std::string(), full_hashes[0].metadata); }
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc index 92c7c85..9decd2a 100644 --- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
@@ -92,7 +92,7 @@ std::vector<GURL>(1, gurl), std::vector<SBFullHash>(), client, - safe_browsing_util::MALWARE, + safe_browsing::MALWARE, expected_threats); sb_check.url_results[0] = badurls[gurl.spec()]; sb_check.OnSafeBrowsingResult();
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.cc b/chrome/browser/safe_browsing/safe_browsing_database.cc index 81948a6..80c16f7b 100644 --- a/chrome/browser/safe_browsing/safe_browsing_database.cc +++ b/chrome/browser/safe_browsing/safe_browsing_database.cc
@@ -107,7 +107,7 @@ return encoded_chunk_id >> 1; } int EncodeChunkId(const int chunk, const int list_id) { - DCHECK_NE(list_id, safe_browsing_util::INVALID); + DCHECK_NE(list_id, safe_browsing::INVALID); return chunk << 1 | list_id % 2; } @@ -128,16 +128,17 @@ if (url.HostIsIPAddress()) { hosts.push_back(url.host()); } else { - safe_browsing_util::GenerateHostsToCheck(url, &hosts); + safe_browsing::GenerateHostsToCheck(url, &hosts); } std::vector<std::string> paths; - safe_browsing_util::GeneratePathsToCheck(url, &paths); + safe_browsing::GeneratePathsToCheck(url, &paths); for (size_t i = 0; i < hosts.size(); ++i) { for (size_t j = 0; j < paths.size(); ++j) { const std::string& path = paths[j]; - full_hashes->push_back(SBFullHashForString(hosts[i] + path)); + full_hashes->push_back(safe_browsing::SBFullHashForString( + hosts[i] + path)); // We may have /foo as path-prefix in the whitelist which should // also match with /foo/bar and /foo?bar. Hence, for every path @@ -146,7 +147,8 @@ path.size() > 1 && path[path.size() - 1] == '/') { full_hashes->push_back( - SBFullHashForString(hosts[i] + path.substr(0, path.size() - 1))); + safe_browsing::SBFullHashForString( + hosts[i] + path.substr(0, path.size() - 1))); } } } @@ -230,10 +232,10 @@ for (size_t i = 0; i < listnames.size(); ++i) { const std::string& listname = listnames[i]; - DCHECK_EQ(safe_browsing_util::GetListId(listname) % 2, + DCHECK_EQ(safe_browsing::GetListId(listname) % 2, static_cast<int>(i % 2)); - DCHECK_NE(safe_browsing_util::GetListId(listname), - safe_browsing_util::INVALID); + DCHECK_NE(safe_browsing::GetListId(listname), + safe_browsing::INVALID); lists->push_back(SBListChunkRanges(listname)); lists->back().adds.swap(adds[i]); lists->back().subs.swap(subs[i]); @@ -289,7 +291,7 @@ // Find full-hash matches. std::vector<SBFullHashResult>& cached_hashes = cached_result.full_hashes; for (size_t i = 0; i < cached_hashes.size(); ++i) { - if (SBFullHashEqual(full_hash, cached_hashes[i].hash)) + if (safe_browsing::SBFullHashEqual(full_hash, cached_hashes[i].hash)) results->push_back(cached_hashes[i]); } @@ -445,22 +447,22 @@ // Stores are not thread safe. DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); - if (list_id == safe_browsing_util::PHISH || - list_id == safe_browsing_util::MALWARE) { + if (list_id == safe_browsing::PHISH || + list_id == safe_browsing::MALWARE) { return browse_store_.get(); - } else if (list_id == safe_browsing_util::BINURL) { + } else if (list_id == safe_browsing::BINURL) { return download_store_.get(); - } else if (list_id == safe_browsing_util::CSDWHITELIST) { + } else if (list_id == safe_browsing::CSDWHITELIST) { return csd_whitelist_store_.get(); - } else if (list_id == safe_browsing_util::DOWNLOADWHITELIST) { + } else if (list_id == safe_browsing::DOWNLOADWHITELIST) { return download_whitelist_store_.get(); - } else if (list_id == safe_browsing_util::INCLUSIONWHITELIST) { + } else if (list_id == safe_browsing::INCLUSIONWHITELIST) { return inclusion_whitelist_store_.get(); - } else if (list_id == safe_browsing_util::EXTENSIONBLACKLIST) { + } else if (list_id == safe_browsing::EXTENSIONBLACKLIST) { return extension_blacklist_store_.get(); - } else if (list_id == safe_browsing_util::IPBLACKLIST) { + } else if (list_id == safe_browsing::IPBLACKLIST) { return ip_blacklist_store_.get(); - } else if (list_id == safe_browsing_util::UNWANTEDURL) { + } else if (list_id == safe_browsing::UNWANTEDURL) { return unwanted_software_store_.get(); } return NULL; @@ -915,7 +917,7 @@ return false; return MatchAddPrefixes(download_store_.get(), - safe_browsing_util::BINURL % 2, + safe_browsing::BINURL % 2, prefixes, prefix_hits); } @@ -947,7 +949,7 @@ return false; return MatchAddPrefixes(extension_blacklist_store_.get(), - safe_browsing_util::EXTENSIONBLACKLIST % 2, + safe_browsing::EXTENSIONBLACKLIST % 2, prefixes, prefix_hits); } @@ -987,7 +989,7 @@ bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedString( const std::string& str) { std::vector<SBFullHash> hashes; - hashes.push_back(SBFullHashForString(str)); + hashes.push_back(safe_browsing::SBFullHashForString(str)); return ContainsWhitelistedHashes(SBWhitelistId::DOWNLOAD, hashes); } @@ -1001,7 +1003,7 @@ for (std::vector<SBFullHash>::const_iterator it = hashes.begin(); it != hashes.end(); ++it) { if (std::binary_search(whitelist->first.begin(), whitelist->first.end(), - *it, SBFullHashLess)) { + *it, safe_browsing::SBFullHashLess)) { return true; } } @@ -1011,7 +1013,7 @@ // Helper to insert add-chunk entries. void SafeBrowsingDatabaseNew::InsertAddChunk( SafeBrowsingStore* store, - const safe_browsing_util::ListType list_id, + const safe_browsing::ListType list_id, const SBChunkData& chunk_data) { DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); DCHECK(store); @@ -1040,7 +1042,7 @@ // Helper to insert sub-chunk entries. void SafeBrowsingDatabaseNew::InsertSubChunk( SafeBrowsingStore* store, - const safe_browsing_util::ListType list_id, + const safe_browsing::ListType list_id, const SBChunkData& chunk_data) { DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); DCHECK(store); @@ -1083,8 +1085,8 @@ const base::TimeTicks before = base::TimeTicks::Now(); // TODO(shess): The caller should just pass list_id. - const safe_browsing_util::ListType list_id = - safe_browsing_util::GetListId(list_name); + const safe_browsing::ListType list_id = + safe_browsing::GetListId(list_name); SafeBrowsingStore* store = GetStore(list_id); if (!store) return; @@ -1116,8 +1118,8 @@ return; const std::string& list_name = chunk_deletes.front().list_name; - const safe_browsing_util::ListType list_id = - safe_browsing_util::GetListId(list_name); + const safe_browsing::ListType list_id = + safe_browsing::GetListId(list_name); SafeBrowsingStore* store = GetStore(list_id); if (!store) return; @@ -1221,8 +1223,8 @@ state_manager_.BeginWriteTransaction()->clear_prefix_gethash_cache(); UpdateChunkRangesForLists(browse_store_.get(), - safe_browsing_util::kMalwareList, - safe_browsing_util::kPhishingList, + safe_browsing::kMalwareList, + safe_browsing::kPhishingList, lists); // NOTE(shess): |download_store_| used to contain kBinHashList, which has been @@ -1230,25 +1232,25 @@ // of Feb 2014, so it has been removed. Everything _should_ be resilient to // extra data of that sort. UpdateChunkRangesForList(download_store_.get(), - safe_browsing_util::kBinUrlList, lists); + safe_browsing::kBinUrlList, lists); UpdateChunkRangesForList(csd_whitelist_store_.get(), - safe_browsing_util::kCsdWhiteList, lists); + safe_browsing::kCsdWhiteList, lists); UpdateChunkRangesForList(download_whitelist_store_.get(), - safe_browsing_util::kDownloadWhiteList, lists); + safe_browsing::kDownloadWhiteList, lists); UpdateChunkRangesForList(inclusion_whitelist_store_.get(), - safe_browsing_util::kInclusionWhitelist, lists); + safe_browsing::kInclusionWhitelist, lists); UpdateChunkRangesForList(extension_blacklist_store_.get(), - safe_browsing_util::kExtensionBlacklist, lists); + safe_browsing::kExtensionBlacklist, lists); UpdateChunkRangesForList(ip_blacklist_store_.get(), - safe_browsing_util::kIPBlacklist, lists); + safe_browsing::kIPBlacklist, lists); UpdateChunkRangesForList(unwanted_software_store_.get(), - safe_browsing_util::kUnwantedUrlList, + safe_browsing::kUnwantedUrlList, lists); db_state_manager_.reset_corruption_detected(); @@ -1702,11 +1704,13 @@ it != full_hashes.end(); ++it) { new_whitelist.push_back(it->full_hash); } - std::sort(new_whitelist.begin(), new_whitelist.end(), SBFullHashLess); + std::sort(new_whitelist.begin(), new_whitelist.end(), + safe_browsing::SBFullHashLess); - SBFullHash kill_switch = SBFullHashForString(kWhitelistKillSwitchUrl); + SBFullHash kill_switch = safe_browsing::SBFullHashForString( + kWhitelistKillSwitchUrl); if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), - kill_switch, SBFullHashLess)) { + kill_switch, safe_browsing::SBFullHashLess)) { // The kill switch is whitelisted hence we whitelist all URLs. state_manager_.BeginWriteTransaction()->WhitelistEverything(whitelist_id); } else { @@ -1756,7 +1760,8 @@ } bool SafeBrowsingDatabaseNew::IsMalwareIPMatchKillSwitchOn() { - SBFullHash malware_kill_switch = SBFullHashForString(kMalwareIPKillSwitchUrl); + SBFullHash malware_kill_switch = safe_browsing::SBFullHashForString( + kMalwareIPKillSwitchUrl); std::vector<SBFullHash> full_hashes; full_hashes.push_back(malware_kill_switch); return ContainsWhitelistedHashes(SBWhitelistId::CSD, full_hashes);
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.h b/chrome/browser/safe_browsing/safe_browsing_database.h index 4d57ea3..22642a2 100644 --- a/chrome/browser/safe_browsing/safe_browsing_database.h +++ b/chrome/browser/safe_browsing/safe_browsing_database.h
@@ -19,6 +19,7 @@ #include "base/synchronization/lock.h" #include "base/time/time.h" #include "chrome/browser/safe_browsing/safe_browsing_store.h" +#include "components/safe_browsing_db/util.h" namespace safe_browsing { class PrefixSet; @@ -590,10 +591,10 @@ // Helpers for InsertChunks(). void InsertAddChunk(SafeBrowsingStore* store, - safe_browsing_util::ListType list_id, + safe_browsing::ListType list_id, const SBChunkData& chunk); void InsertSubChunk(SafeBrowsingStore* store, - safe_browsing_util::ListType list_id, + safe_browsing::ListType list_id, const SBChunkData& chunk); // Updates the |store| and stores the result on disk under |store_filename|.
diff --git a/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc index 75e4030b..33328129 100644 --- a/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc +++ b/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
@@ -32,7 +32,7 @@ const TimeDelta kCacheLifetime = TimeDelta::FromMinutes(45); SBPrefix SBPrefixForString(const std::string& str) { - return SBFullHashForString(str).prefix; + return safe_browsing::SBFullHashForString(str).prefix; } // Construct a full hash which has the given prefix, with the given @@ -135,7 +135,8 @@ // Generate an add chunk with a full hash generated from |value|. SBChunkData* AddChunkFullHashValue(int chunk_number, const std::string& value) { - return AddChunkFullHash(chunk_number, SBFullHashForString(value)); + return AddChunkFullHash(chunk_number, + safe_browsing::SBFullHashForString(value)); } // Generate an add chunk with two full hashes. @@ -143,8 +144,8 @@ const std::string& value1, const std::string& value2) { const SBFullHash full_hashes[2] = { - SBFullHashForString(value1), - SBFullHashForString(value2), + safe_browsing::SBFullHashForString(value1), + safe_browsing::SBFullHashForString(value2), }; return BuildChunk(chunk_number, safe_browsing::ChunkData::ADD, safe_browsing::ChunkData::FULL_32B, @@ -197,7 +198,7 @@ const std::string& value, int add_chunk_number) { return SubChunkFullHash(chunk_number, - SBFullHashForString(value), + safe_browsing::SBFullHashForString(value), add_chunk_number); } @@ -351,12 +352,12 @@ chunks.push_back(AddChunkPrefixValue(3, "www.whatever.com/malware.html")); ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); GetListsInfo(&lists); ASSERT_LE(1U, lists.size()); - EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name); + EXPECT_EQ(safe_browsing::kMalwareList, lists[0].name); EXPECT_EQ("1-3", lists[0].adds); EXPECT_TRUE(lists[0].subs.empty()); @@ -365,19 +366,19 @@ chunks.push_back(SubChunkPrefixValue(7, "www.subbed.com/noteveil1.html", 19)); ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); GetListsInfo(&lists); ASSERT_LE(1U, lists.size()); - EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name); + EXPECT_EQ(safe_browsing::kMalwareList, lists[0].name); EXPECT_EQ("1-3", lists[0].adds); EXPECT_EQ("7", lists[0].subs); if (lists.size() == 2) { // Old style database won't have the second entry since it creates the lists // when it receives an update containing that list. The filter-based // database has these values hard coded. - EXPECT_EQ(safe_browsing_util::kPhishingList, lists[1].name); + EXPECT_EQ(safe_browsing::kPhishingList, lists[1].name); EXPECT_TRUE(lists[1].adds.empty()); EXPECT_TRUE(lists[1].subs.empty()); } @@ -391,15 +392,15 @@ SubChunkPrefixValue(201, "www.phishy2.com/notevil1.html", 1999)); ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kPhishingList, chunks.get()); + database_->InsertChunks(safe_browsing::kPhishingList, chunks.get()); database_->UpdateFinished(true); GetListsInfo(&lists); ASSERT_LE(2U, lists.size()); - EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name); + EXPECT_EQ(safe_browsing::kMalwareList, lists[0].name); EXPECT_EQ("1-3", lists[0].adds); EXPECT_EQ("7", lists[0].subs); - EXPECT_EQ(safe_browsing_util::kPhishingList, lists[1].name); + EXPECT_EQ(safe_browsing::kPhishingList, lists[1].name); EXPECT_EQ("47", lists[1].adds); EXPECT_EQ("200-201", lists[1].subs); } @@ -412,73 +413,73 @@ // Insert malware, phish, binurl and bindownload add chunks. chunks.push_back(AddChunkPrefixValue(1, "www.evil.com/malware.html")); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); chunks.clear(); chunks.push_back(AddChunkPrefixValue(2, "www.foo.com/malware.html")); - database_->InsertChunks(safe_browsing_util::kPhishingList, chunks.get()); + database_->InsertChunks(safe_browsing::kPhishingList, chunks.get()); chunks.clear(); chunks.push_back(AddChunkPrefixValue(3, "www.whatever.com/download.html")); - database_->InsertChunks(safe_browsing_util::kBinUrlList, chunks.get()); + database_->InsertChunks(safe_browsing::kBinUrlList, chunks.get()); chunks.clear(); chunks.push_back(AddChunkFullHashValue(5, "www.forwhitelist.com/a.html")); - database_->InsertChunks(safe_browsing_util::kCsdWhiteList, chunks.get()); + database_->InsertChunks(safe_browsing::kCsdWhiteList, chunks.get()); chunks.clear(); chunks.push_back(AddChunkFullHashValue(6, "www.download.com/")); - database_->InsertChunks(safe_browsing_util::kDownloadWhiteList, chunks.get()); + database_->InsertChunks(safe_browsing::kDownloadWhiteList, chunks.get()); chunks.clear(); chunks.push_back(AddChunkFullHashValue(7, "www.inclusion.com/")); - database_->InsertChunks(safe_browsing_util::kInclusionWhitelist, + database_->InsertChunks(safe_browsing::kInclusionWhitelist, chunks.get()); chunks.clear(); chunks.push_back(AddChunkFullHashValue(8, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")); - database_->InsertChunks(safe_browsing_util::kExtensionBlacklist, + database_->InsertChunks(safe_browsing::kExtensionBlacklist, chunks.get()); chunks.clear(); chunks.push_back(AddChunkHashedIpValue(10, "::ffff:192.168.1.0", 120)); - database_->InsertChunks(safe_browsing_util::kIPBlacklist, chunks.get()); + database_->InsertChunks(safe_browsing::kIPBlacklist, chunks.get()); chunks.clear(); chunks.push_back(AddChunkPrefixValue(11, "www.unwanted.com/software.html")); - database_->InsertChunks(safe_browsing_util::kUnwantedUrlList, chunks.get()); + database_->InsertChunks(safe_browsing::kUnwantedUrlList, chunks.get()); database_->UpdateFinished(true); GetListsInfo(&lists); ASSERT_EQ(9U, lists.size()); - EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name); + EXPECT_EQ(safe_browsing::kMalwareList, lists[0].name); EXPECT_EQ("1", lists[0].adds); EXPECT_TRUE(lists[0].subs.empty()); - EXPECT_EQ(safe_browsing_util::kPhishingList, lists[1].name); + EXPECT_EQ(safe_browsing::kPhishingList, lists[1].name); EXPECT_EQ("2", lists[1].adds); EXPECT_TRUE(lists[1].subs.empty()); - EXPECT_EQ(safe_browsing_util::kBinUrlList, lists[2].name); + EXPECT_EQ(safe_browsing::kBinUrlList, lists[2].name); EXPECT_EQ("3", lists[2].adds); EXPECT_TRUE(lists[2].subs.empty()); - EXPECT_EQ(safe_browsing_util::kCsdWhiteList, lists[3].name); + EXPECT_EQ(safe_browsing::kCsdWhiteList, lists[3].name); EXPECT_EQ("5", lists[3].adds); EXPECT_TRUE(lists[3].subs.empty()); - EXPECT_EQ(safe_browsing_util::kDownloadWhiteList, lists[4].name); + EXPECT_EQ(safe_browsing::kDownloadWhiteList, lists[4].name); EXPECT_EQ("6", lists[4].adds); EXPECT_TRUE(lists[4].subs.empty()); - EXPECT_EQ(safe_browsing_util::kInclusionWhitelist, lists[5].name); + EXPECT_EQ(safe_browsing::kInclusionWhitelist, lists[5].name); EXPECT_EQ("7", lists[5].adds); EXPECT_TRUE(lists[5].subs.empty()); - EXPECT_EQ(safe_browsing_util::kExtensionBlacklist, lists[6].name); + EXPECT_EQ(safe_browsing::kExtensionBlacklist, lists[6].name); EXPECT_EQ("8", lists[6].adds); EXPECT_TRUE(lists[6].subs.empty()); - EXPECT_EQ(safe_browsing_util::kIPBlacklist, lists[7].name); + EXPECT_EQ(safe_browsing::kIPBlacklist, lists[7].name); EXPECT_EQ("10", lists[7].adds); EXPECT_TRUE(lists[7].subs.empty()); - EXPECT_EQ(safe_browsing_util::kUnwantedUrlList, lists[8].name); + EXPECT_EQ(safe_browsing::kUnwantedUrlList, lists[8].name); EXPECT_EQ("11", lists[8].adds); EXPECT_TRUE(lists[8].subs.empty()); @@ -497,11 +498,11 @@ size_t expected_list_index; TestListContainsBadUrl test_list_contains_bad_url; } const kTestCases[] { - { safe_browsing_util::kMalwareList, 0U, + { safe_browsing::kMalwareList, 0U, &SafeBrowsingDatabase::ContainsBrowseUrl }, - { safe_browsing_util::kPhishingList, 1U, + { safe_browsing::kPhishingList, 1U, &SafeBrowsingDatabase::ContainsBrowseUrl }, - { safe_browsing_util::kUnwantedUrlList, 8U, + { safe_browsing::kUnwantedUrlList, 8U, &SafeBrowsingDatabase::ContainsUnwantedSoftwareUrl }, }; @@ -757,13 +758,13 @@ "www.random.com/random2.html")); ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); // Add an empty ADD and SUB chunk. GetListsInfo(&lists); ASSERT_LE(1U, lists.size()); - EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name); + EXPECT_EQ(safe_browsing::kMalwareList, lists[0].name); EXPECT_EQ("1,10", lists[0].adds); EXPECT_TRUE(lists[0].subs.empty()); @@ -776,12 +777,12 @@ NULL, 0, std::vector<int>())); ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); GetListsInfo(&lists); ASSERT_LE(1U, lists.size()); - EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name); + EXPECT_EQ(safe_browsing::kMalwareList, lists[0].name); EXPECT_EQ("1,10,19", lists[0].adds); EXPECT_EQ("7", lists[0].subs); @@ -795,7 +796,7 @@ chunks.push_back(AddChunkPrefixValue(22, "www.notempty.com/full2.html")); ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); std::vector<SBPrefix> prefix_hits; @@ -807,28 +808,28 @@ GetListsInfo(&lists); ASSERT_LE(1U, lists.size()); - EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name); + EXPECT_EQ(safe_browsing::kMalwareList, lists[0].name); EXPECT_EQ("1,10,19-22", lists[0].adds); EXPECT_EQ("7", lists[0].subs); // Handle AddDel and SubDel commands for empty chunks. ASSERT_TRUE(database_->UpdateStarted(&lists)); - AddDelChunk(safe_browsing_util::kMalwareList, 21); + AddDelChunk(safe_browsing::kMalwareList, 21); database_->UpdateFinished(true); GetListsInfo(&lists); ASSERT_LE(1U, lists.size()); - EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name); + EXPECT_EQ(safe_browsing::kMalwareList, lists[0].name); EXPECT_EQ("1,10,19-20,22", lists[0].adds); EXPECT_EQ("7", lists[0].subs); ASSERT_TRUE(database_->UpdateStarted(&lists)); - SubDelChunk(safe_browsing_util::kMalwareList, 7); + SubDelChunk(safe_browsing::kMalwareList, 7); database_->UpdateFinished(true); GetListsInfo(&lists); ASSERT_LE(1U, lists.size()); - EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name); + EXPECT_EQ(safe_browsing::kMalwareList, lists[0].name); EXPECT_EQ("1,10,19-20,22", lists[0].adds); EXPECT_TRUE(lists[0].subs.empty()); } @@ -843,7 +844,7 @@ std::vector<SBListChunkRanges> lists; ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); // Cache should be cleared after updating. @@ -851,17 +852,19 @@ database_->GetUnsynchronizedPrefixGetHashCacheForTesting()->empty()); SBFullHashResult full_hash; - full_hash.list_id = safe_browsing_util::MALWARE; + full_hash.list_id = safe_browsing::MALWARE; std::vector<SBFullHashResult> results; std::vector<SBPrefix> prefixes; // Add a fullhash result for each prefix. - full_hash.hash = SBFullHashForString("www.evil.com/phishing.html"); + full_hash.hash = + safe_browsing::SBFullHashForString("www.evil.com/phishing.html"); results.push_back(full_hash); prefixes.push_back(full_hash.hash.prefix); - full_hash.hash = SBFullHashForString("www.evil.com/malware.html"); + full_hash.hash = + safe_browsing::SBFullHashForString("www.evil.com/malware.html"); results.push_back(full_hash); prefixes.push_back(full_hash.hash.prefix); @@ -882,8 +885,9 @@ GURL("http://www.evil.com/phishing.html"), &prefix_hits, &cache_hits)); EXPECT_TRUE(prefix_hits.empty()); ASSERT_EQ(1U, cache_hits.size()); - EXPECT_TRUE(SBFullHashEqual( - cache_hits[0].hash, SBFullHashForString("www.evil.com/phishing.html"))); + EXPECT_TRUE(safe_browsing::SBFullHashEqual( + cache_hits[0].hash, + safe_browsing::SBFullHashForString("www.evil.com/phishing.html"))); prefix_hits.clear(); cache_hits.clear(); @@ -893,8 +897,9 @@ GURL("http://www.evil.com/malware.html"), &prefix_hits, &cache_hits)); EXPECT_TRUE(prefix_hits.empty()); ASSERT_EQ(1U, cache_hits.size()); - EXPECT_TRUE(SBFullHashEqual( - cache_hits[0].hash, SBFullHashForString("www.evil.com/malware.html"))); + EXPECT_TRUE(safe_browsing::SBFullHashEqual( + cache_hits[0].hash, + safe_browsing::SBFullHashForString("www.evil.com/malware.html"))); prefix_hits.clear(); cache_hits.clear(); @@ -905,7 +910,7 @@ std::vector<SBListChunkRanges> lists; ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); // This prefix should still be there, but cached fullhash should be gone. @@ -925,7 +930,7 @@ // Test that an AddDel for the original chunk removes the last cached entry. ASSERT_TRUE(database_->UpdateStarted(&lists)); - AddDelChunk(safe_browsing_util::kMalwareList, 1); + AddDelChunk(safe_browsing::kMalwareList, 1); database_->UpdateFinished(true); EXPECT_FALSE(database_->ContainsBrowseUrl( GURL("http://www.evil.com/malware.html"), &prefix_hits, &cache_hits)); @@ -967,7 +972,7 @@ // Since PopulateDatabaseForCacheTest() doesn't handle adding duplicate // chunks. ASSERT_TRUE(database_->UpdateStarted(&lists)); - AddDelChunk(safe_browsing_util::kMalwareList, 1); + AddDelChunk(safe_browsing::kMalwareList, 1); database_->UpdateFinished(true); // Cache should be cleared after updating. @@ -1016,7 +1021,7 @@ "www.fullevil.com/bad1.html", "www.fullevil.com/bad2.html")); ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); EXPECT_TRUE(database_->ContainsBrowseUrl( @@ -1041,7 +1046,7 @@ "www.fullevil.com/bad1.html", 20)); ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); EXPECT_FALSE(database_->ContainsBrowseUrl( @@ -1058,7 +1063,7 @@ // Now test an AddDel for the remaining full add. ASSERT_TRUE(database_->UpdateStarted(&lists)); - AddDelChunk(safe_browsing_util::kMalwareList, 20); + AddDelChunk(safe_browsing::kMalwareList, 20); database_->UpdateFinished(true); EXPECT_FALSE(database_->ContainsBrowseUrl( @@ -1076,7 +1081,7 @@ { ScopedVector<SBChunkData> chunks; chunks.push_back(AddChunkPrefixValue(21, kExampleCollision)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); } database_->UpdateFinished(true); @@ -1091,8 +1096,8 @@ // Cache gethash response for |kExampleCollision|. { SBFullHashResult result; - result.hash = SBFullHashForString(kExampleCollision); - result.list_id = safe_browsing_util::MALWARE; + result.hash = safe_browsing::SBFullHashForString(kExampleCollision); + result.list_id = safe_browsing::MALWARE; database_->CacheHashResults(std::vector<SBPrefix>(1, result.hash.prefix), std::vector<SBFullHashResult>(1, result), kCacheLifetime); @@ -1145,7 +1150,7 @@ // Start an update. The insert will fail due to corruption. ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); // Database file still exists until the corruption handler has run. @@ -1161,7 +1166,7 @@ // Run the update again successfully. ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); EXPECT_TRUE(base::PathExists(database_filename_)); @@ -1179,7 +1184,7 @@ std::vector<SBListChunkRanges> lists; ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kBinUrlList, chunks.get()); + database_->InsertChunks(safe_browsing::kBinUrlList, chunks.get()); database_->UpdateFinished(true); std::vector<SBPrefix> prefix_hits; @@ -1276,13 +1281,13 @@ // for strings. TestListContainsWhitelistedString test_list_contains_whitelisted_string; } const kTestCases[]{ - {safe_browsing_util::kCsdWhiteList, + {safe_browsing::kCsdWhiteList, &SafeBrowsingDatabase::ContainsCsdWhitelistedUrl, nullptr}, - {safe_browsing_util::kDownloadWhiteList, + {safe_browsing::kDownloadWhiteList, &SafeBrowsingDatabase::ContainsDownloadWhitelistedUrl, &SafeBrowsingDatabase::ContainsDownloadWhitelistedString}, - {safe_browsing_util::kInclusionWhitelist, + {safe_browsing::kInclusionWhitelist, &SafeBrowsingDatabase::ContainsInclusionWhitelistedUrl, nullptr}, }; @@ -1417,7 +1422,7 @@ GURL(std::string("http://www.google.com/")))); // The malware kill switch is for the CSD whitelist only. - if (test_case.test_list_name == safe_browsing_util::kCsdWhiteList) { + if (test_case.test_list_name == safe_browsing::kCsdWhiteList) { // The CSD whitelist killswitch is not present. EXPECT_FALSE(database_->IsCsdWhitelistKillSwitchOn()); @@ -1427,7 +1432,7 @@ 15, "sb-ssl.google.com/safebrowsing/csd/killswitch_malware")); ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kCsdWhiteList, chunks.get()); + database_->InsertChunks(safe_browsing::kCsdWhiteList, chunks.get()); database_->UpdateFinished(true); EXPECT_TRUE(database_->IsMalwareIPMatchKillSwitchOn()); @@ -1446,7 +1451,7 @@ database_->UpdateFinished(true); // Test CSD whitelist specific methods. - if (test_case.test_list_name == safe_browsing_util::kCsdWhiteList) { + if (test_case.test_list_name == safe_browsing::kCsdWhiteList) { // The CSD whitelist killswitch is present. EXPECT_TRUE(database_->IsCsdWhitelistKillSwitchOn()); EXPECT_TRUE(database_->IsMalwareIPMatchKillSwitchOn()); @@ -1476,7 +1481,7 @@ lists.clear(); chunks.push_back(SubChunkFullHashValue( 1, "sb-ssl.google.com/safebrowsing/csd/killswitch", 5)); - if (test_case.test_list_name == safe_browsing_util::kCsdWhiteList) { + if (test_case.test_list_name == safe_browsing::kCsdWhiteList) { chunks.push_back(SubChunkFullHashValue( 10, "sb-ssl.google.com/safebrowsing/csd/killswitch_malware", 15)); } @@ -1485,7 +1490,7 @@ database_->InsertChunks(test_case.test_list_name, chunks.get()); database_->UpdateFinished(true); - if (test_case.test_list_name == safe_browsing_util::kCsdWhiteList) { + if (test_case.test_list_name == safe_browsing::kCsdWhiteList) { EXPECT_FALSE(database_->IsMalwareIPMatchKillSwitchOn()); EXPECT_FALSE(database_->IsCsdWhitelistKillSwitchOn()); } @@ -1528,12 +1533,12 @@ // Insert the testing chunks into database. std::vector<SBListChunkRanges> lists; ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); GetListsInfo(&lists); ASSERT_LE(1U, lists.size()); - EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name); + EXPECT_EQ(safe_browsing::kMalwareList, lists[0].name); EXPECT_EQ("1", lists[0].adds); EXPECT_TRUE(lists[0].subs.empty()); @@ -1544,15 +1549,15 @@ "www.evil.com/phishing2.html")); ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kPhishingList, chunks.get()); + database_->InsertChunks(safe_browsing::kPhishingList, chunks.get()); database_->UpdateFinished(true); GetListsInfo(&lists); ASSERT_LE(2U, lists.size()); - EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name); + EXPECT_EQ(safe_browsing::kMalwareList, lists[0].name); EXPECT_EQ("1", lists[0].adds); EXPECT_TRUE(lists[0].subs.empty()); - EXPECT_EQ(safe_browsing_util::kPhishingList, lists[1].name); + EXPECT_EQ(safe_browsing::kPhishingList, lists[1].name); EXPECT_EQ("47", lists[1].adds); EXPECT_TRUE(lists[1].subs.empty()); @@ -1573,14 +1578,14 @@ chunks.clear(); chunks.push_back(SubChunkPrefixValue(4, "www.evil.com/malware1.html", 1)); ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); // Remove the prefix that added last. chunks.clear(); chunks.push_back(SubChunkPrefixValue(5, "www.evil.com/phishing2.html", 47)); ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kPhishingList, chunks.get()); + database_->InsertChunks(safe_browsing::kPhishingList, chunks.get()); database_->UpdateFinished(true); // Verify that the database contains urls expected. @@ -1606,7 +1611,7 @@ std::vector<SBListChunkRanges> lists; ASSERT_TRUE(database_->UpdateStarted(&lists)); chunks.push_back(AddChunkPrefixValue(1, "www.evil.com/malware.html")); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); // Get an older time to reset the lastmod time for detecting whether @@ -1623,7 +1628,7 @@ ASSERT_TRUE(base::GetFileInfo(filename, &before_info)); ASSERT_TRUE(database_->UpdateStarted(&lists)); chunks.push_back(AddChunkPrefixValue(2, "www.foo.com/malware.html")); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); ASSERT_TRUE(base::GetFileInfo(filename, &after_info)); EXPECT_LT(before_info.last_modified, after_info.last_modified); @@ -1632,7 +1637,7 @@ ASSERT_TRUE(base::TouchFile(filename, old_last_modified, old_last_modified)); ASSERT_TRUE(base::GetFileInfo(filename, &before_info)); ASSERT_TRUE(database_->UpdateStarted(&lists)); - AddDelChunk(safe_browsing_util::kMalwareList, 2); + AddDelChunk(safe_browsing::kMalwareList, 2); database_->UpdateFinished(true); ASSERT_TRUE(base::GetFileInfo(filename, &after_info)); EXPECT_LT(before_info.last_modified, after_info.last_modified); @@ -1658,7 +1663,7 @@ ScopedVector<SBChunkData> chunks; chunks.push_back(AddChunkPrefixValue(1, "www.evil.com/malware.html")); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); } @@ -1708,7 +1713,7 @@ std::vector<SBListChunkRanges> lists; ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); { @@ -1763,7 +1768,7 @@ std::vector<SBListChunkRanges> lists; ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); { @@ -1807,7 +1812,7 @@ std::vector<SBFullHashResult> cache_results; SBFullHashResult full_hash_result; - full_hash_result.list_id = safe_browsing_util::MALWARE; + full_hash_result.list_id = safe_browsing::MALWARE; full_hash_result.hash = kFullHash1_1; cache_results.push_back(full_hash_result); @@ -1827,7 +1832,8 @@ full_hashes, &prefix_hits, &cache_hits)); EXPECT_TRUE(prefix_hits.empty()); ASSERT_EQ(1U, cache_hits.size()); - EXPECT_TRUE(SBFullHashEqual(kFullHash1_1, cache_hits[0].hash)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual( + kFullHash1_1, cache_hits[0].hash)); // Adding kFullHash2_1 will see the existing cache hit plus the prefix hit // for kPrefix2. @@ -1839,7 +1845,8 @@ ASSERT_EQ(1U, prefix_hits.size()); EXPECT_EQ(kPrefix2, prefix_hits[0]); ASSERT_EQ(1U, cache_hits.size()); - EXPECT_TRUE(SBFullHashEqual(kFullHash1_1, cache_hits[0].hash)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual( + kFullHash1_1, cache_hits[0].hash)); // kFullHash1_3 also gets a cache hit. full_hashes.push_back(kFullHash1_3); @@ -1850,8 +1857,10 @@ ASSERT_EQ(1U, prefix_hits.size()); EXPECT_EQ(kPrefix2, prefix_hits[0]); ASSERT_EQ(2U, cache_hits.size()); - EXPECT_TRUE(SBFullHashEqual(kFullHash1_1, cache_hits[0].hash)); - EXPECT_TRUE(SBFullHashEqual(kFullHash1_3, cache_hits[1].hash)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual( + kFullHash1_1, cache_hits[0].hash)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual( + kFullHash1_3, cache_hits[1].hash)); } { @@ -1863,7 +1872,8 @@ full_hashes, &prefix_hits, &cache_hits)); EXPECT_TRUE(prefix_hits.empty()); ASSERT_EQ(1U, cache_hits.size()); - EXPECT_TRUE(SBFullHashEqual(kFullHash1_3, cache_hits[0].hash)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual( + kFullHash1_3, cache_hits[0].hash)); } { @@ -1903,7 +1913,7 @@ std::vector<SBListChunkRanges> lists; ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); { @@ -1938,7 +1948,7 @@ { // Cache a gethash result for kFullHash1_2. SBFullHashResult full_hash_result; - full_hash_result.list_id = safe_browsing_util::MALWARE; + full_hash_result.list_id = safe_browsing::MALWARE; full_hash_result.hash = kFullHash1_2; std::vector<SBPrefix> prefixes(1, kPrefix1); @@ -1972,7 +1982,8 @@ full_hashes, &prefix_hits, &cache_hits)); EXPECT_TRUE(prefix_hits.empty()); ASSERT_EQ(1U, cache_hits.size()); - EXPECT_TRUE(SBFullHashEqual(kFullHash1_2, cache_hits[0].hash)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual( + kFullHash1_2, cache_hits[0].hash)); } // Remove kFullHash1_1 from the database. @@ -1980,7 +1991,7 @@ chunks.push_back(SubChunkFullHash(11, kFullHash1_1, 1)); ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); // Cache should be cleared after updating. @@ -2018,7 +2029,7 @@ chunks.push_back(SubChunkFullHash(12, kFullHash1_2, 2)); ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); // Cache should be cleared after updating. @@ -2050,7 +2061,7 @@ std::vector<SBListChunkRanges> lists; ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); { @@ -2067,7 +2078,7 @@ chunks.push_back(AddChunkPrefix(2, kPrefix1)); ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); { @@ -2087,7 +2098,7 @@ chunks.push_back(SubChunkFullHash(11, kFullHash1_1, 1)); ASSERT_TRUE(database_->UpdateStarted(&lists)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); database_->UpdateFinished(true); { @@ -2127,7 +2138,7 @@ // IPv4 prefix match for ::ffff:192.1.128.0/113. chunks.push_back(AddChunkHashedIpValue(6, "::ffff:192.1.128.0", 113)); - database_->InsertChunks(safe_browsing_util::kIPBlacklist, chunks.get()); + database_->InsertChunks(safe_browsing::kIPBlacklist, chunks.get()); database_->UpdateFinished(true); EXPECT_FALSE(database_->ContainsMalwareIP("192.168.0.255")); @@ -2177,7 +2188,7 @@ { ScopedVector<SBChunkData> chunks; chunks.push_back(AddChunkPrefixValue(1, "www.evil.com/")); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); } // Add a specific fullhash. @@ -2185,7 +2196,7 @@ { ScopedVector<SBChunkData> chunks; chunks.push_back(AddChunkFullHashValue(2, kWhateverMalware)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); } // Add a fullhash which has a prefix collision for a known url. @@ -2197,7 +2208,7 @@ { ScopedVector<SBChunkData> chunks; chunks.push_back(AddChunkFullHashValue(3, kExampleCollision)); - database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get()); + database_->InsertChunks(safe_browsing::kMalwareList, chunks.get()); } database_->UpdateFinished(true);
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc index f1d3971a..222cb7b 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -138,8 +138,8 @@ std::vector<SBPrefix>* prefix_hits, std::vector<SBFullHashResult>* cache_hits) override { cache_hits->clear(); - return ContainsUrl(safe_browsing_util::MALWARE, - safe_browsing_util::PHISH, + return ContainsUrl(safe_browsing::MALWARE, + safe_browsing::PHISH, std::vector<GURL>(1, url), prefix_hits); } @@ -148,8 +148,8 @@ std::vector<SBPrefix>* prefix_hits, std::vector<SBFullHashResult>* cache_hits) override { cache_hits->clear(); - return ContainsUrl(safe_browsing_util::UNWANTEDURL, - safe_browsing_util::UNWANTEDURL, + return ContainsUrl(safe_browsing::UNWANTEDURL, + safe_browsing::UNWANTEDURL, std::vector<GURL>(1, url), prefix_hits); } @@ -157,8 +157,8 @@ const std::vector<SBPrefix>& prefixes, std::vector<SBPrefix>* prefix_hits) override { bool found = - ContainsUrlPrefixes(safe_browsing_util::BINURL, - safe_browsing_util::BINURL, prefixes, prefix_hits); + ContainsUrlPrefixes(safe_browsing::BINURL, + safe_browsing::BINURL, prefixes, prefix_hits); if (!found) return false; DCHECK_LE(1U, prefix_hits->size()); @@ -424,8 +424,8 @@ SBFullHashResult* full_hash) { std::string host; std::string path; - safe_browsing_util::CanonicalizeUrl(url, &host, &path, NULL); - full_hash->hash = SBFullHashForString(host + path); + safe_browsing::CanonicalizeUrl(url, &host, &path, NULL); + full_hash->hash = safe_browsing::SBFullHashForString(host + path); full_hash->list_id = list_id; } @@ -601,7 +601,7 @@ void GenUrlFullhashResultWithMetadata(const GURL& url, SBFullHashResult* full_hash) { - GenUrlFullhashResult(url, safe_browsing_util::MALWARE, full_hash); + GenUrlFullhashResult(url, safe_browsing::MALWARE, full_hash); safe_browsing::MalwarePatternType proto; switch (GetParam()) { @@ -712,7 +712,7 @@ // Add the img url as coming from a site serving UwS and then load the parent // page. SBFullHashResult uws_full_hash; - GenUrlFullhashResult(img_url, safe_browsing_util::UNWANTEDURL, + GenUrlFullhashResult(img_url, safe_browsing::UNWANTEDURL, &uws_full_hash); SetupResponseForUrl(img_url, uws_full_hash); @@ -727,7 +727,7 @@ // After adding the url to safebrowsing database and getfullhash result, // we should see the interstitial page. SBFullHashResult malware_full_hash; - GenUrlFullhashResult(url, safe_browsing_util::MALWARE, &malware_full_hash); + GenUrlFullhashResult(url, safe_browsing::MALWARE, &malware_full_hash); EXPECT_CALL(observer_, OnSafeBrowsingMatch(IsUnsafeResourceFor(url))).Times(1); EXPECT_CALL(observer_, OnSafeBrowsingHit(IsUnsafeResourceFor(url))).Times(1) @@ -781,7 +781,7 @@ // getfullhash result, we should not see the interstitial page since the // only malware was a prefetch target. SBFullHashResult malware_full_hash; - GenUrlFullhashResult(malware_url, safe_browsing_util::MALWARE, + GenUrlFullhashResult(malware_url, safe_browsing::MALWARE, &malware_full_hash); SetupResponseForUrl(malware_url, malware_full_hash); ui_test_utils::NavigateToURL(browser(), url); @@ -896,7 +896,7 @@ EXPECT_EQ(SB_THREAT_TYPE_SAFE, client->GetThreatType()); SBFullHashResult full_hash_result; - GenUrlFullhashResult(badbin_url, safe_browsing_util::BINURL, + GenUrlFullhashResult(badbin_url, safe_browsing::BINURL, &full_hash_result); SetupResponseForUrl(badbin_url, full_hash_result); @@ -918,7 +918,7 @@ SBFullHashResult full_hash_result; GenUrlFullhashResult( - bad_url, safe_browsing_util::UNWANTEDURL, &full_hash_result); + bad_url, safe_browsing::UNWANTEDURL, &full_hash_result); SetupResponseForUrl(bad_url, full_hash_result); // Now, the bad_url is not safe since it is added to download @@ -940,7 +940,7 @@ SBFullHashResult full_hash_result; GenUrlFullhashResult( - bad_url, safe_browsing_util::MALWARE, &full_hash_result); + bad_url, safe_browsing::MALWARE, &full_hash_result); SetupResponseForUrl(bad_url, full_hash_result); client->CheckBrowseUrl(bad_url); @@ -960,7 +960,7 @@ SBFullHashResult full_hash_result; GenUrlFullhashResult( - bad_url, safe_browsing_util::MALWARE, &full_hash_result); + bad_url, safe_browsing::MALWARE, &full_hash_result); SetupResponseForUrl(bad_url, full_hash_result); // Now, the bad_url is not safe since it is added to download @@ -983,7 +983,7 @@ SBFullHashResult full_hash_result; GenUrlFullhashResult( - bad_url, safe_browsing_util::UNWANTEDURL, &full_hash_result); + bad_url, safe_browsing::UNWANTEDURL, &full_hash_result); SetupResponseForUrl(bad_url, full_hash_result); client->CheckBrowseUrl(bad_url); @@ -1007,7 +1007,7 @@ EXPECT_EQ(SB_THREAT_TYPE_SAFE, client->GetThreatType()); SBFullHashResult full_hash_result; - GenUrlFullhashResult(badbin_url, safe_browsing_util::BINURL, + GenUrlFullhashResult(badbin_url, safe_browsing::BINURL, &full_hash_result); SetupResponseForUrl(badbin_url, full_hash_result); @@ -1030,7 +1030,7 @@ scoped_refptr<TestSBClient> client(new TestSBClient); SBFullHashResult full_hash_result; - GenUrlFullhashResult(badbin_url, safe_browsing_util::BINURL, + GenUrlFullhashResult(badbin_url, safe_browsing::BINURL, &full_hash_result); SetupResponseForUrl(badbin_url, full_hash_result); client->CheckDownloadUrl(badbin_urls);
diff --git a/chrome/browser/safe_browsing/safe_browsing_store_file_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_store_file_unittest.cc index 768b90b..91e6fb3 100644 --- a/chrome/browser/safe_browsing/safe_browsing_store_file_unittest.cc +++ b/chrome/browser/safe_browsing/safe_browsing_store_file_unittest.cc
@@ -13,6 +13,7 @@ #include "base/test/test_simple_task_runner.h" #include "chrome/common/chrome_paths.h" #include "components/safe_browsing_db/prefix_set.h" +#include "components/safe_browsing_db/util.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -26,12 +27,12 @@ const int kSubChunk1 = 2; const int kSubChunk2 = 4; -const SBFullHash kHash1 = SBFullHashForString("one"); -const SBFullHash kHash2 = SBFullHashForString("two"); -const SBFullHash kHash3 = SBFullHashForString("three"); -const SBFullHash kHash4 = SBFullHashForString("four"); -const SBFullHash kHash5 = SBFullHashForString("five"); -const SBFullHash kHash6 = SBFullHashForString("six"); +const SBFullHash kHash1 = safe_browsing::SBFullHashForString("one"); +const SBFullHash kHash2 = safe_browsing::SBFullHashForString("two"); +const SBFullHash kHash3 = safe_browsing::SBFullHashForString("three"); +const SBFullHash kHash4 = safe_browsing::SBFullHashForString("four"); +const SBFullHash kHash5 = safe_browsing::SBFullHashForString("five"); +const SBFullHash kHash6 = safe_browsing::SBFullHashForString("six"); const SBPrefix kMinSBPrefix = 0u; const SBPrefix kMaxSBPrefix = ~kMinSBPrefix; @@ -194,7 +195,8 @@ ASSERT_EQ(1U, add_full_hashes_result.size()); EXPECT_EQ(kAddChunk2, add_full_hashes_result[0].chunk_id); - EXPECT_TRUE(SBFullHashEqual(kHash4, add_full_hashes_result[0].full_hash)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual( + kHash4, add_full_hashes_result[0].full_hash)); } } @@ -279,7 +281,8 @@ ASSERT_EQ(1U, add_full_hashes_result.size()); EXPECT_EQ(kAddChunk2, add_full_hashes_result[0].chunk_id); - EXPECT_TRUE(SBFullHashEqual(kHash4, add_full_hashes_result[0].full_hash)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual( + kHash4, add_full_hashes_result[0].full_hash)); } ASSERT_TRUE(store_->BeginUpdate()); @@ -302,7 +305,8 @@ ASSERT_EQ(1U, add_full_hashes_result.size()); EXPECT_EQ(kAddChunk2, add_full_hashes_result[0].chunk_id); - EXPECT_TRUE(SBFullHashEqual(kHash4, add_full_hashes_result[0].full_hash)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual( + kHash4, add_full_hashes_result[0].full_hash)); } ASSERT_TRUE(store_->BeginUpdate()); @@ -326,7 +330,8 @@ ASSERT_EQ(1U, add_full_hashes_result.size()); EXPECT_EQ(kAddChunk2, add_full_hashes_result[0].chunk_id); - EXPECT_TRUE(SBFullHashEqual(kHash4, add_full_hashes_result[0].full_hash)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual( + kHash4, add_full_hashes_result[0].full_hash)); } } @@ -392,7 +397,8 @@ ASSERT_EQ(1U, add_full_hashes_result.size()); EXPECT_EQ(kAddChunk3, add_full_hashes_result[0].chunk_id); - EXPECT_TRUE(SBFullHashEqual(kHash6, add_full_hashes_result[0].full_hash)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual( + kHash6, add_full_hashes_result[0].full_hash)); } // Expected chunks are there in another update. @@ -665,7 +671,7 @@ EXPECT_TRUE(store_->GetAddFullHashes(&add_hashes)); ASSERT_EQ(1U, add_hashes.size()); EXPECT_EQ(kAddChunk2, add_hashes[0].chunk_id); - EXPECT_TRUE(SBFullHashEqual(kHash4, add_hashes[0].full_hash)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual(kHash4, add_hashes[0].full_hash)); } // Test that the database handles resharding correctly, both when growing and @@ -807,7 +813,7 @@ EXPECT_TRUE(store_->GetAddFullHashes(&add_hashes)); ASSERT_EQ(1U, add_hashes.size()); EXPECT_EQ(kAddChunk1, add_hashes[0].chunk_id); - EXPECT_TRUE(SBFullHashEqual(kHash2, add_hashes[0].full_hash)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual(kHash2, add_hashes[0].full_hash)); // Attempt an update to make sure things work end-to-end. EXPECT_TRUE(store_->BeginUpdate());
diff --git a/chrome/browser/safe_browsing/safe_browsing_store_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_store_unittest.cc index 04751057..fb8ab175 100644 --- a/chrome/browser/safe_browsing/safe_browsing_store_unittest.cc +++ b/chrome/browser/safe_browsing/safe_browsing_store_unittest.cc
@@ -3,18 +3,19 @@ // found in the LICENSE file. #include "chrome/browser/safe_browsing/safe_browsing_store.h" +#include "components/safe_browsing_db/util.h" #include "testing/gtest/include/gtest/gtest.h" namespace { -const SBFullHash kHash1 = SBFullHashForString("one"); -const SBFullHash kHash2 = SBFullHashForString("two"); -const SBFullHash kHash3 = SBFullHashForString("three"); -const SBFullHash kHash4 = SBFullHashForString("four"); -const SBFullHash kHash5 = SBFullHashForString("five"); -const SBFullHash kHash6 = SBFullHashForString("six"); -const SBFullHash kHash7 = SBFullHashForString("seven"); +const SBFullHash kHash1 = safe_browsing::SBFullHashForString("one"); +const SBFullHash kHash2 = safe_browsing::SBFullHashForString("two"); +const SBFullHash kHash3 = safe_browsing::SBFullHashForString("three"); +const SBFullHash kHash4 = safe_browsing::SBFullHashForString("four"); +const SBFullHash kHash5 = safe_browsing::SBFullHashForString("five"); +const SBFullHash kHash6 = safe_browsing::SBFullHashForString("six"); +const SBFullHash kHash7 = safe_browsing::SBFullHashForString("seven"); const int kAddChunk1 = 1; // Use different chunk numbers just in case. const int kSubChunk1 = 2; @@ -217,9 +218,9 @@ ASSERT_EQ(2U, add_hashes.size()); EXPECT_EQ(kAddChunk5, add_hashes[0].chunk_id); - EXPECT_TRUE(SBFullHashEqual(kHash4, add_hashes[0].full_hash)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual(kHash4, add_hashes[0].full_hash)); EXPECT_EQ(kAddChunk6, add_hashes[1].chunk_id); - EXPECT_TRUE(SBFullHashEqual(kHash6, add_hashes[1].full_hash)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual(kHash6, add_hashes[1].full_hash)); ASSERT_EQ(1U, sub_prefixes.size()); EXPECT_EQ(kSubChunk4, sub_prefixes[0].chunk_id); @@ -229,7 +230,7 @@ ASSERT_EQ(1U, sub_hashes.size()); EXPECT_EQ(kSubChunk3, sub_hashes[0].chunk_id); EXPECT_EQ(kAddChunk3, sub_hashes[0].add_chunk_id); - EXPECT_TRUE(SBFullHashEqual(kHash7, sub_hashes[0].full_hash)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual(kHash7, sub_hashes[0].full_hash)); } // Test chunk deletions, and ordering of deletions WRT subs knocking @@ -274,7 +275,7 @@ ASSERT_EQ(1U, add_hashes.size()); EXPECT_EQ(kAddChunk1, add_hashes[0].chunk_id); - EXPECT_TRUE(SBFullHashEqual(kHash6, add_hashes[0].full_hash)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual(kHash6, add_hashes[0].full_hash)); EXPECT_TRUE(sub_prefixes.empty()); EXPECT_TRUE(sub_hashes.empty());
diff --git a/chrome/browser/safe_browsing/safe_browsing_util.cc b/chrome/browser/safe_browsing/safe_browsing_util.cc index 3a5ba424..867c1aa 100644 --- a/chrome/browser/safe_browsing/safe_browsing_util.cc +++ b/chrome/browser/safe_browsing/safe_browsing_util.cc
@@ -4,25 +4,10 @@ #include "chrome/browser/safe_browsing/safe_browsing_util.h" -#include "base/logging.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "chrome/browser/safe_browsing/chunk.pb.h" #include "components/google/core/browser/google_util.h" -#include "crypto/sha2.h" -#include "net/base/escape.h" -#include "url/gurl.h" -#include "url/url_util.h" - -// SBCachedFullHashResult ------------------------------------------------------ - -SBCachedFullHashResult::SBCachedFullHashResult() {} - -SBCachedFullHashResult::SBCachedFullHashResult( - const base::Time& in_expire_after) - : expire_after(in_expire_after) {} - -SBCachedFullHashResult::~SBCachedFullHashResult() {} // SBChunkData ----------------------------------------------------------------- @@ -143,343 +128,3 @@ SBChunkDelete::SBChunkDelete() : is_sub_del(false) {} SBChunkDelete::~SBChunkDelete() {} - -// Utility functions ----------------------------------------------------------- - -namespace { -bool IsKnownList(const std::string& name) { - for (size_t i = 0; i < arraysize(safe_browsing_util::kAllLists); ++i) { - if (!strcmp(safe_browsing_util::kAllLists[i], name.c_str())) { - return true; - } - } - return false; -} -} // namespace - -namespace safe_browsing_util { - -// Listnames that browser can process. -const char kMalwareList[] = "goog-malware-shavar"; -const char kPhishingList[] = "goog-phish-shavar"; -const char kBinUrlList[] = "goog-badbinurl-shavar"; -const char kCsdWhiteList[] = "goog-csdwhite-sha256"; -const char kDownloadWhiteList[] = "goog-downloadwhite-digest256"; -const char kExtensionBlacklist[] = "goog-badcrxids-digestvar"; -const char kIPBlacklist[] = "goog-badip-digest256"; -const char kUnwantedUrlList[] = "goog-unwanted-shavar"; -const char kInclusionWhitelist[] = "goog-csdinclusionwhite-sha256"; - -const char* kAllLists[9] = { - kMalwareList, - kPhishingList, - kBinUrlList, - kCsdWhiteList, - kDownloadWhiteList, - kExtensionBlacklist, - kIPBlacklist, - kUnwantedUrlList, - kInclusionWhitelist, -}; - -ListType GetListId(const base::StringPiece& name) { - ListType id; - if (name == safe_browsing_util::kMalwareList) { - id = MALWARE; - } else if (name == safe_browsing_util::kPhishingList) { - id = PHISH; - } else if (name == safe_browsing_util::kBinUrlList) { - id = BINURL; - } else if (name == safe_browsing_util::kCsdWhiteList) { - id = CSDWHITELIST; - } else if (name == safe_browsing_util::kDownloadWhiteList) { - id = DOWNLOADWHITELIST; - } else if (name == safe_browsing_util::kExtensionBlacklist) { - id = EXTENSIONBLACKLIST; - } else if (name == safe_browsing_util::kIPBlacklist) { - id = IPBLACKLIST; - } else if (name == safe_browsing_util::kUnwantedUrlList) { - id = UNWANTEDURL; - } else if (name == safe_browsing_util::kInclusionWhitelist) { - id = INCLUSIONWHITELIST; - } else { - id = INVALID; - } - return id; -} - -bool GetListName(ListType list_id, std::string* list) { - switch (list_id) { - case MALWARE: - *list = safe_browsing_util::kMalwareList; - break; - case PHISH: - *list = safe_browsing_util::kPhishingList; - break; - case BINURL: - *list = safe_browsing_util::kBinUrlList; - break; - case CSDWHITELIST: - *list = safe_browsing_util::kCsdWhiteList; - break; - case DOWNLOADWHITELIST: - *list = safe_browsing_util::kDownloadWhiteList; - break; - case EXTENSIONBLACKLIST: - *list = safe_browsing_util::kExtensionBlacklist; - break; - case IPBLACKLIST: - *list = safe_browsing_util::kIPBlacklist; - break; - case UNWANTEDURL: - *list = safe_browsing_util::kUnwantedUrlList; - break; - case INCLUSIONWHITELIST: - *list = safe_browsing_util::kInclusionWhitelist; - break; - default: - return false; - } - DCHECK(IsKnownList(*list)); - return true; -} - -std::string Unescape(const std::string& url) { - std::string unescaped_str(url); - std::string old_unescaped_str; - const int kMaxLoopIterations = 1024; - int loop_var = 0; - do { - old_unescaped_str = unescaped_str; - unescaped_str = net::UnescapeURLComponent( - old_unescaped_str, net::UnescapeRule::SPOOFING_AND_CONTROL_CHARS | - net::UnescapeRule::SPACES | - net::UnescapeRule::URL_SPECIAL_CHARS); - } while (unescaped_str != old_unescaped_str && ++loop_var <= - kMaxLoopIterations); - - return unescaped_str; -} - -std::string Escape(const std::string& url) { - std::string escaped_str; - const char* kHexString = "0123456789ABCDEF"; - for (size_t i = 0; i < url.length(); i++) { - unsigned char c = static_cast<unsigned char>(url[i]); - if (c <= ' ' || c > '~' || c == '#' || c == '%') { - escaped_str.push_back('%'); - escaped_str.push_back(kHexString[c >> 4]); - escaped_str.push_back(kHexString[c & 0xf]); - } else { - escaped_str.push_back(c); - } - } - - return escaped_str; -} - -std::string RemoveConsecutiveChars(const std::string& str, const char c) { - std::string output(str); - std::string string_to_find; - std::string::size_type loc = 0; - string_to_find.append(2, c); - while ((loc = output.find(string_to_find, loc)) != std::string::npos) { - output.erase(loc, 1); - } - - return output; -} - -// Canonicalizes url as per Google Safe Browsing Specification. -// See section 6.1 in -// http://code.google.com/p/google-safe-browsing/wiki/Protocolv2Spec. -void CanonicalizeUrl(const GURL& url, - std::string* canonicalized_hostname, - std::string* canonicalized_path, - std::string* canonicalized_query) { - DCHECK(url.is_valid()); - - // We only canonicalize "normal" URLs. - if (!url.IsStandard()) - return; - - // Following canonicalization steps are excluded since url parsing takes care - // of those :- - // 1. Remove any tab (0x09), CR (0x0d), and LF (0x0a) chars from url. - // (Exclude escaped version of these chars). - // 2. Normalize hostname to 4 dot-seperated decimal values. - // 3. Lowercase hostname. - // 4. Resolve path sequences "/../" and "/./". - - // That leaves us with the following :- - // 1. Remove fragment in URL. - GURL url_without_fragment; - GURL::Replacements f_replacements; - f_replacements.ClearRef(); - f_replacements.ClearUsername(); - f_replacements.ClearPassword(); - url_without_fragment = url.ReplaceComponents(f_replacements); - - // 2. Do URL unescaping until no more hex encoded characters exist. - std::string url_unescaped_str(Unescape(url_without_fragment.spec())); - url::Parsed parsed; - url::ParseStandardURL(url_unescaped_str.data(), url_unescaped_str.length(), - &parsed); - - // 3. In hostname, remove all leading and trailing dots. - const std::string host = - (parsed.host.len > 0) - ? url_unescaped_str.substr(parsed.host.begin, parsed.host.len) - : std::string(); - std::string host_without_end_dots; - base::TrimString(host, ".", &host_without_end_dots); - - // 4. In hostname, replace consecutive dots with a single dot. - std::string host_without_consecutive_dots(RemoveConsecutiveChars( - host_without_end_dots, '.')); - - // 5. In path, replace runs of consecutive slashes with a single slash. - std::string path = - (parsed.path.len > 0) - ? url_unescaped_str.substr(parsed.path.begin, parsed.path.len) - : std::string(); - std::string path_without_consecutive_slash(RemoveConsecutiveChars(path, '/')); - - url::Replacements<char> hp_replacements; - hp_replacements.SetHost( - host_without_consecutive_dots.data(), - url::Component(0, host_without_consecutive_dots.length())); - hp_replacements.SetPath( - path_without_consecutive_slash.data(), - url::Component(0, path_without_consecutive_slash.length())); - - std::string url_unescaped_with_can_hostpath; - url::StdStringCanonOutput output(&url_unescaped_with_can_hostpath); - url::Parsed temp_parsed; - url::ReplaceComponents(url_unescaped_str.data(), - url_unescaped_str.length(), - parsed, - hp_replacements, - NULL, - &output, - &temp_parsed); - output.Complete(); - - // 6. Step needed to revert escaping done in url::ReplaceComponents. - url_unescaped_with_can_hostpath = Unescape(url_unescaped_with_can_hostpath); - - // 7. After performing all above steps, percent-escape all chars in url which - // are <= ASCII 32, >= 127, #, %. Escapes must be uppercase hex characters. - std::string escaped_canon_url_str(Escape(url_unescaped_with_can_hostpath)); - url::Parsed final_parsed; - url::ParseStandardURL(escaped_canon_url_str.data(), - escaped_canon_url_str.length(), - &final_parsed); - - if (canonicalized_hostname && final_parsed.host.len > 0) { - *canonicalized_hostname = - escaped_canon_url_str.substr(final_parsed.host.begin, - final_parsed.host.len); - } - if (canonicalized_path && final_parsed.path.len > 0) { - *canonicalized_path = escaped_canon_url_str.substr(final_parsed.path.begin, - final_parsed.path.len); - } - if (canonicalized_query && final_parsed.query.len > 0) { - *canonicalized_query = escaped_canon_url_str.substr( - final_parsed.query.begin, final_parsed.query.len); - } -} - -void GenerateHostsToCheck(const GURL& url, std::vector<std::string>* hosts) { - hosts->clear(); - - std::string canon_host; - CanonicalizeUrl(url, &canon_host, NULL, NULL); - - const std::string host = canon_host; // const sidesteps GCC bugs below! - if (host.empty()) - return; - - // Per the Safe Browsing Protocol v2 spec, we try the host, and also up to 4 - // hostnames formed by starting with the last 5 components and successively - // removing the leading component. The last component isn't examined alone, - // since it's the TLD or a subcomponent thereof. - // - // Note that we don't need to be clever about stopping at the "real" eTLD -- - // the data on the server side has been filtered to ensure it will not - // blacklist a whole TLD, and it's not significantly slower on our side to - // just check too much. - // - // Also note that because we have a simple blacklist, not some sort of complex - // whitelist-in-blacklist or vice versa, it doesn't matter what order we check - // these in. - const size_t kMaxHostsToCheck = 4; - bool skipped_last_component = false; - for (std::string::const_reverse_iterator i(host.rbegin()); - i != host.rend() && hosts->size() < kMaxHostsToCheck; ++i) { - if (*i == '.') { - if (skipped_last_component) - hosts->push_back(std::string(i.base(), host.end())); - else - skipped_last_component = true; - } - } - hosts->push_back(host); -} - -void GeneratePathsToCheck(const GURL& url, std::vector<std::string>* paths) { - paths->clear(); - - std::string canon_path; - std::string canon_query; - CanonicalizeUrl(url, NULL, &canon_path, &canon_query); - - const std::string path = canon_path; // const sidesteps GCC bugs below! - const std::string query = canon_query; - if (path.empty()) - return; - - // Per the Safe Browsing Protocol v2 spec, we try the exact path with/without - // the query parameters, and also up to 4 paths formed by starting at the root - // and adding more path components. - // - // As with the hosts above, it doesn't matter what order we check these in. - const size_t kMaxPathsToCheck = 4; - for (std::string::const_iterator i(path.begin()); - i != path.end() && paths->size() < kMaxPathsToCheck; ++i) { - if (*i == '/') - paths->push_back(std::string(path.begin(), i + 1)); - } - - if (!paths->empty() && paths->back() != path) - paths->push_back(path); - - if (!query.empty()) - paths->push_back(path + "?" + query); -} - -void GeneratePatternsToCheck(const GURL& url, std::vector<std::string>* urls) { - std::vector<std::string> hosts, paths; - GenerateHostsToCheck(url, &hosts); - GeneratePathsToCheck(url, &paths); - for (size_t h = 0; h < hosts.size(); ++h) { - for (size_t p = 0; p < paths.size(); ++p) { - urls->push_back(hosts[h] + paths[p]); - } - } -} - -SBFullHash StringToSBFullHash(const std::string& hash_in) { - DCHECK_EQ(crypto::kSHA256Length, hash_in.size()); - SBFullHash hash_out; - memcpy(hash_out.full_hash, hash_in.data(), crypto::kSHA256Length); - return hash_out; -} - -std::string SBFullHashToString(const SBFullHash& hash) { - DCHECK_EQ(crypto::kSHA256Length, sizeof(hash.full_hash)); - return std::string(hash.full_hash, sizeof(hash.full_hash)); -} - -} // namespace safe_browsing_util
diff --git a/chrome/browser/safe_browsing/safe_browsing_util.h b/chrome/browser/safe_browsing/safe_browsing_util.h index b01f6a3..9cbb3cd 100644 --- a/chrome/browser/safe_browsing/safe_browsing_util.h +++ b/chrome/browser/safe_browsing/safe_browsing_util.h
@@ -16,14 +16,12 @@ #include "base/strings/string_piece.h" #include "base/time/time.h" #include "chrome/browser/safe_browsing/chunk_range.h" -#include "components/safe_browsing_db/safe_browsing_db_util.h" +#include "components/safe_browsing_db/util.h" namespace safe_browsing { class ChunkData; }; -class GURL; - // Container for holding a chunk URL and the list it belongs to. struct ChunkUrl { std::string url; @@ -65,24 +63,6 @@ DISALLOW_COPY_AND_ASSIGN(SBChunkData); }; -// Used when we get a gethash response. -struct SBFullHashResult { - SBFullHash hash; - // TODO(shess): Refactor to allow ListType here. - int list_id; - std::string metadata; -}; - -// Caches individual response from GETHASH request. -struct SBCachedFullHashResult { - SBCachedFullHashResult(); - explicit SBCachedFullHashResult(const base::Time& in_expire_after); - ~SBCachedFullHashResult(); - - base::Time expire_after; - std::vector<SBFullHashResult> full_hashes; -}; - // Contains information about a list in the database. struct SBListChunkRanges { explicit SBListChunkRanges(const std::string& n); @@ -102,81 +82,4 @@ std::vector<ChunkRange> chunk_del; }; -// Utility functions ----------------------------------------------------------- - -namespace safe_browsing_util { - -// SafeBrowsing list names. -extern const char kMalwareList[]; -extern const char kPhishingList[]; -// Binary Download list name. -extern const char kBinUrlList[]; -// SafeBrowsing client-side detection whitelist list name. -extern const char kCsdWhiteList[]; -// SafeBrowsing download whitelist list name. -extern const char kDownloadWhiteList[]; -// SafeBrowsing extension list name. -extern const char kExtensionBlacklist[]; -// SafeBrowsing csd malware IP blacklist name. -extern const char kIPBlacklist[]; -// SafeBrowsing unwanted URL list. -extern const char kUnwantedUrlList[]; -// SafeBrowsing off-domain inclusion whitelist list name. -extern const char kInclusionWhitelist[]; - -// This array must contain all Safe Browsing lists. -extern const char* kAllLists[9]; - -enum ListType { - INVALID = -1, - MALWARE = 0, - PHISH = 1, - BINURL = 2, - // Obsolete BINHASH = 3, - CSDWHITELIST = 4, - // SafeBrowsing lists are stored in pairs. Keep ListType 5 - // available for a potential second list that we would store in the - // csd-whitelist store file. - DOWNLOADWHITELIST = 6, - // See above comment. Leave 7 available. - EXTENSIONBLACKLIST = 8, - // See above comment. Leave 9 available. - // Obsolete SIDEEFFECTFREEWHITELIST = 10, - // See above comment. Leave 11 available. - IPBLACKLIST = 12, - // See above comment. Leave 13 available. - UNWANTEDURL = 14, - // See above comment. Leave 15 available. - INCLUSIONWHITELIST = 16, - // See above comment. Leave 17 available. -}; - -// Maps a list name to ListType. -ListType GetListId(const base::StringPiece& name); - -// Maps a ListId to list name. Return false if fails. -bool GetListName(ListType list_id, std::string* list); - -// Canonicalizes url as per Google Safe Browsing Specification. -// See section 6.1 in -// http://code.google.com/p/google-safe-browsing/wiki/Protocolv2Spec. -void CanonicalizeUrl(const GURL& url, std::string* canonicalized_hostname, - std::string* canonicalized_path, - std::string* canonicalized_query); - -// Given a URL, returns all the hosts we need to check. They are returned -// in order of size (i.e. b.c is first, then a.b.c). -void GenerateHostsToCheck(const GURL& url, std::vector<std::string>* hosts); - -// Given a URL, returns all the paths we need to check. -void GeneratePathsToCheck(const GURL& url, std::vector<std::string>* paths); - -// Given a URL, returns all the patterns we need to check. -void GeneratePatternsToCheck(const GURL& url, std::vector<std::string>* urls); - -SBFullHash StringToSBFullHash(const std::string& hash_in); -std::string SBFullHashToString(const SBFullHash& hash_out); - -} // namespace safe_browsing_util - #endif // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_UTIL_H_
diff --git a/chrome/browser/safe_browsing/safe_browsing_util_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_util_unittest.cc deleted file mode 100644 index 3c875bb..0000000 --- a/chrome/browser/safe_browsing/safe_browsing_util_unittest.cc +++ /dev/null
@@ -1,323 +0,0 @@ -// Copyright (c) 2011 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 <algorithm> - -#include "base/strings/stringprintf.h" -#include "chrome/browser/safe_browsing/safe_browsing_util.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -namespace { - -bool VectorContains(const std::vector<std::string>& data, - const std::string& str) { - return std::find(data.begin(), data.end(), str) != data.end(); -} - -// Tests that we generate the required host/path combinations for testing -// according to the Safe Browsing spec. -// See section 6.2 in -// http://code.google.com/p/google-safe-browsing/wiki/Protocolv2Spec. -TEST(SafeBrowsingUtilTest, UrlParsing) { - std::vector<std::string> hosts, paths; - - GURL url("http://a.b.c/1/2.html?param=1"); - safe_browsing_util::GenerateHostsToCheck(url, &hosts); - safe_browsing_util::GeneratePathsToCheck(url, &paths); - EXPECT_EQ(hosts.size(), static_cast<size_t>(2)); - EXPECT_EQ(paths.size(), static_cast<size_t>(4)); - EXPECT_EQ(hosts[0], "b.c"); - EXPECT_EQ(hosts[1], "a.b.c"); - - EXPECT_TRUE(VectorContains(paths, "/1/2.html?param=1")); - EXPECT_TRUE(VectorContains(paths, "/1/2.html")); - EXPECT_TRUE(VectorContains(paths, "/1/")); - EXPECT_TRUE(VectorContains(paths, "/")); - - url = GURL("http://a.b.c.d.e.f.g/1.html"); - safe_browsing_util::GenerateHostsToCheck(url, &hosts); - safe_browsing_util::GeneratePathsToCheck(url, &paths); - EXPECT_EQ(hosts.size(), static_cast<size_t>(5)); - EXPECT_EQ(paths.size(), static_cast<size_t>(2)); - EXPECT_EQ(hosts[0], "f.g"); - EXPECT_EQ(hosts[1], "e.f.g"); - EXPECT_EQ(hosts[2], "d.e.f.g"); - EXPECT_EQ(hosts[3], "c.d.e.f.g"); - EXPECT_EQ(hosts[4], "a.b.c.d.e.f.g"); - EXPECT_TRUE(VectorContains(paths, "/1.html")); - EXPECT_TRUE(VectorContains(paths, "/")); - - url = GURL("http://a.b/saw-cgi/eBayISAPI.dll/"); - safe_browsing_util::GeneratePathsToCheck(url, &paths); - EXPECT_EQ(paths.size(), static_cast<size_t>(3)); - EXPECT_TRUE(VectorContains(paths, "/saw-cgi/eBayISAPI.dll/")); - EXPECT_TRUE(VectorContains(paths, "/saw-cgi/")); - EXPECT_TRUE(VectorContains(paths, "/")); -} - -// Tests the url canonicalization according to the Safe Browsing spec. -// See section 6.1 in -// http://code.google.com/p/google-safe-browsing/wiki/Protocolv2Spec. -TEST(SafeBrowsingUtilTest, CanonicalizeUrl) { - struct { - const char* input_url; - const char* expected_canonicalized_hostname; - const char* expected_canonicalized_path; - const char* expected_canonicalized_query; - } tests[] = { - { - "http://host/%25%32%35", - "host", - "/%25", - "" - }, { - "http://host/%25%32%35%25%32%35", - "host", - "/%25%25", - "" - }, { - "http://host/%2525252525252525", - "host", - "/%25", - "" - }, { - "http://host/asdf%25%32%35asd", - "host", - "/asdf%25asd", - "" - }, { - "http://host/%%%25%32%35asd%%", - "host", - "/%25%25%25asd%25%25", - "" - }, { - "http://host/%%%25%32%35asd%%", - "host", - "/%25%25%25asd%25%25", - "" - }, { - "http://www.google.com/", - "www.google.com", - "/", - "" - }, { - "http://%31%36%38%2e%31%38%38%2e%39%39%2e%32%36/%2E%73%65%63%75%72%65/%77" - "%77%77%2E%65%62%61%79%2E%63%6F%6D/", - "168.188.99.26", - "/.secure/www.ebay.com/", - "" - }, { - "http://195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserd" - "ataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/", - "195.127.0.11", - "/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmv" - "alidateinfoswqpcmlx=hgplmcx/", - "" - }, { - "http://host.com/%257Ea%2521b%2540c%2523d%2524e%25f%255E00%252611%252A" - "22%252833%252944_55%252B", - "host.com", - "/~a!b@c%23d$e%25f^00&11*22(33)44_55+", - "" - }, { - "http://3279880203/blah", - "195.127.0.11", - "/blah", - "" - }, { - "http://www.google.com/blah/..", - "www.google.com", - "/", - "" - }, { - "http://www.google.com/blah#fraq", - "www.google.com", - "/blah", - "" - }, { - "http://www.GOOgle.com/", - "www.google.com", - "/", - "" - }, { - "http://www.google.com.../", - "www.google.com", - "/", - "" - }, { - "http://www.google.com/q?", - "www.google.com", - "/q", - "" - }, { - "http://www.google.com/q?r?", - "www.google.com", - "/q", - "r?" - }, { - "http://www.google.com/q?r?s", - "www.google.com", - "/q", - "r?s" - }, { - "http://evil.com/foo#bar#baz", - "evil.com", - "/foo", - "" - }, { - "http://evil.com/foo;", - "evil.com", - "/foo;", - "" - }, { - "http://evil.com/foo?bar;", - "evil.com", - "/foo", - "bar;" - }, { - "http://notrailingslash.com", - "notrailingslash.com", - "/", - "" - }, { - "http://www.gotaport.com:1234/", - "www.gotaport.com", - "/", - "" - }, { - " http://www.google.com/ ", - "www.google.com", - "/", - "" - }, { - "http:// leadingspace.com/", - "%20leadingspace.com", - "/", - "" - }, { - "http://%20leadingspace.com/", - "%20leadingspace.com", - "/", - "" - }, { - "https://www.securesite.com/", - "www.securesite.com", - "/", - "" - }, { - "http://host.com/ab%23cd", - "host.com", - "/ab%23cd", - "" - }, { - "http://host%3e.com//twoslashes?more//slashes", - "host>.com", - "/twoslashes", - "more//slashes" - }, { - "http://host.com/abc?val=xyz#anything", - "host.com", - "/abc", - "val=xyz" - }, { - "http://abc:def@host.com/xyz", - "host.com", - "/xyz", - "" - }, { - "http://host%3e.com/abc/%2e%2e%2fdef", - "host>.com", - "/def", - "" - }, { - "http://.......host...com.....//abc/////def%2F%2F%2Fxyz", - "host.com", - "/abc/def/xyz", - "" - }, { - "ftp://host.com/foo?bar", - "host.com", - "/foo", - "bar" - }, { - "data:text/html;charset=utf-8,%0D%0A", - "", - "", - "" - }, { - "javascript:alert()", - "", - "", - "" - }, { - "mailto:abc@example.com", - "", - "", - "" - }, - }; - for (size_t i = 0; i < arraysize(tests); ++i) { - SCOPED_TRACE(base::StringPrintf("Test: %s", tests[i].input_url)); - GURL url(tests[i].input_url); - - std::string canonicalized_hostname; - std::string canonicalized_path; - std::string canonicalized_query; - safe_browsing_util::CanonicalizeUrl(url, &canonicalized_hostname, - &canonicalized_path, &canonicalized_query); - - EXPECT_EQ(tests[i].expected_canonicalized_hostname, - canonicalized_hostname); - EXPECT_EQ(tests[i].expected_canonicalized_path, - canonicalized_path); - EXPECT_EQ(tests[i].expected_canonicalized_query, - canonicalized_query); - } -} - -TEST(SafeBrowsingUtilTest, ListIdListNameConversion) { - std::string list_name; - EXPECT_FALSE(safe_browsing_util::GetListName(safe_browsing_util::INVALID, - &list_name)); - EXPECT_TRUE(safe_browsing_util::GetListName(safe_browsing_util::MALWARE, - &list_name)); - EXPECT_EQ(list_name, std::string(safe_browsing_util::kMalwareList)); - EXPECT_EQ(safe_browsing_util::MALWARE, - safe_browsing_util::GetListId(list_name)); - - EXPECT_TRUE(safe_browsing_util::GetListName(safe_browsing_util::PHISH, - &list_name)); - EXPECT_EQ(list_name, std::string(safe_browsing_util::kPhishingList)); - EXPECT_EQ(safe_browsing_util::PHISH, - safe_browsing_util::GetListId(list_name)); - - EXPECT_TRUE(safe_browsing_util::GetListName(safe_browsing_util::BINURL, - &list_name)); - EXPECT_EQ(list_name, std::string(safe_browsing_util::kBinUrlList)); - EXPECT_EQ(safe_browsing_util::BINURL, - safe_browsing_util::GetListId(list_name)); -} - -// Since the ids are saved in file, we need to make sure they don't change. -// Since only the last bit of each id is saved in file together with -// chunkids, this checks only last bit. -TEST(SafeBrowsingUtilTest, ListIdVerification) { - EXPECT_EQ(0, safe_browsing_util::MALWARE % 2); - EXPECT_EQ(1, safe_browsing_util::PHISH % 2); - EXPECT_EQ(0, safe_browsing_util::BINURL %2); -} - -TEST(SafeBrowsingUtilTest, StringToSBFullHashAndSBFullHashToString) { - // 31 chars plus the last \0 as full_hash. - const std::string hash_in = "12345678902234567890323456789012"; - SBFullHash hash_out = safe_browsing_util::StringToSBFullHash(hash_in); - EXPECT_EQ(0x34333231U, hash_out.prefix); - EXPECT_EQ(0, memcmp(hash_in.data(), hash_out.full_hash, sizeof(SBFullHash))); - - std::string hash_final = safe_browsing_util::SBFullHashToString(hash_out); - EXPECT_EQ(hash_in, hash_final); -} - -} // namespace
diff --git a/chrome/browser/safe_browsing/unverified_download_field_trial.cc b/chrome/browser/safe_browsing/unverified_download_field_trial.cc index 6086ab9..0eaa06e 100644 --- a/chrome/browser/safe_browsing/unverified_download_field_trial.cc +++ b/chrome/browser/safe_browsing/unverified_download_field_trial.cc
@@ -9,6 +9,7 @@ #include "base/metrics/field_trial.h" #include "base/metrics/histogram.h" #include "base/strings/string_split.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/safe_browsing/download_protection_util.h" @@ -19,14 +20,12 @@ const char kUnverifiedDownloadFieldTrialName[] = "SafeBrowsingUnverifiedDownloads"; -const char kUnverifiedDownloadFieldTrialDisableAll[] = "DisableAll"; const char kUnverifiedDownloadFieldTrialDisableByParameter[] = "DisableByParameter"; -const char kUnverifiedDownloadFieldTrialDisableSBTypesAndByParameter[] = - "DisableSBTypesAndByParameter"; const char kUnverifiedDownloadFieldTrialWhitelistParam[] = "whitelist"; const char kUnverifiedDownloadFieldTrialBlacklistParam[] = "blacklist"; +const char kUnverifiedDownloadFieldTrialBlockSBTypesParam[] = "block_sb_types"; namespace { @@ -41,6 +40,11 @@ std::vector<base::FilePath::StringPieceType> extension_list = base::SplitStringPiece(comma_separated_extensions, FILE_PATH_LITERAL(","), base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + + // A single '*' matches everything. + if (extension_list.size() == 1 && extension_list[0] == FILE_PATH_LITERAL("*")) + return true; + for (const auto& extension : extension_list) { // This shouldn't happen, but check anyway in case the parameter is // accidentally malformed. The underlying FilePath implementation expects @@ -64,11 +68,14 @@ switches::kAllowUncheckedDangerousDownloads)) return true; - if (group_name == kUnverifiedDownloadFieldTrialDisableAll) + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisallowUncheckedDangerousDownloads) && + download_protection_util::IsSupportedBinaryFile(file)) return false; - if (group_name == kUnverifiedDownloadFieldTrialDisableByParameter || - group_name == kUnverifiedDownloadFieldTrialDisableSBTypesAndByParameter) { + if (base::StartsWith(group_name, + kUnverifiedDownloadFieldTrialDisableByParameter, + base::CompareCase::SENSITIVE)) { std::map<std::string, std::string> parameters; variations::GetVariationParams(kUnverifiedDownloadFieldTrialName, ¶meters); @@ -82,12 +89,12 @@ MatchesExtensionList( file, parameters[kUnverifiedDownloadFieldTrialWhitelistParam])) return true; - } - if (group_name == kUnverifiedDownloadFieldTrialDisableSBTypesAndByParameter || - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisallowUncheckedDangerousDownloads)) - return !download_protection_util::IsSupportedBinaryFile(file); + if (parameters.count(kUnverifiedDownloadFieldTrialBlockSBTypesParam) && + !parameters[kUnverifiedDownloadFieldTrialBlockSBTypesParam].empty() && + download_protection_util::IsSupportedBinaryFile(file)) + return false; + } return true; }
diff --git a/chrome/browser/safe_browsing/unverified_download_field_trial.h b/chrome/browser/safe_browsing/unverified_download_field_trial.h index 4d9432a5..3490f79 100644 --- a/chrome/browser/safe_browsing/unverified_download_field_trial.h +++ b/chrome/browser/safe_browsing/unverified_download_field_trial.h
@@ -24,12 +24,7 @@ // The trial groups are: // -// * DisableAll : Disables all unverified downloads regardless of whether the -// specific file in question is potentially dangerous or handled by Safe -// Browsing at all. -extern const char kUnverifiedDownloadFieldTrialDisableAll[]; - -// * DisableByParameter : Decides the fate of unverified downloads based on +// * DisableByParameter[*] : Decides the fate of unverified downloads based on // whether the file type matches a whitelist and a blacklist specified as a // parameter to this trial group. Any file type that doesn't match either of // these lists will default to being allowed. @@ -47,11 +42,9 @@ // types to be disallowed from downloading. extern const char kUnverifiedDownloadFieldTrialBlacklistParam[]; -// * DisableSBTypesAndByParameter : Applies the whitelist and blacklist as -// described in DisableByParameter. However, any file type that doesn't -// match either list but is considered supported by SafeBrowsing will be -// blocked. -extern const char kUnverifiedDownloadFieldTrialDisableSBTypesAndByParameter[]; +// - 'block_sb_types' : If non-empty, causes all file types that satisfy +// safe_browsing::IsSupportedBinaryFile() to be blocked. +extern const char kUnverifiedDownloadFieldTrialBlockSBTypesParam[]; // Returns true if |file| is allowed to be downloaded based on the current field // trial settings.
diff --git a/chrome/browser/safe_browsing/unverified_download_field_trial_unittest.cc b/chrome/browser/safe_browsing/unverified_download_field_trial_unittest.cc index 2442ba6..13b911ec 100644 --- a/chrome/browser/safe_browsing/unverified_download_field_trial_unittest.cc +++ b/chrome/browser/safe_browsing/unverified_download_field_trial_unittest.cc
@@ -62,15 +62,9 @@ base::FilePath(kSafeFilename))); } -TEST(UnverifiedDownloadFieldTrialTest, CommandLine_AllowAll) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAllowUncheckedDangerousDownloads); - EXPECT_TRUE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( - base::FilePath(kSafeFilename))); - EXPECT_TRUE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( - base::FilePath(kHandledFilename))); -} - +// Verify that disallow-unchecked-dangerous-downloads command line switch causes +// all dangerous file types to be blocked, and that safe files types are still +// allowed. TEST(UnverifiedDownloadFieldTrialTest, CommandLine_DisallowDangerous) { base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kDisallowUncheckedDangerousDownloads); @@ -80,15 +74,76 @@ base::FilePath(kHandledFilename))); } -TEST(UnverifiedDownloadFieldTrialTest, DisableAll) { - ScopedFieldTrialState field_trial(kUnverifiedDownloadFieldTrialDisableAll); +// Verify that a wildcard blacklist matches all file types. +TEST(UnverifiedDownloadFieldTrialTest, WildCardBlacklist) { + FieldTrialParameters parameters; + parameters[kUnverifiedDownloadFieldTrialBlacklistParam] = "*"; + parameters[kUnverifiedDownloadFieldTrialWhitelistParam] = ".xyz"; + ScopedFieldTrialState field_trial( + kUnverifiedDownloadFieldTrialDisableByParameter, parameters); + EXPECT_FALSE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( base::FilePath(kSafeFilename))); EXPECT_FALSE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( base::FilePath(kHandledFilename))); + EXPECT_FALSE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( + base::FilePath(FILE_PATH_LITERAL("foo.xyz")))); } -TEST(UnverifiedDownloadFieldTrialTest, DisableByParam) { +// Verify that allow-unchecked-dangerous-downloads command line option takes +// precedence over a Finch trial specified blacklist. +TEST(UnverifiedDownloadFieldTrialTest, BlacklistVsCommandline) { + FieldTrialParameters parameters; + parameters[kUnverifiedDownloadFieldTrialBlacklistParam] = "*"; + parameters[kUnverifiedDownloadFieldTrialWhitelistParam] = ".xyz"; + ScopedFieldTrialState field_trial( + kUnverifiedDownloadFieldTrialDisableByParameter, parameters); + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kAllowUncheckedDangerousDownloads); + + EXPECT_TRUE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( + base::FilePath(kSafeFilename))); + EXPECT_TRUE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( + base::FilePath(kHandledFilename))); +} + +// Verify that disallow-unchecked-dangerous-downloads command line option takes +// precedence over a Finch trial specified whitelist. +TEST(UnverifiedDownloadFieldTrialTest, WhitelistVsCommandline) { + FieldTrialParameters parameters; + parameters[kUnverifiedDownloadFieldTrialBlacklistParam] = ".foo"; + parameters[kUnverifiedDownloadFieldTrialWhitelistParam] = ".exe"; + ScopedFieldTrialState field_trial( + kUnverifiedDownloadFieldTrialDisableByParameter, parameters); + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kDisallowUncheckedDangerousDownloads); + + EXPECT_FALSE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( + base::FilePath(FILE_PATH_LITERAL("foo.foo")))); + EXPECT_FALSE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( + base::FilePath(FILE_PATH_LITERAL("foo.exe")))); + EXPECT_TRUE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( + base::FilePath(FILE_PATH_LITERAL("foo.txt")))); +} + +// Verify that wildcards only work if they are specified by themselves. +TEST(UnverifiedDownloadFieldTrialTest, WildcardOnlyByItself) { + FieldTrialParameters parameters; + parameters[kUnverifiedDownloadFieldTrialBlacklistParam] = ".foo,*"; + parameters[kUnverifiedDownloadFieldTrialWhitelistParam] = ".xyz"; + ScopedFieldTrialState field_trial( + kUnverifiedDownloadFieldTrialDisableByParameter, parameters); + + EXPECT_FALSE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( + base::FilePath(FILE_PATH_LITERAL("foo.foo")))); + EXPECT_TRUE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( + base::FilePath(FILE_PATH_LITERAL("foo.xyz")))); + EXPECT_TRUE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( + base::FilePath(FILE_PATH_LITERAL("foo.txt")))); +} + +// Verify that the blacklist takes precedence over whitelist. +TEST(UnverifiedDownloadFieldTrialTest, WhitelistVsBlacklist) { FieldTrialParameters parameters; parameters[kUnverifiedDownloadFieldTrialBlacklistParam] = ".abc,.def"; parameters[kUnverifiedDownloadFieldTrialWhitelistParam] = ".xyz"; @@ -107,9 +162,8 @@ base::FilePath(FILE_PATH_LITERAL("foo.def")))); } -// Verify that nothing terrible happens if no parameters are specified for a -// group that expects parameters. -TEST(UnverifiedDownloadFieldTrialTest, DisableByParam_NoParameters) { +// Verify that nothing terrible happens if no parameters are specified. +TEST(UnverifiedDownloadFieldTrialTest, MissingParameters) { ScopedFieldTrialState field_trial( kUnverifiedDownloadFieldTrialDisableByParameter); @@ -121,7 +175,7 @@ // Verify that nothing terrible happens if the parameters set for a field trial // are malformed. -TEST(UnverifiedDownloadFieldTrialTest, DisableByParam_BadFormat) { +TEST(UnverifiedDownloadFieldTrialTest, MalformedParameters) { FieldTrialParameters parameters; parameters[kUnverifiedDownloadFieldTrialBlacklistParam] = "abcasdfa#??# ~def"; parameters[kUnverifiedDownloadFieldTrialWhitelistParam] = @@ -141,6 +195,7 @@ FieldTrialParameters parameters; parameters[kUnverifiedDownloadFieldTrialBlacklistParam] = ""; parameters[kUnverifiedDownloadFieldTrialWhitelistParam] = ""; + parameters[kUnverifiedDownloadFieldTrialBlockSBTypesParam] = ""; ScopedFieldTrialState field_trial( kUnverifiedDownloadFieldTrialDisableByParameter, parameters); @@ -150,10 +205,10 @@ base::FilePath(kHandledFilename))); } -TEST(UnverifiedDownloadFieldTrialTest, DisableByParam_CaseSensitive) { +// Verified that file types specified via white/blacklists are case insensitive. +TEST(UnverifiedDownloadFieldTrialTest, CaseInsensitive) { FieldTrialParameters parameters; parameters[kUnverifiedDownloadFieldTrialBlacklistParam] = ".ABC,.xyz"; - parameters[kUnverifiedDownloadFieldTrialWhitelistParam] = ""; ScopedFieldTrialState field_trial( kUnverifiedDownloadFieldTrialDisableByParameter, parameters); @@ -167,12 +222,14 @@ base::FilePath(FILE_PATH_LITERAL("FOO.txt")))); } -TEST(UnverifiedDownloadFieldTrialTest, DisableSBTypesAndByParameter) { +// Verify functionality when all parameters are specified. +TEST(UnverifiedDownloadFieldTrialTest, WhitelistVsBlacklistVsSBTypes) { FieldTrialParameters parameters; parameters[kUnverifiedDownloadFieldTrialBlacklistParam] = ".abc,.def"; parameters[kUnverifiedDownloadFieldTrialWhitelistParam] = ".xyz"; + parameters[kUnverifiedDownloadFieldTrialBlockSBTypesParam] = "*"; ScopedFieldTrialState field_trial( - kUnverifiedDownloadFieldTrialDisableSBTypesAndByParameter, parameters); + kUnverifiedDownloadFieldTrialDisableByParameter, parameters); EXPECT_TRUE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( base::FilePath(kSafeFilename))); @@ -186,14 +243,13 @@ base::FilePath(FILE_PATH_LITERAL("foo.def")))); } -// Verify that a whitelist is able to override the SafeBrowsing file type list. -TEST(UnverifiedDownloadFieldTrialTest, - DisableSBTypesAndByParameter_OverrideSB) { +// Verify that block_sb_types parameter being empty is equivalent to it not +// being specified. +TEST(UnverifiedDownloadFieldTrialTest, DisableSBTypesEmpty) { FieldTrialParameters parameters; - parameters[kUnverifiedDownloadFieldTrialBlacklistParam] = ".abc,.def"; - parameters[kUnverifiedDownloadFieldTrialWhitelistParam] = ".exe"; + parameters[kUnverifiedDownloadFieldTrialBlockSBTypesParam] = ""; ScopedFieldTrialState field_trial( - kUnverifiedDownloadFieldTrialDisableSBTypesAndByParameter, parameters); + kUnverifiedDownloadFieldTrialDisableByParameter, parameters); EXPECT_TRUE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( base::FilePath(kSafeFilename))); @@ -201,4 +257,39 @@ base::FilePath(kHandledFilename))); } +// Verify that a whitelist is able to override the SafeBrowsing file type list. +TEST(UnverifiedDownloadFieldTrialTest, ListsOverrideSBTypes) { + FieldTrialParameters parameters; + parameters[kUnverifiedDownloadFieldTrialBlacklistParam] = ".abc,.def"; + parameters[kUnverifiedDownloadFieldTrialWhitelistParam] = ".exe"; + parameters[kUnverifiedDownloadFieldTrialBlockSBTypesParam] = "*"; + ScopedFieldTrialState field_trial( + kUnverifiedDownloadFieldTrialDisableByParameter, parameters); + + EXPECT_TRUE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( + base::FilePath(kSafeFilename))); + EXPECT_TRUE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( + base::FilePath(kHandledFilename))); + EXPECT_FALSE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( + base::FilePath(FILE_PATH_LITERAL("foo.abc")))); +} + +// Verify that the field trial is only sensitive to the prefix of the group +// name. +TEST(UnverifiedDownloadFieldTrialTest, FieldTrialGroupPrefix) { + FieldTrialParameters parameters; + parameters[kUnverifiedDownloadFieldTrialBlacklistParam] = ".abc,.def"; + parameters[kUnverifiedDownloadFieldTrialBlockSBTypesParam] = "*"; + ScopedFieldTrialState field_trial( + std::string(kUnverifiedDownloadFieldTrialDisableByParameter) + "FooBar", + parameters); + + EXPECT_TRUE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( + base::FilePath(kSafeFilename))); + EXPECT_FALSE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( + base::FilePath(kHandledFilename))); + EXPECT_FALSE(safe_browsing::IsUnverifiedDownloadAllowedByFieldTrial( + base::FilePath(FILE_PATH_LITERAL("foo.abc")))); +} + } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/unverified_download_policy.cc b/chrome/browser/safe_browsing/unverified_download_policy.cc index 17e74ffa..c7ff6b6 100644 --- a/chrome/browser/safe_browsing/unverified_download_policy.cc +++ b/chrome/browser/safe_browsing/unverified_download_policy.cc
@@ -4,26 +4,96 @@ #include "chrome/browser/safe_browsing/unverified_download_policy.h" +#include "base/bind.h" +#include "base/callback.h" #include "base/files/file_path.h" #include "base/metrics/sparse_histogram.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/safe_browsing/database_manager.h" +#include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/safe_browsing/unverified_download_field_trial.h" #include "chrome/common/safe_browsing/download_protection_util.h" +#include "content/public/browser/browser_thread.h" namespace safe_browsing { -bool IsUnverifiedDownloadAllowed(const base::FilePath& file) { - // Currently, the policy is determined entirely by a field trial. - bool is_allowed = IsUnverifiedDownloadAllowedByFieldTrial(file); +namespace { + +void RespondWithPolicy( + const base::FilePath& file, + const UnverifiedDownloadCheckCompletionCallback& callback, + UnverifiedDownloadPolicy policy) { int uma_file_type = download_protection_util::GetSBClientDownloadExtensionValueForUMA(file); - if (is_allowed) { + if (policy == UnverifiedDownloadPolicy::ALLOWED) { UMA_HISTOGRAM_SPARSE_SLOWLY("SafeBrowsing.UnverifiedDownloads.Allowed", uma_file_type); } else { UMA_HISTOGRAM_SPARSE_SLOWLY("SafeBrowsing.UnverifiedDownloads.Blocked", uma_file_type); } - return is_allowed; + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + base::Bind(callback, policy)); +} + +void CheckFieldTrialOnAnyThread( + const base::FilePath& file, + const UnverifiedDownloadCheckCompletionCallback& callback) { + bool is_allowed = IsUnverifiedDownloadAllowedByFieldTrial(file); + RespondWithPolicy(file, callback, is_allowed + ? UnverifiedDownloadPolicy::ALLOWED + : UnverifiedDownloadPolicy::DISALLOWED); +} + +void CheckWhitelistOnIOThread( + scoped_refptr<SafeBrowsingService> service, + const GURL& requestor, + const base::FilePath& file, + const UnverifiedDownloadCheckCompletionCallback& callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + int uma_file_type = + download_protection_util::GetSBClientDownloadExtensionValueForUMA(file); + + if (!service || !service->enabled()) { + // If the SafeBrowsing service was disabled, don't try to check against the + // field trial list. Instead allow the download. We are assuming that if the + // SafeBrowsing service was disabled for this user, then we shouldn't + // interefere with unverified downloads. + UMA_HISTOGRAM_SPARSE_SLOWLY( + "SafeBrowsing.UnverifiedDownloads.AllowedDueToDisabledService", + uma_file_type); + RespondWithPolicy(file, callback, UnverifiedDownloadPolicy::ALLOWED); + return; + } + + if (service->database_manager() && + service->database_manager()->MatchDownloadWhitelistUrl(requestor)) { + UMA_HISTOGRAM_SPARSE_SLOWLY( + "SafeBrowsing.UnverifiedDownloads.AllowedByWhitelist", uma_file_type); + RespondWithPolicy(file, callback, UnverifiedDownloadPolicy::ALLOWED); + return; + } + + CheckFieldTrialOnAnyThread(file, callback); +} + +} // namespace + +void CheckUnverifiedDownloadPolicy( + const GURL& requestor, + const base::FilePath& file, + const UnverifiedDownloadCheckCompletionCallback& callback) { + if (requestor.is_valid()) { + scoped_refptr<SafeBrowsingService> service = + g_browser_process->safe_browsing_service(); + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&CheckWhitelistOnIOThread, service, requestor, file, + callback)); + return; + } + + CheckFieldTrialOnAnyThread(file, callback); } } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/unverified_download_policy.h b/chrome/browser/safe_browsing/unverified_download_policy.h index 081a070..170e92bf 100644 --- a/chrome/browser/safe_browsing/unverified_download_policy.h +++ b/chrome/browser/safe_browsing/unverified_download_policy.h
@@ -5,15 +5,27 @@ #ifndef CHROME_BROWSER_SAFE_BROWSING_UNVERIFIED_DOWNLOAD_POLICY_H_ #define CHROME_BROWSER_SAFE_BROWSING_UNVERIFIED_DOWNLOAD_POLICY_H_ +#include "base/callback_forward.h" + +class GURL; + namespace base { class FilePath; } namespace safe_browsing { -// Returns true if |file| is allowed to be downloaded without invoking -// SafeBrowsing to verify the contents and source URL. -bool IsUnverifiedDownloadAllowed(const base::FilePath& file); +enum class UnverifiedDownloadPolicy { ALLOWED, DISALLOWED }; + +using UnverifiedDownloadCheckCompletionCallback = + base::Callback<void(UnverifiedDownloadPolicy)>; + +// Invokes |callback| on the current thread with the effective download policy +// for an unverified download of |file| by |requestor|. +void CheckUnverifiedDownloadPolicy( + const GURL& requestor, + const base::FilePath& file, + const UnverifiedDownloadCheckCompletionCallback& callback); } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/unverified_download_policy_unittest.cc b/chrome/browser/safe_browsing/unverified_download_policy_unittest.cc new file mode 100644 index 0000000..94593f8b --- /dev/null +++ b/chrome/browser/safe_browsing/unverified_download_policy_unittest.cc
@@ -0,0 +1,186 @@ +// Copyright 2015 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/safe_browsing/unverified_download_policy.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/callback_helpers.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/prefs/testing_pref_service.h" +#include "base/run_loop.h" +#include "chrome/browser/safe_browsing/safe_browsing_service.h" +#include "chrome/browser/safe_browsing/test_database_manager.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace safe_browsing { + +namespace { + +class FakeDatabaseManager : public TestSafeBrowsingDatabaseManager { + public: + bool IsSupported() const override { return true; } + + bool MatchDownloadWhitelistUrl(const GURL& url) override { + return url.SchemeIsHTTPOrHTTPS() && url.host() == "supported.example.com"; + } + + protected: + ~FakeDatabaseManager() override {} +}; + +class TestSafeBrowsingService : public SafeBrowsingService { + public: + SafeBrowsingDatabaseManager* CreateDatabaseManager() override { + return new FakeDatabaseManager(); + } + + protected: + ~TestSafeBrowsingService() override {} +}; + +class TestSafeBrowsingServiceFactory : public SafeBrowsingServiceFactory { + public: + SafeBrowsingService* CreateSafeBrowsingService() override { + return new TestSafeBrowsingService(); + } +}; + +class CompletionCallback { + public: + CompletionCallback() {} + + UnverifiedDownloadCheckCompletionCallback GetCallback() { + completed_ = false; + completion_closure_.Reset(); + return base::Bind(&CompletionCallback::OnUnverifiedDownloadPolicyAvailable, + base::Unretained(this)); + } + + UnverifiedDownloadPolicy WaitForResult() { + if (!completed_) { + base::RunLoop run_loop; + completion_closure_ = run_loop.QuitClosure(); + run_loop.Run(); + } + return result_; + } + + private: + void OnUnverifiedDownloadPolicyAvailable(UnverifiedDownloadPolicy policy) { + result_ = policy; + completed_ = true; + if (!completion_closure_.is_null()) + base::ResetAndReturn(&completion_closure_).Run(); + } + + bool completed_ = false; + base::Closure completion_closure_; + UnverifiedDownloadPolicy result_ = UnverifiedDownloadPolicy::DISALLOWED; +}; + +class UnverifiedDownloadPolicyTest : public ::testing::Test { + public: + void SetUp() override { + SafeBrowsingService::RegisterFactory(&test_safe_browsing_service_factory_); + testing_safe_browsing_service_ = + SafeBrowsingService::CreateSafeBrowsingService(); + TestingBrowserProcess* browser_process = TestingBrowserProcess::GetGlobal(); + browser_process->SetSafeBrowsingService( + testing_safe_browsing_service_.get()); + browser_process->safe_browsing_service()->Initialize(); + base::RunLoop().RunUntilIdle(); + + testing_profile_manager_.reset( + new TestingProfileManager(TestingBrowserProcess::GetGlobal())); + ASSERT_TRUE(testing_profile_manager_->SetUp()); + + testing_profile_ = testing_profile_manager_->CreateTestingProfile("foo"); + testing_profile_->GetPrefs()->SetBoolean(prefs::kSafeBrowsingEnabled, true); + } + + void TearDown() override { + TestingBrowserProcess* browser_process = TestingBrowserProcess::GetGlobal(); + browser_process->safe_browsing_service()->ShutDown(); + browser_process->SetSafeBrowsingService(nullptr); + testing_safe_browsing_service_ = nullptr; + SafeBrowsingService::RegisterFactory(nullptr); + base::RunLoop().RunUntilIdle(); + } + + protected: + content::TestBrowserThreadBundle thread_bundle_; + TestSafeBrowsingServiceFactory test_safe_browsing_service_factory_; + scoped_ptr<TestingProfileManager> testing_profile_manager_; + scoped_refptr<SafeBrowsingService> testing_safe_browsing_service_; + TestingProfile* testing_profile_ = nullptr; +}; + +} // namespace + +// Verify that SafeBrowsing whitelists can override field trials. +TEST_F(UnverifiedDownloadPolicyTest, Whitelist) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kDisallowUncheckedDangerousDownloads); + + base::FilePath test_file_path(FILE_PATH_LITERAL("foo.exe")); + + CompletionCallback completion_callback; + CheckUnverifiedDownloadPolicy(GURL(), test_file_path, + completion_callback.GetCallback()); + EXPECT_EQ(UnverifiedDownloadPolicy::DISALLOWED, + completion_callback.WaitForResult()); + + // Not http/s and hence isn't covered by the whitelist. + CheckUnverifiedDownloadPolicy(GURL("ftp://supported.example.com/foo/bar"), + test_file_path, + completion_callback.GetCallback()); + EXPECT_EQ(UnverifiedDownloadPolicy::DISALLOWED, + completion_callback.WaitForResult()); + + CheckUnverifiedDownloadPolicy(GURL("http://supported.example.com/foo/bar"), + test_file_path, + completion_callback.GetCallback()); + EXPECT_EQ(UnverifiedDownloadPolicy::ALLOWED, + completion_callback.WaitForResult()); + + CheckUnverifiedDownloadPolicy(GURL("http://unsupported.example.com/foo/bar"), + test_file_path, + completion_callback.GetCallback()); + EXPECT_EQ(UnverifiedDownloadPolicy::DISALLOWED, + completion_callback.WaitForResult()); + + CheckUnverifiedDownloadPolicy(GURL("https://supported.example.com/foo/bar"), + test_file_path, + completion_callback.GetCallback()); + EXPECT_EQ(UnverifiedDownloadPolicy::ALLOWED, + completion_callback.WaitForResult()); +} + +// Verify behavior when the SafeBrowsing service is disabled. +TEST_F(UnverifiedDownloadPolicyTest, ServiceDisabled) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kDisallowUncheckedDangerousDownloads); + + testing_profile_->GetPrefs()->SetBoolean(prefs::kSafeBrowsingEnabled, false); + base::RunLoop().RunUntilIdle(); + + base::FilePath test_file_path(FILE_PATH_LITERAL("foo.exe")); + + CompletionCallback completion_callback; + CheckUnverifiedDownloadPolicy(GURL("http://supported.example.com/foo/bar"), + test_file_path, + completion_callback.GetCallback()); + EXPECT_EQ(UnverifiedDownloadPolicy::ALLOWED, + completion_callback.WaitForResult()); +} + +} // namespace safe_browsing
diff --git a/chrome/browser/services/gcm/fake_gcm_profile_service.cc b/chrome/browser/services/gcm/fake_gcm_profile_service.cc index e0530d56..eeba262 100644 --- a/chrome/browser/services/gcm/fake_gcm_profile_service.cc +++ b/chrome/browser/services/gcm/fake_gcm_profile_service.cc
@@ -12,6 +12,7 @@ #include "base/strings/stringprintf.h" #include "base/thread_task_runner_handle.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" #include "components/gcm_driver/fake_gcm_client_factory.h" #include "components/gcm_driver/fake_gcm_driver.h" #include "components/gcm_driver/gcm_driver.h" @@ -104,7 +105,9 @@ content::BrowserContext* context) { Profile* profile = static_cast<Profile*>(context); scoped_ptr<FakeGCMProfileService> service(new FakeGCMProfileService(profile)); - service->SetDriverForTesting(new CustomFakeGCMDriver(service.get())); + service->SetDriverForTesting( + LoginUIServiceFactory::GetShowLoginPopupCallbackForProfile(profile), + new CustomFakeGCMDriver(service.get())); return service.Pass(); }
diff --git a/chrome/browser/services/gcm/fake_gcm_profile_service.h b/chrome/browser/services/gcm/fake_gcm_profile_service.h index 499bd83..a76035b 100644 --- a/chrome/browser/services/gcm/fake_gcm_profile_service.h +++ b/chrome/browser/services/gcm/fake_gcm_profile_service.h
@@ -9,8 +9,10 @@ #include <vector> #include "base/memory/scoped_ptr.h" -#include "chrome/browser/services/gcm/gcm_profile_service.h" #include "components/gcm_driver/gcm_driver.h" +#include "components/gcm_driver/gcm_profile_service.h" + +class Profile; namespace content { class BrowserContext;
diff --git a/chrome/browser/services/gcm/gcm_profile_service.cc b/chrome/browser/services/gcm/gcm_profile_service.cc deleted file mode 100644 index 0f9650b..0000000 --- a/chrome/browser/services/gcm/gcm_profile_service.cc +++ /dev/null
@@ -1,206 +0,0 @@ -// Copyright (c) 2013 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/services/gcm/gcm_profile_service.h" - -#include <vector> - -#include "base/logging.h" -#include "base/prefs/pref_service.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/common/chrome_constants.h" -#include "components/gcm_driver/gcm_driver.h" -#include "components/pref_registry/pref_registry_syncable.h" - -#if defined(OS_ANDROID) -#include "base/sequenced_task_runner.h" -#include "base/threading/sequenced_worker_pool.h" -#include "components/gcm_driver/gcm_driver_android.h" -#include "content/public/browser/browser_thread.h" -#else -#include "base/bind.h" -#include "base/files/file_path.h" -#include "base/memory/weak_ptr.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" -#include "chrome/browser/signin/signin_manager_factory.h" -#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" -#include "chrome/common/channel_info.h" -#include "components/gcm_driver/gcm_account_tracker.h" -#include "components/gcm_driver/gcm_channel_status_syncer.h" -#include "components/gcm_driver/gcm_client_factory.h" -#include "components/gcm_driver/gcm_desktop_utils.h" -#include "components/gcm_driver/gcm_driver_desktop.h" -#include "components/signin/core/browser/profile_identity_provider.h" -#include "components/signin/core/browser/signin_manager.h" -#include "content/public/browser/browser_thread.h" -#include "google_apis/gaia/account_tracker.h" -#include "google_apis/gaia/identity_provider.h" -#include "net/url_request/url_request_context_getter.h" -#endif - -namespace gcm { - -#if !defined(OS_ANDROID) -// Identity observer only has actual work to do when the user is actually signed -// in. It ensures that account tracker is taking -class GCMProfileService::IdentityObserver : public IdentityProvider::Observer { - public: - IdentityObserver(Profile* profile, GCMDriver* driver); - ~IdentityObserver() override; - - // IdentityProvider::Observer: - void OnActiveAccountLogin() override; - void OnActiveAccountLogout() override; - - private: - void StartAccountTracker(); - - Profile* profile_; - GCMDriver* driver_; - scoped_ptr<IdentityProvider> identity_provider_; - scoped_ptr<GCMAccountTracker> gcm_account_tracker_; - - // The account ID that this service is responsible for. Empty when the service - // is not running. - std::string account_id_; - - base::WeakPtrFactory<GCMProfileService::IdentityObserver> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(IdentityObserver); -}; - -GCMProfileService::IdentityObserver::IdentityObserver(Profile* profile, - GCMDriver* driver) - : profile_(profile), driver_(driver), weak_ptr_factory_(this) { - identity_provider_.reset(new ProfileIdentityProvider( - SigninManagerFactory::GetForProfile(profile), - ProfileOAuth2TokenServiceFactory::GetForProfile(profile), - LoginUIServiceFactory::GetShowLoginPopupCallbackForProfile(profile))); - identity_provider_->AddObserver(this); - - OnActiveAccountLogin(); - StartAccountTracker(); -} - -GCMProfileService::IdentityObserver::~IdentityObserver() { - if (gcm_account_tracker_) - gcm_account_tracker_->Shutdown(); - identity_provider_->RemoveObserver(this); -} - -void GCMProfileService::IdentityObserver::OnActiveAccountLogin() { - // This might be called multiple times when the password changes. - const std::string account_id = identity_provider_->GetActiveAccountId(); - if (account_id == account_id_) - return; - account_id_ = account_id; - - // Still need to notify GCMDriver for UMA purpose. - driver_->OnSignedIn(); -} - -void GCMProfileService::IdentityObserver::OnActiveAccountLogout() { - account_id_.clear(); - - // Still need to notify GCMDriver for UMA purpose. - driver_->OnSignedOut(); -} - -void GCMProfileService::IdentityObserver::StartAccountTracker() { - if (gcm_account_tracker_) - return; - - scoped_ptr<gaia::AccountTracker> gaia_account_tracker( - new gaia::AccountTracker(identity_provider_.get(), - profile_->GetRequestContext())); - - gcm_account_tracker_.reset( - new GCMAccountTracker(gaia_account_tracker.Pass(), driver_)); - - gcm_account_tracker_->Start(); -} - -#endif // !defined(OS_ANDROID) - -// static -bool GCMProfileService::IsGCMEnabled(Profile* profile) { -#if defined(OS_ANDROID) - return true; -#else - return profile->GetPrefs()->GetBoolean(gcm::prefs::kGCMChannelStatus); -#endif // defined(OS_ANDROID) -} - -#if defined(OS_ANDROID) -GCMProfileService::GCMProfileService(Profile* profile) - : profile_(profile) { - DCHECK(!profile->IsOffTheRecord()); - - scoped_refptr<base::SequencedWorkerPool> worker_pool( - content::BrowserThread::GetBlockingPool()); - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner( - worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( - worker_pool->GetSequenceToken(), - base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); - - driver_.reset(new GCMDriverAndroid( - profile_->GetPath().Append(chrome::kGCMStoreDirname), - blocking_task_runner)); -} -#else -GCMProfileService::GCMProfileService( - Profile* profile, - scoped_ptr<GCMClientFactory> gcm_client_factory) - : profile_(profile) { - DCHECK(!profile->IsOffTheRecord()); - - base::SequencedWorkerPool* worker_pool = - content::BrowserThread::GetBlockingPool(); - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner( - worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( - worker_pool->GetSequenceToken(), - base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); - - driver_ = CreateGCMDriverDesktop( - gcm_client_factory.Pass(), - profile_->GetPrefs(), - profile_->GetPath().Append(chrome::kGCMStoreDirname), - profile_->GetRequestContext(), - chrome::GetChannel(), - content::BrowserThread::GetMessageLoopProxyForThread( - content::BrowserThread::UI), - content::BrowserThread::GetMessageLoopProxyForThread( - content::BrowserThread::IO), - blocking_task_runner); - - identity_observer_.reset(new IdentityObserver(profile, driver_.get())); -} -#endif // defined(OS_ANDROID) - -GCMProfileService::GCMProfileService() - : profile_(NULL) { -} - -GCMProfileService::~GCMProfileService() { -} - -void GCMProfileService::Shutdown() { -#if !defined(OS_ANDROID) - identity_observer_.reset(); -#endif // !defined(OS_ANDROID) - if (driver_) { - driver_->Shutdown(); - driver_.reset(); - } -} - -void GCMProfileService::SetDriverForTesting(GCMDriver* driver) { - driver_.reset(driver); -#if !defined(OS_ANDROID) - if (identity_observer_) - identity_observer_.reset(new IdentityObserver(profile_, driver)); -#endif // !defined(OS_ANDROID) -} - -} // namespace gcm
diff --git a/chrome/browser/services/gcm/gcm_profile_service.h b/chrome/browser/services/gcm/gcm_profile_service.h deleted file mode 100644 index 7eba5eaf..0000000 --- a/chrome/browser/services/gcm/gcm_profile_service.h +++ /dev/null
@@ -1,73 +0,0 @@ -// Copyright (c) 2013 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_SERVICES_GCM_GCM_PROFILE_SERVICE_H_ -#define CHROME_BROWSER_SERVICES_GCM_GCM_PROFILE_SERVICE_H_ - -#include <string> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "components/keyed_service/core/keyed_service.h" - -class Profile; - -namespace user_prefs { -class PrefRegistrySyncable; -} - -namespace gcm { - -class GCMClientFactory; -class GCMDriver; - -#if defined(OS_CHROMEOS) -class GCMConnectionObserver; -#endif - -// Providing GCM service, via GCMDriver, to a profile. -class GCMProfileService : public KeyedService { - public: - // Returns whether GCM is enabled for |profile|. - static bool IsGCMEnabled(Profile* profile); - -#if defined(OS_ANDROID) - explicit GCMProfileService(Profile* profile); -#else - GCMProfileService(Profile* profile, - scoped_ptr<GCMClientFactory> gcm_client_factory); -#endif - ~GCMProfileService() override; - - // KeyedService: - void Shutdown() override; - - // For testing purpose. - void SetDriverForTesting(GCMDriver* driver); - - GCMDriver* driver() const { return driver_.get(); } - - protected: - // Used for constructing fake GCMProfileService for testing purpose. - GCMProfileService(); - - private: - // The profile which owns this object. - Profile* profile_; - - scoped_ptr<GCMDriver> driver_; - - // Used for both account tracker and GCM.UserSignedIn UMA. -#if !defined(OS_ANDROID) - class IdentityObserver; - scoped_ptr<IdentityObserver> identity_observer_; -#endif - - DISALLOW_COPY_AND_ASSIGN(GCMProfileService); -}; - -} // namespace gcm - -#endif // CHROME_BROWSER_SERVICES_GCM_GCM_PROFILE_SERVICE_H_
diff --git a/chrome/browser/services/gcm/gcm_profile_service_factory.cc b/chrome/browser/services/gcm/gcm_profile_service_factory.cc index 561a2fd..dbbe54c 100644 --- a/chrome/browser/services/gcm/gcm_profile_service_factory.cc +++ b/chrome/browser/services/gcm/gcm_profile_service_factory.cc
@@ -7,10 +7,14 @@ #include "base/memory/scoped_ptr.h" #include "chrome/browser/profiles/incognito_helpers.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/services/gcm/gcm_profile_service.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/common/channel_info.h" +#include "components/gcm_driver/gcm_profile_service.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "components/signin/core/browser/profile_identity_provider.h" +#include "components/signin/core/browser/signin_manager.h" +#include "content/public/browser/browser_thread.h" #if !defined(OS_ANDROID) #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" @@ -51,12 +55,31 @@ KeyedService* GCMProfileServiceFactory::BuildServiceInstanceFor( content::BrowserContext* context) const { + Profile* profile = Profile::FromBrowserContext(context); + DCHECK(!profile->IsOffTheRecord()); + + base::SequencedWorkerPool* worker_pool = + content::BrowserThread::GetBlockingPool(); + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner( + worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( + worker_pool->GetSequenceToken(), + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); #if defined(OS_ANDROID) - return new GCMProfileService(Profile::FromBrowserContext(context)); + return new GCMProfileService(profile->GetPath(), blocking_task_runner); #else return new GCMProfileService( - Profile::FromBrowserContext(context), - scoped_ptr<GCMClientFactory>(new GCMClientFactory)); + profile->GetPrefs(), profile->GetPath(), profile->GetRequestContext(), + chrome::GetChannel(), + scoped_ptr<ProfileIdentityProvider>(new ProfileIdentityProvider( + SigninManagerFactory::GetForProfile(profile), + ProfileOAuth2TokenServiceFactory::GetForProfile(profile), + LoginUIServiceFactory::GetShowLoginPopupCallbackForProfile(profile))), + scoped_ptr<GCMClientFactory>(new GCMClientFactory), + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::UI), + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::IO), + blocking_task_runner); #endif }
diff --git a/chrome/browser/services/gcm/gcm_profile_service_unittest.cc b/chrome/browser/services/gcm/gcm_profile_service_unittest.cc index 94f6390..2ba5b18 100644 --- a/chrome/browser/services/gcm/gcm_profile_service_unittest.cc +++ b/chrome/browser/services/gcm/gcm_profile_service_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/services/gcm/gcm_profile_service.h" +#include "components/gcm_driver/gcm_profile_service.h" #include <vector> @@ -12,6 +12,10 @@ #include "base/memory/scoped_ptr.h" #include "base/run_loop.h" #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" +#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" +#include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" +#include "chrome/common/channel_info.h" #include "chrome/test/base/testing_profile.h" #if defined(OS_CHROMEOS) #include "chromeos/dbus/dbus_thread_manager.h" @@ -23,6 +27,7 @@ #include "components/gcm_driver/gcm_client_factory.h" #include "components/gcm_driver/gcm_driver.h" #include "components/pref_registry/pref_registry_syncable.h" +#include "components/signin/core/browser/signin_manager.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_browser_thread_bundle.h" @@ -37,13 +42,30 @@ scoped_ptr<KeyedService> BuildGCMProfileService( content::BrowserContext* context) { - return make_scoped_ptr(new GCMProfileService( - Profile::FromBrowserContext(context), - scoped_ptr<GCMClientFactory>(new FakeGCMClientFactory( + Profile* profile = Profile::FromBrowserContext(context); + base::SequencedWorkerPool* worker_pool = + content::BrowserThread::GetBlockingPool(); + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner( + worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( + worker_pool->GetSequenceToken(), + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); + return make_scoped_ptr(new gcm::GCMProfileService( + profile->GetPrefs(), profile->GetPath(), profile->GetRequestContext(), + chrome::GetChannel(), + scoped_ptr<ProfileIdentityProvider>(new ProfileIdentityProvider( + SigninManagerFactory::GetForProfile(profile), + ProfileOAuth2TokenServiceFactory::GetForProfile(profile), + LoginUIServiceFactory::GetShowLoginPopupCallbackForProfile(profile))), + scoped_ptr<gcm::GCMClientFactory>(new gcm::FakeGCMClientFactory( content::BrowserThread::GetMessageLoopProxyForThread( content::BrowserThread::UI), content::BrowserThread::GetMessageLoopProxyForThread( - content::BrowserThread::IO))))); + content::BrowserThread::IO))), + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::UI), + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::IO), + blocking_task_runner)); } } // namespace
diff --git a/chrome/browser/services/gcm/instance_id/instance_id_profile_service.cc b/chrome/browser/services/gcm/instance_id/instance_id_profile_service.cc index b8d1f3c..635577f 100644 --- a/chrome/browser/services/gcm/instance_id/instance_id_profile_service.cc +++ b/chrome/browser/services/gcm/instance_id/instance_id_profile_service.cc
@@ -6,8 +6,8 @@ #include "base/logging.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/services/gcm/gcm_profile_service.h" #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" +#include "components/gcm_driver/gcm_profile_service.h" #include "components/gcm_driver/instance_id/instance_id_driver.h" namespace instance_id { @@ -15,7 +15,7 @@ // static bool InstanceIDProfileService::IsInstanceIDEnabled(Profile* profile) { // Instance ID depends on GCM which has to been enabled. - if (!gcm::GCMProfileService::IsGCMEnabled(profile)) + if (!gcm::GCMProfileService::IsGCMEnabled(profile->GetPrefs())) return false; return InstanceIDDriver::IsInstanceIDEnabled();
diff --git a/chrome/browser/signin/easy_unlock_service_regular.cc b/chrome/browser/signin/easy_unlock_service_regular.cc index e69ebd1..a8e0d52 100644 --- a/chrome/browser/signin/easy_unlock_service_regular.cc +++ b/chrome/browser/signin/easy_unlock_service_regular.cc
@@ -14,7 +14,6 @@ #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/services/gcm/gcm_profile_service.h" #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" #include "chrome/browser/signin/chrome_proximity_auth_client.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" @@ -23,6 +22,7 @@ #include "chrome/common/extensions/extension_constants.h" #include "chrome/common/pref_names.h" #include "chromeos/login/user_names.h" +#include "components/gcm_driver/gcm_profile_service.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/cryptauth/cryptauth_access_token_fetcher.h" @@ -133,6 +133,7 @@ dict->SetString("name", device.name); dict->SetString("psk", b64_psk); dict->SetString("bluetoothAddress", device.bluetooth_address); + dict->SetInteger("bluetoothType", static_cast<int>(device.bluetooth_type)); dict->SetString("permitId", "permit://google.com/easyunlock/v1/" + proximity_auth_client()->GetAccountId()); dict->SetString("permitRecord.id", b64_public_key);
diff --git a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc index 279b7a7e..a8909e89 100644 --- a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc +++ b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc
@@ -430,11 +430,9 @@ proximity_auth::Base64UrlDecode(devices[0].public_key, &decoded_public_key); proximity_auth::Base64UrlDecode(devices[0].psk, &decoded_psk); proximity_auth::Base64UrlDecode(devices[0].challenge, &decoded_challenge); - - // TODO(tengs): We need to store the Bluetooth type with the TPM data. proximity_auth::RemoteDevice::BluetoothType bluetooth_type = - base::CommandLine::ForCurrentProcess()->HasSwitch( - proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery) + devices[0].bluetooth_type == + chromeos::EasyUnlockDeviceKeyData::BLUETOOTH_LE ? proximity_auth::RemoteDevice::BLUETOOTH_LE : proximity_auth::RemoteDevice::BLUETOOTH_CLASSIC;
diff --git a/chrome/browser/signin/oauth2_token_service_delegate_android.cc b/chrome/browser/signin/oauth2_token_service_delegate_android.cc index 9dca879..65f0b11 100644 --- a/chrome/browser/signin/oauth2_token_service_delegate_android.cc +++ b/chrome/browser/signin/oauth2_token_service_delegate_android.cc
@@ -288,52 +288,52 @@ jobject obj, jstring j_current_acc, jboolean j_force_notifications) { - std::string signed_in_account; + std::string signed_in_account_name; DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts from java"; if (j_current_acc) - signed_in_account = ConvertJavaStringToUTF8(env, j_current_acc); - if (!signed_in_account.empty()) - signed_in_account = gaia::CanonicalizeEmail(signed_in_account); + signed_in_account_name = ConvertJavaStringToUTF8(env, j_current_acc); + if (!signed_in_account_name.empty()) + signed_in_account_name = gaia::CanonicalizeEmail(signed_in_account_name); // Clear any auth errors so that client can retry to get access tokens. errors_.clear(); - ValidateAccounts(MapAccountNameToAccountId(signed_in_account), + ValidateAccounts(MapAccountNameToAccountId(signed_in_account_name), j_force_notifications != JNI_FALSE); } void OAuth2TokenServiceDelegateAndroid::ValidateAccounts( - const std::string& signed_in_account, + const std::string& signed_in_account_id, bool force_notifications) { - std::vector<std::string> prev_stored_ids = GetAccounts(); + std::vector<std::string> curr_ids; + for (const std::string& curr_name : GetSystemAccountNames()) { + std::string curr_id(MapAccountNameToAccountId(curr_name)); + // TODO(knn): Convert to DCHECK after https://crbug.com/535211 + CHECK(!curr_id.empty()); + curr_ids.push_back(curr_id); + } + std::vector<std::string> prev_ids; - std::vector<std::string> curr_ids = GetSystemAccountNames(); - std::vector<std::string> refreshed_ids; - std::vector<std::string> revoked_ids; - bool account_validation_result = true; - - for (size_t i = 0; i < curr_ids.size(); ++i) - curr_ids[i] = MapAccountNameToAccountId(curr_ids[i]); - - for (size_t i = 0; i < prev_stored_ids.size(); ++i) { - if (ValidateAccountId(prev_stored_ids[i])) - prev_ids.push_back(prev_stored_ids[i]); + for (const std::string& prev_id : GetAccounts()) { + if (ValidateAccountId(prev_id)) + prev_ids.push_back(prev_id); } DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:" - << " sigined_in_account=" << signed_in_account + << " sigined_in_account_id=" << signed_in_account_id << " prev_ids=" << prev_ids.size() << " curr_ids=" << curr_ids.size() << " force=" << (force_notifications ? "true" : "false"); - account_validation_result = - ValidateAccounts(signed_in_account, prev_ids, curr_ids, refreshed_ids, - revoked_ids, force_notifications); + std::vector<std::string> refreshed_ids; + std::vector<std::string> revoked_ids; + bool currently_signed_in = + ValidateAccounts(signed_in_account_id, prev_ids, curr_ids, &refreshed_ids, + &revoked_ids, force_notifications); ScopedBatchChange batch(this); - JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jobjectArray> java_accounts; - if (account_validation_result) { + if (currently_signed_in) { java_accounts = base::android::ToJavaArrayOfStrings(env, curr_ids); } else { java_accounts = @@ -345,14 +345,10 @@ Java_OAuth2TokenService_saveStoredAccounts( env, base::android::GetApplicationContext(), java_accounts.obj()); - for (std::vector<std::string>::iterator it = refreshed_ids.begin(); - it != refreshed_ids.end(); it++) { - FireRefreshTokenAvailable(*it); - } - for (std::vector<std::string>::iterator it = revoked_ids.begin(); - it != revoked_ids.end(); it++) { - FireRefreshTokenRevoked(*it); - } + for (const std::string& refreshed_id : refreshed_ids) + FireRefreshTokenAvailable(refreshed_id); + for (const std::string& revoked_id : revoked_ids) + FireRefreshTokenRevoked(revoked_id); if (fire_refresh_token_loaded_ == RT_WAIT_FOR_VALIDATION) { fire_refresh_token_loaded_ = RT_LOADED; FireRefreshTokensLoaded(); @@ -363,89 +359,78 @@ // Clear accounts no longer exist on device from AccountTrackerService. std::vector<AccountInfo> accounts_info = account_tracker_service_->GetAccounts(); - for (auto info : accounts_info) { - auto it = curr_ids.begin(); - for (; it != curr_ids.end(); ++it) { - if (*it == info.account_id) - break; - } - if (it == curr_ids.end()) + for (const AccountInfo& info : accounts_info) { + if (std::find(curr_ids.begin(), curr_ids.end(), info.account_id) == + curr_ids.end()) account_tracker_service_->RemoveAccount(info.account_id); } // No need to wait for SigninManager to finish migration if not signed in. if (account_tracker_service_->GetMigrationState() == AccountTrackerService::MIGRATION_IN_PROGRESS && - signed_in_account.empty()) { + signed_in_account_id.empty()) { account_tracker_service_->SetMigrationDone(); } } bool OAuth2TokenServiceDelegateAndroid::ValidateAccounts( - const std::string& signed_in_account, - const std::vector<std::string>& prev_account_ids, - const std::vector<std::string>& curr_account_ids, - std::vector<std::string>& refreshed_ids, - std::vector<std::string>& revoked_ids, + const std::string& signed_in_id, + const std::vector<std::string>& prev_ids, + const std::vector<std::string>& curr_ids, + std::vector<std::string>* refreshed_ids, + std::vector<std::string>* revoked_ids, bool force_notifications) { - if (std::find(curr_account_ids.begin(), curr_account_ids.end(), - signed_in_account) != curr_account_ids.end()) { - // Test to see if an account is removed from the Android AccountManager. - // If so, invoke FireRefreshTokenRevoked to notify the reconcilor. - for (std::vector<std::string>::const_iterator it = prev_account_ids.begin(); - it != prev_account_ids.end(); it++) { - if (*it == signed_in_account) + bool currently_signed_in = std::find(curr_ids.begin(), curr_ids.end(), + signed_in_id) != curr_ids.end(); + if (currently_signed_in) { + // Revoke token for ids that have been removed from the device. + for (const std::string& prev_id : prev_ids) { + if (prev_id == signed_in_id) continue; - - if (std::find(curr_account_ids.begin(), curr_account_ids.end(), *it) == - curr_account_ids.end()) { + if (std::find(curr_ids.begin(), curr_ids.end(), prev_id) == + curr_ids.end()) { DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:" - << "revoked=" << *it; - revoked_ids.push_back(*it); + << "revoked=" << prev_id; + revoked_ids->push_back(prev_id); } } + // Refresh token for new ids or all ids if |force_notifications|. if (force_notifications || - std::find(prev_account_ids.begin(), prev_account_ids.end(), - signed_in_account) == prev_account_ids.end()) { + std::find(prev_ids.begin(), prev_ids.end(), signed_in_id) == + prev_ids.end()) { // Always fire the primary signed in account first. DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:" - << "refreshed=" << signed_in_account; - refreshed_ids.push_back(signed_in_account); + << "refreshed=" << signed_in_id; + refreshed_ids->push_back(signed_in_id); } - - for (std::vector<std::string>::const_iterator it = curr_account_ids.begin(); - it != curr_account_ids.end(); it++) { - if (*it != signed_in_account) { - if (force_notifications || - std::find(prev_account_ids.begin(), prev_account_ids.end(), *it) == - prev_account_ids.end()) { - DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:" - << "refreshed=" << *it; - refreshed_ids.push_back(*it); - } + for (const std::string& curr_id : curr_ids) { + if (curr_id == signed_in_id) + continue; + if (force_notifications || + std::find(prev_ids.begin(), prev_ids.end(), curr_id) == + prev_ids.end()) { + DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:" + << "refreshed=" << curr_id; + refreshed_ids->push_back(curr_id); } } - return true; } else { - // Currently signed in account does not any longer exist among accounts on - // system together with all other accounts. - if (std::find(prev_account_ids.begin(), prev_account_ids.end(), - signed_in_account) != prev_account_ids.end()) { + if (std::find(prev_ids.begin(), prev_ids.end(), signed_in_id) != + prev_ids.end()) { DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:" - << "revoked=" << signed_in_account; - revoked_ids.push_back(signed_in_account); + << "revoked=" << signed_in_id; + revoked_ids->push_back(signed_in_id); } - for (std::vector<std::string>::const_iterator it = prev_account_ids.begin(); - it != prev_account_ids.end(); it++) { - if (*it == signed_in_account) + for (const std::string& prev_id : prev_ids) { + if (prev_id == signed_in_id) continue; DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:" - << "revoked=" << *it; - revoked_ids.push_back(*it); + << "revoked=" << prev_id; + revoked_ids->push_back(prev_id); } - return false; } + return currently_signed_in; } void OAuth2TokenServiceDelegateAndroid::FireRefreshTokenAvailableFromJava( @@ -460,13 +445,18 @@ void OAuth2TokenServiceDelegateAndroid::FireRefreshTokenAvailable( const std::string& account_id) { + // TODO(knn): Convert to DCHECK after https://crbug.com/535211 + CHECK(!account_id.empty()); DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::FireRefreshTokenAvailable id=" << account_id; + std::string account_name = MapAccountIdToAccountName(account_id); + // TODO(knn): Convert to DCHECK after https://crbug.com/535211 + CHECK(!account_name.empty()); JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jstring> account_name = - ConvertUTF8ToJavaString(env, MapAccountIdToAccountName(account_id)); + ScopedJavaLocalRef<jstring> j_account_name = + ConvertUTF8ToJavaString(env, account_name); Java_OAuth2TokenService_notifyRefreshTokenAvailable(env, java_ref_.obj(), - account_name.obj()); + j_account_name.obj()); OAuth2TokenServiceDelegate::FireRefreshTokenAvailable(account_id); } @@ -482,17 +472,18 @@ void OAuth2TokenServiceDelegateAndroid::FireRefreshTokenRevoked( const std::string& account_id) { + // TODO(knn): Convert to DCHECK after https://crbug.com/535211 + CHECK(!account_id.empty()); DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::FireRefreshTokenRevoked id=" << account_id; - JNIEnv* env = AttachCurrentThread(); std::string account_name = MapAccountIdToAccountName(account_id); - // Do not crash in case of missed information. - if (!account_name.empty()) { - ScopedJavaLocalRef<jstring> account = - ConvertUTF8ToJavaString(env, account_name); - Java_OAuth2TokenService_notifyRefreshTokenRevoked(env, java_ref_.obj(), - account.obj()); - } + // TODO(knn): Convert to DCHECK after https://crbug.com/535211 + CHECK(!account_name.empty()); + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jstring> j_account_name = + ConvertUTF8ToJavaString(env, account_name); + Java_OAuth2TokenService_notifyRefreshTokenRevoked(env, java_ref_.obj(), + j_account_name.obj()); OAuth2TokenServiceDelegate::FireRefreshTokenRevoked(account_id); }
diff --git a/chrome/browser/signin/oauth2_token_service_delegate_android.h b/chrome/browser/signin/oauth2_token_service_delegate_android.h index b398f84..4bade06d 100644 --- a/chrome/browser/signin/oauth2_token_service_delegate_android.h +++ b/chrome/browser/signin/oauth2_token_service_delegate_android.h
@@ -64,7 +64,7 @@ // android account ids and check the token status of each. If // |force_notifications| is true, TokenAvailable notifications will // be sent anyway, even if the account was already known. - void ValidateAccounts(const std::string& signed_in_account, + void ValidateAccounts(const std::string& signed_in_account_id, bool force_notifications); // Triggers a notification to all observers of the OAuth2TokenService that a @@ -130,15 +130,15 @@ RT_LOADED }; - // Return whether |signed_in_account| is valid and we have access - // to all the tokens in |curr_account_ids|. If |force_notifications| is true, + // Return whether |signed_in_id| is valid and we have access + // to all the tokens in |curr_ids|. If |force_notifications| is true, // TokenAvailable notifications will be sent anyway, even if the account was // already known. - bool ValidateAccounts(const std::string& signed_in_account, - const std::vector<std::string>& prev_account_ids, - const std::vector<std::string>& curr_account_ids, - std::vector<std::string>& refreshed_ids, - std::vector<std::string>& revoked_ids, + bool ValidateAccounts(const std::string& signed_in_id, + const std::vector<std::string>& prev_ids, + const std::vector<std::string>& curr_ids, + std::vector<std::string>* refreshed_ids, + std::vector<std::string>* revoked_ids, bool force_notifications); base::android::ScopedJavaGlobalRef<jobject> java_ref_;
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc index 5ce5137..d112e92 100644 --- a/chrome/browser/sync/chrome_sync_client.cc +++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -105,6 +105,20 @@ ~SyncSessionsClientImpl() override {} // SyncSessionsClient implementation. + bookmarks::BookmarkModel* GetBookmarkModel() override { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + return BookmarkModelFactory::GetForProfile(profile_); + } + favicon::FaviconService* GetFaviconService() override { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + return FaviconServiceFactory::GetForProfile( + profile_, ServiceAccessType::EXPLICIT_ACCESS); + } + history::HistoryService* GetHistoryService() override { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + return HistoryServiceFactory::GetForProfile( + profile_, ServiceAccessType::EXPLICIT_ACCESS); + } bool ShouldSyncURL(const GURL& url) const override { if (url == GURL(chrome::kChromeUIHistoryURL)) { // The history page is treated specially as we want it to trigger syncable
diff --git a/chrome/browser/sync/chrome_sync_client.h b/chrome/browser/sync/chrome_sync_client.h index e9482f31..3713270a 100644 --- a/chrome/browser/sync/chrome_sync_client.h +++ b/chrome/browser/sync/chrome_sync_client.h
@@ -26,10 +26,8 @@ scoped_ptr<sync_driver::SyncApiComponentFactory> component_factory); ~ChromeSyncClient() override; - // Initializes the ChromeSyncClient internal state. - void Initialize(sync_driver::SyncService* sync_service) override; - // SyncClient implementation. + void Initialize(sync_driver::SyncService* sync_service) override; sync_driver::SyncService* GetSyncService() override; PrefService* GetPrefService() override; bookmarks::BookmarkModel* GetBookmarkModel() override;
diff --git a/chrome/browser/sync/profile_sync_components_factory_impl.cc b/chrome/browser/sync/profile_sync_components_factory_impl.cc index deb02f81..b0258ae7 100644 --- a/chrome/browser/sync/profile_sync_components_factory_impl.cc +++ b/chrome/browser/sync/profile_sync_components_factory_impl.cc
@@ -15,7 +15,6 @@ #include "chrome/browser/sync/glue/sync_backend_host_impl.h" #include "chrome/browser/sync/glue/theme_data_type_controller.h" #include "chrome/browser/sync/profile_sync_service.h" -#include "chrome/browser/sync/sessions/session_data_type_controller.h" #include "chrome/common/channel_info.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" @@ -41,6 +40,8 @@ #include "components/sync_driver/proxy_data_type_controller.h" #include "components/sync_driver/sync_client.h" #include "components/sync_driver/ui_data_type_controller.h" +#include "components/sync_sessions/session_data_type_controller.h" +#include "components/variations/variations_associated_data.h" #include "content/public/browser/browser_thread.h" #include "google_apis/gaia/oauth2_token_service.h" #include "google_apis/gaia/oauth2_token_service_request.h" @@ -244,9 +245,10 @@ // ProfileSyncService at this level. ProfileSyncService* pss = static_cast<ProfileSyncService*>(sync_service); sync_service->RegisterDataTypeController(new SessionDataTypeController( - error_callback, sync_client, profile_, + ui_thread, error_callback, sync_client, pss->GetSyncedWindowDelegatesGetter(), - sync_service->GetLocalDeviceInfoProvider())); + sync_service->GetLocalDeviceInfoProvider(), + prefs::kSavingBrowserHistoryDisabled)); } // Favicon sync is enabled by default. Register unless explicitly disabled.
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc index 2b3538b..bfe80ae 100644 --- a/chrome/browser/sync/profile_sync_service.cc +++ b/chrome/browser/sync/profile_sync_service.cc
@@ -27,7 +27,6 @@ #include "base/time/time.h" #include "build/build_config.h" #include "chrome/browser/browsing_data/browsing_data_helper.h" -#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h" #include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/browser/profiles/profile.h" @@ -66,13 +65,12 @@ #include "components/sync_driver/system_encryptor.h" #include "components/sync_driver/user_selectable_sync_type.h" #include "components/sync_sessions/favicon_cache.h" +#include "components/sync_sessions/session_data_type_controller.h" +#include "components/sync_sessions/sessions_sync_manager.h" #include "components/sync_sessions/sync_sessions_client.h" #include "components/syncable_prefs/pref_service_syncable.h" #include "components/version_info/version_info_values.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/notification_details.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_source.h" #include "net/cookies/cookie_monster.h" #include "net/url_request/url_request_context_getter.h" #include "sync/api/sync_error.h" @@ -183,7 +181,7 @@ } } -} // anonymous namespace +} // namespace bool ShouldShowActionOnUI( const syncer::SyncProtocolError& error) { @@ -267,12 +265,14 @@ local_device_->GetSyncUserAgent(), profile_->GetRequestContext(), browser_sync::SyncStoppedReporter::ResultCallback())); - - registrar_.Add(this, chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED, - content::Source<Profile>(profile)); - sessions_sync_manager_.reset( - new SessionsSyncManager(sync_client_->GetSyncSessionsClient(), profile, - local_device_.get(), router.Pass())); + sessions_sync_manager_.reset(new SessionsSyncManager( + sync_client_->GetSyncSessionsClient(), &sync_prefs_, local_device_.get(), + router.Pass(), + base::Bind(&ProfileSyncService::NotifyForeignSessionUpdated, + weak_factory_.GetWeakPtr()), + base::Bind(&ProfileSyncService::TriggerRefresh, + weak_factory_.GetWeakPtr(), + syncer::ModelTypeSet(syncer::SESSIONS)))); device_info_sync_service_.reset( new DeviceInfoSyncService(local_device_.get())); @@ -479,6 +479,18 @@ (*state_map)[iter->first] = iter->second.get()->state(); } +void ProfileSyncService::OnSessionRestoreComplete() { + scoped_refptr<DataTypeController> session_data_type_controller = + data_type_controllers_[syncer::SESSIONS]; + + if (!session_data_type_controller) + return; + + static_cast<browser_sync::SessionDataTypeController*>( + session_data_type_controller.get()) + ->OnSessionRestoreComplete(); +} + SyncCredentials ProfileSyncService::GetCredentials() { SyncCredentials credentials; if (backend_mode_ == SYNC) { @@ -917,14 +929,6 @@ sync_prefs_.SetCleanShutdown(true); } -void ProfileSyncService::Observe( - int type, const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK_EQ(chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED, type); - FOR_EACH_OBSERVER(sync_driver::SyncServiceObserver, observers_, - OnForeignSessionUpdated()); -} - void ProfileSyncService::StopImpl(SyncStopDataFate data_fate) { switch (data_fate) { case KEEP_DATA: @@ -967,6 +971,11 @@ OnSyncCycleCompleted()); } +void ProfileSyncService::NotifyForeignSessionUpdated() { + FOR_EACH_OBSERVER(sync_driver::SyncServiceObserver, observers_, + OnForeignSessionUpdated()); +} + void ProfileSyncService::ClearStaleErrors() { ClearUnrecoverableError(); last_actionable_error_ = SyncProtocolError();
diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h index c82f4c05..b3442d7 100644 --- a/chrome/browser/sync/profile_sync_service.h +++ b/chrome/browser/sync/profile_sync_service.h
@@ -23,7 +23,6 @@ #include "base/timer/timer.h" #include "chrome/browser/browsing_data/browsing_data_remover.h" #include "chrome/browser/sync/glue/sync_backend_host.h" -#include "chrome/browser/sync/sessions/sessions_sync_manager.h" #include "components/keyed_service/core/keyed_service.h" #include "components/signin/core/browser/signin_manager_base.h" #include "components/sync_driver/backup_rollback_controller.h" @@ -39,8 +38,6 @@ #include "components/sync_driver/sync_prefs.h" #include "components/sync_driver/sync_service.h" #include "components/sync_driver/sync_stopped_reporter.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" #include "google_apis/gaia/google_service_auth_error.h" #include "google_apis/gaia/oauth2_token_service.h" #include "net/base/backoff_entry.h" @@ -64,6 +61,7 @@ namespace browser_sync { class BackendMigrator; class FaviconCache; +class SessionsSyncManager; class SyncedWindowDelegatesGetter; } // namespace browser_sync @@ -180,7 +178,6 @@ public sync_driver::DataTypeManagerObserver, public syncer::UnrecoverableErrorHandler, public KeyedService, - public content::NotificationObserver, public OAuth2TokenService::Consumer, public OAuth2TokenService::Observer, public SigninManagerBase::Observer { @@ -345,6 +342,9 @@ void GetDataTypeControllerStates( sync_driver::DataTypeController::StateMap* state_map) const; + // Called when asynchronous session restore has completed. + void OnSessionRestoreComplete(); + // SyncFrontend implementation. void OnBackendInitialized( const syncer::WeakHandle<syncer::JsBackend>& js_backend, @@ -644,11 +644,6 @@ friend class TestProfileSyncService; FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceTest, InitialState); - // Observe notifications. - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; - // Stops the sync engine. Does NOT set IsSyncRequested to false. Use // RequestStop for that. |data_fate| controls whether the local sync data is // deleted or kept when the engine shuts down. @@ -698,6 +693,7 @@ void NotifyObservers(); void NotifySyncCycleCompleted(); + void NotifyForeignSessionUpdated(); void ClearStaleErrors(); @@ -989,8 +985,6 @@ // IsPassphrasePrompted sync preference. bool passphrase_prompt_triggered_by_version_; - content::NotificationRegistrar registrar_; - base::WeakPtrFactory<ProfileSyncService> weak_factory_; // We don't use |weak_factory_| for the StartupController because the weak
diff --git a/chrome/browser/sync/profile_sync_service_unittest.cc b/chrome/browser/sync/profile_sync_service_unittest.cc index 2789c12..463ff0a 100644 --- a/chrome/browser/sync/profile_sync_service_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_unittest.cc
@@ -39,7 +39,6 @@ #include "components/sync_driver/data_type_manager.h" #include "components/sync_driver/data_type_manager_observer.h" #include "components/sync_driver/fake_data_type_controller.h" -#include "components/sync_driver/fake_sync_client.h" #include "components/sync_driver/pref_names.h" #include "components/sync_driver/signin_manager_wrapper.h" #include "components/sync_driver/sync_api_component_factory_mock.h"
diff --git a/chrome/browser/sync/sessions/notification_service_sessions_router.h b/chrome/browser/sync/sessions/notification_service_sessions_router.h index 97394c8..af7f35f 100644 --- a/chrome/browser/sync/sessions/notification_service_sessions_router.h +++ b/chrome/browser/sync/sessions/notification_service_sessions_router.h
@@ -9,7 +9,7 @@ #include "base/callback_list.h" #include "base/memory/weak_ptr.h" -#include "chrome/browser/sync/sessions/sessions_sync_manager.h" +#include "components/sync_sessions/sessions_sync_manager.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h"
diff --git a/chrome/browser/sync/sessions/page_revisit_broadcaster.cc b/chrome/browser/sync/sessions/page_revisit_broadcaster.cc deleted file mode 100644 index ded3778..0000000 --- a/chrome/browser/sync/sessions/page_revisit_broadcaster.cc +++ /dev/null
@@ -1,132 +0,0 @@ -// Copyright 2015 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/sync/sessions/page_revisit_broadcaster.h" - -#include <string> -#include <vector> - -#include "base/memory/scoped_ptr.h" -#include "base/metrics/field_trial.h" -#include "chrome/browser/sync/sessions/sessions_sync_manager.h" -#include "components/bookmarks/browser/bookmark_model.h" -#include "components/history/core/browser/history_service.h" -#include "components/sync_sessions/revisit/bookmarks_by_url_provider_impl.h" -#include "components/sync_sessions/revisit/bookmarks_page_revisit_observer.h" -#include "components/sync_sessions/revisit/sessions_page_revisit_observer.h" -#include "components/sync_sessions/revisit/typed_url_page_revisit_observer.h" -#include "components/sync_sessions/sync_sessions_client.h" - -namespace browser_sync { - -namespace { - -// Simple implementation of ForeignSessionsProvider that delegates to -// SessionsSyncManager. It holds onto a non-owning pointer, with the assumption -// that this class is only used by classes owned by SessionsSyncManager itself. -class SessionsSyncManagerWrapper - : public sync_sessions::ForeignSessionsProvider { - public: - explicit SessionsSyncManagerWrapper(SessionsSyncManager* manager) - : manager_(manager) {} - ~SessionsSyncManagerWrapper() override{}; - bool GetAllForeignSessions( - std::vector<const sync_driver::SyncedSession*>* sessions) override { - return manager_->GetAllForeignSessions(sessions); - } - - private: - SessionsSyncManager* manager_; - DISALLOW_COPY_AND_ASSIGN(SessionsSyncManagerWrapper); -}; - -} // namespace - -PageRevisitBroadcaster::PageRevisitBroadcaster( - SessionsSyncManager* sessions, - sync_sessions::SyncSessionsClient* sessions_client, - history::HistoryService* history, - bookmarks::BookmarkModel* bookmarks) - : sessions_client_(sessions_client) { - const std::string group_name = - base::FieldTrialList::FindFullName("PageRevisitInstrumentation"); - bool shouldInstrument = group_name == "Enabled"; - if (shouldInstrument) { - revisit_observers_.push_back(new sync_sessions::SessionsPageRevisitObserver( - scoped_ptr<sync_sessions::ForeignSessionsProvider>( - new SessionsSyncManagerWrapper(sessions)))); - - revisit_observers_.push_back( - new sync_sessions::TypedUrlPageRevisitObserver(history)); - - revisit_observers_.push_back( - new sync_sessions::BookmarksPageRevisitObserver( - scoped_ptr<sync_sessions::BookmarksByUrlProvider>( - new sync_sessions::BookmarksByUrlProviderImpl(bookmarks)))); - } -} - -PageRevisitBroadcaster::~PageRevisitBroadcaster() {} - -void PageRevisitBroadcaster::OnPageVisit(const GURL& url, - const ui::PageTransition transition) { - if (sessions_client_->ShouldSyncURL(url)) { - sync_sessions::PageVisitObserver::TransitionType converted( - ConvertTransitionEnum(transition)); - for (auto* observer : revisit_observers_) { - observer->OnPageVisit(url, converted); - } - } -} - -// Static -sync_sessions::PageVisitObserver::TransitionType -PageRevisitBroadcaster::ConvertTransitionEnum( - const ui::PageTransition original) { - switch (ui::PageTransitionStripQualifier(original)) { - case ui::PAGE_TRANSITION_LINK: - if (original & ui::PAGE_TRANSITION_FROM_ADDRESS_BAR) { - return sync_sessions::PageVisitObserver::kTransitionCopyPaste; - } else { - return sync_sessions::PageVisitObserver::kTransitionPage; - } - case ui::PAGE_TRANSITION_TYPED: - return sync_sessions::PageVisitObserver::kTransitionOmniboxUrl; - - case ui::PAGE_TRANSITION_AUTO_BOOKMARK: - return sync_sessions::PageVisitObserver::kTransitionBookmark; - - case ui::PAGE_TRANSITION_AUTO_SUBFRAME: - case ui::PAGE_TRANSITION_MANUAL_SUBFRAME: - // These are not expected, we only expect top-level frame transitions. - return sync_sessions::PageVisitObserver::kTransitionUnknown; - - case ui::PAGE_TRANSITION_GENERATED: - return sync_sessions::PageVisitObserver::kTransitionOmniboxDefaultSearch; - - case ui::PAGE_TRANSITION_AUTO_TOPLEVEL: - if (original & ui::PAGE_TRANSITION_FORWARD_BACK) { - return sync_sessions::PageVisitObserver::kTransitionForwardBackward; - } else { - return sync_sessions::PageVisitObserver::kTransitionUnknown; - } - - case ui::PAGE_TRANSITION_FORM_SUBMIT: - return sync_sessions::PageVisitObserver::kTransitionPage; - - case ui::PAGE_TRANSITION_RELOAD: - // Refreshing pages also carry PAGE_TRANSITION_RELOAD but the url never - // changes so we don't expect to ever get them. - return sync_sessions::PageVisitObserver::kTransitionRestore; - - case ui::PAGE_TRANSITION_KEYWORD: - case ui::PAGE_TRANSITION_KEYWORD_GENERATED: - return sync_sessions::PageVisitObserver::kTransitionOmniboxTemplateSearch; - - default: - return sync_sessions::PageVisitObserver::kTransitionUnknown; - } -} - -} // namespace browser_sync
diff --git a/chrome/browser/sync/sessions/page_revisit_broadcaster.h b/chrome/browser/sync/sessions/page_revisit_broadcaster.h deleted file mode 100644 index 38a8a8c..0000000 --- a/chrome/browser/sync/sessions/page_revisit_broadcaster.h +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright 2015 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_SYNC_SESSIONS_PAGE_REVISIT_BROADCASTER_H_ -#define CHROME_BROWSER_SYNC_SESSIONS_PAGE_REVISIT_BROADCASTER_H_ - -#include "base/memory/scoped_vector.h" -#include "components/sync_sessions/revisit/page_visit_observer.h" -#include "ui/base/page_transition_types.h" -#include "url/gurl.h" - -namespace bookmarks { -class BookmarkModel; -} // namespace bookmarks - -namespace history { -class HistoryService; -} // namespace history - -namespace sync_sessions { -class SyncSessionsClient; -} - -namespace browser_sync { - -class SessionsSyncManager; - -// This class has the job of creating and holding onto the PageVisitObservers -// that are to be notified on page change for purposes of instrumenting -// revisists. -class PageRevisitBroadcaster { - public: - PageRevisitBroadcaster(SessionsSyncManager* sessions, - sync_sessions::SyncSessionsClient* sessions_client, - history::HistoryService* history, - bookmarks::BookmarkModel* bookmarks); - ~PageRevisitBroadcaster(); - - // Broadcasts to all observers the given page visit event. Should only be - // called when the url changes. - void OnPageVisit(const GURL& url, const ui::PageTransition transition); - - private: - friend class PageRevisitBroadcasterTest; - - // We convert between enums here for a couple reasons. We don't want to force - // observers to depend on ui/, and the high bit masks don't work for emitting - // histograms. Some of the high bit masks correspond to cases we're - // particularly interested in and want to treat as first class values. - static sync_sessions::PageVisitObserver::TransitionType ConvertTransitionEnum( - const ui::PageTransition original); - - // The client of this sync sessions datatype. - sync_sessions::SyncSessionsClient* const sessions_client_; - - ScopedVector<sync_sessions::PageVisitObserver> revisit_observers_; - - DISALLOW_COPY_AND_ASSIGN(PageRevisitBroadcaster); -}; - -} // namespace browser_sync - -#endif // CHROME_BROWSER_SYNC_SESSIONS_PAGE_REVISIT_BROADCASTER_H_
diff --git a/chrome/browser/sync/sessions/page_revisit_broadcaster_unittest.cc b/chrome/browser/sync/sessions/page_revisit_broadcaster_unittest.cc deleted file mode 100644 index 02c7a66..0000000 --- a/chrome/browser/sync/sessions/page_revisit_broadcaster_unittest.cc +++ /dev/null
@@ -1,110 +0,0 @@ -// Copyright 2015 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/sync/sessions/page_revisit_broadcaster.h" - -#include "components/sync_sessions/revisit/page_visit_observer.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/page_transition_types.h" - -using sync_sessions::PageVisitObserver; - -namespace browser_sync { - -class PageRevisitBroadcasterTest : public ::testing::Test { - protected: - PageVisitObserver::TransitionType Convert( - const ui::PageTransition conversionInput) { - return PageRevisitBroadcaster::ConvertTransitionEnum(conversionInput); - } - - void Check(const PageVisitObserver::TransitionType expected, - const ui::PageTransition conversionInput) { - EXPECT_EQ(expected, Convert(conversionInput)); - } - - void Check(const PageVisitObserver::TransitionType expected, - const int32 conversionInput) { - Check(expected, ui::PageTransitionFromInt(conversionInput)); - } -}; - -TEST_F(PageRevisitBroadcasterTest, ConvertPageInteraction) { - Check(PageVisitObserver::kTransitionPage, ui::PAGE_TRANSITION_LINK); - Check(PageVisitObserver::kTransitionPage, - ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_BLOCKED); - Check(PageVisitObserver::kTransitionPage, - ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_FORWARD_BACK); - // Don't check ui::PAGE_TRANSITION_FROM_ADDRESS_BAR, this is actually a copy - // and paste action when combined with ui::PAGE_TRANSITION_LINK. - Check(PageVisitObserver::kTransitionPage, - ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_HOME_PAGE); - Check(PageVisitObserver::kTransitionPage, - ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_FROM_API); - Check(PageVisitObserver::kTransitionPage, - ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CHAIN_START); - Check(PageVisitObserver::kTransitionPage, - ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CHAIN_END); - Check(PageVisitObserver::kTransitionPage, - ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT); - Check(PageVisitObserver::kTransitionPage, - ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_SERVER_REDIRECT); - Check(PageVisitObserver::kTransitionPage, - ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_IS_REDIRECT_MASK); -} - -TEST_F(PageRevisitBroadcasterTest, ConvertOmniboxURL) { - Check(PageVisitObserver::kTransitionOmniboxUrl, ui::PAGE_TRANSITION_TYPED); - Check(PageVisitObserver::kTransitionOmniboxUrl, - ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); -} - -TEST_F(PageRevisitBroadcasterTest, ConvertOmniboxDefaultSearch) { - Check(PageVisitObserver::kTransitionOmniboxDefaultSearch, - ui::PAGE_TRANSITION_GENERATED); - Check(PageVisitObserver::kTransitionOmniboxDefaultSearch, - ui::PAGE_TRANSITION_GENERATED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); -} - -TEST_F(PageRevisitBroadcasterTest, ConvertOmniboxTemplateSearch) { - Check(PageVisitObserver::kTransitionOmniboxTemplateSearch, - ui::PAGE_TRANSITION_KEYWORD); - Check(PageVisitObserver::kTransitionOmniboxTemplateSearch, - ui::PAGE_TRANSITION_KEYWORD | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); - Check(PageVisitObserver::kTransitionOmniboxTemplateSearch, - ui::PAGE_TRANSITION_KEYWORD_GENERATED); - Check(PageVisitObserver::kTransitionOmniboxTemplateSearch, - ui::PAGE_TRANSITION_KEYWORD_GENERATED | - ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); -} - -TEST_F(PageRevisitBroadcasterTest, ConvertBookmark) { - Check(PageVisitObserver::kTransitionBookmark, - ui::PAGE_TRANSITION_AUTO_BOOKMARK); -} - -TEST_F(PageRevisitBroadcasterTest, ConvertCopyPaste) { - Check(PageVisitObserver::kTransitionCopyPaste, - ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); -} - -TEST_F(PageRevisitBroadcasterTest, ConvertForwardBackward) { - Check(PageVisitObserver::kTransitionForwardBackward, - ui::PAGE_TRANSITION_AUTO_TOPLEVEL | ui::PAGE_TRANSITION_FORWARD_BACK); -} - -TEST_F(PageRevisitBroadcasterTest, ConvertRestore) { - Check(PageVisitObserver::kTransitionRestore, ui::PAGE_TRANSITION_RELOAD); -} - -TEST_F(PageRevisitBroadcasterTest, ConvertUnknown) { - Check(PageVisitObserver::kTransitionUnknown, - ui::PAGE_TRANSITION_AUTO_SUBFRAME); - Check(PageVisitObserver::kTransitionUnknown, - ui::PAGE_TRANSITION_MANUAL_SUBFRAME); - Check(PageVisitObserver::kTransitionUnknown, - ui::PAGE_TRANSITION_AUTO_TOPLEVEL); -} - -} // namespace browser_sync
diff --git a/chrome/browser/sync/sessions/session_data_type_controller.cc b/chrome/browser/sync/sessions/session_data_type_controller.cc deleted file mode 100644 index a5a08f9c..0000000 --- a/chrome/browser/sync/sessions/session_data_type_controller.cc +++ /dev/null
@@ -1,136 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/sessions/session_data_type_controller.h" - -#include "base/prefs/pref_service.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/common/pref_names.h" -#include "components/sync_driver/glue/synced_window_delegate.h" -#include "components/sync_driver/sessions/synced_window_delegates_getter.h" -#include "components/sync_driver/sync_client.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/notification_details.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_source.h" - -using content::BrowserThread; - -namespace browser_sync { - -SessionDataTypeController::SessionDataTypeController( - const base::Closure& error_callback, - sync_driver::SyncClient* sync_client, - Profile* profile, - SyncedWindowDelegatesGetter* synced_window_getter, - sync_driver::LocalDeviceInfoProvider* local_device) - : UIDataTypeController( - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - error_callback, - syncer::SESSIONS, - sync_client), - sync_client_(sync_client), - profile_(profile), - synced_window_getter_(synced_window_getter), - local_device_(local_device), - waiting_on_session_restore_(false), - waiting_on_local_device_info_(false) { - DCHECK(local_device_); - pref_registrar_.Init(sync_client_->GetPrefService()); - pref_registrar_.Add( - prefs::kSavingBrowserHistoryDisabled, - base::Bind(&SessionDataTypeController::OnSavingBrowserHistoryPrefChanged, - base::Unretained(this))); -} - -SessionDataTypeController::~SessionDataTypeController() {} - -bool SessionDataTypeController::StartModels() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - std::set<const browser_sync::SyncedWindowDelegate*> window = - synced_window_getter_->GetSyncedWindowDelegates(); - for (std::set<const browser_sync::SyncedWindowDelegate*>::const_iterator i = - window.begin(); i != window.end(); ++i) { - if ((*i)->IsSessionRestoreInProgress()) { - notification_registrar_.Add( - this, - chrome::NOTIFICATION_SESSION_RESTORE_COMPLETE, - content::Source<Profile>(profile_)); - waiting_on_session_restore_ = true; - break; - } - } - - if (!local_device_->GetLocalDeviceInfo()) { - subscription_ = local_device_->RegisterOnInitializedCallback( - base::Bind(&SessionDataTypeController::OnLocalDeviceInfoInitialized, - this)); - waiting_on_local_device_info_ = true; - } - - return !IsWaiting(); -} - -void SessionDataTypeController::StopModels() { - subscription_.reset(); - notification_registrar_.RemoveAll(); -} - -bool SessionDataTypeController::ReadyForStart() const { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - return !sync_client_->GetPrefService()->GetBoolean( - prefs::kSavingBrowserHistoryDisabled); -} - -bool SessionDataTypeController::IsWaiting() { - return waiting_on_session_restore_ || waiting_on_local_device_info_; -} - -void SessionDataTypeController::MaybeCompleteLoading() { - if (state_ == MODEL_STARTING && !IsWaiting()) { - OnModelLoaded(); - } -} - -void SessionDataTypeController::Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK_EQ(chrome::NOTIFICATION_SESSION_RESTORE_COMPLETE, type); - DCHECK_EQ(profile_, content::Source<Profile>(source).ptr()); - notification_registrar_.RemoveAll(); - - waiting_on_session_restore_ = false; - MaybeCompleteLoading(); -} - -void SessionDataTypeController::OnLocalDeviceInfoInitialized() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - subscription_.reset(); - - waiting_on_local_device_info_ = false; - MaybeCompleteLoading(); -} - -void SessionDataTypeController::OnSavingBrowserHistoryPrefChanged() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (sync_client_->GetPrefService()->GetBoolean( - prefs::kSavingBrowserHistoryDisabled)) { - // If history and tabs persistence is turned off then generate an - // unrecoverable error. SESSIONS won't be a registered type on the next - // Chrome restart. - if (state() != NOT_RUNNING && state() != STOPPING) { - syncer::SyncError error( - FROM_HERE, - syncer::SyncError::DATATYPE_POLICY_ERROR, - "History and tab saving is now disabled by policy.", - syncer::SESSIONS); - OnSingleDataTypeUnrecoverableError(error); - } - } -} - -} // namespace browser_sync
diff --git a/chrome/browser/sync/sessions/session_data_type_controller.h b/chrome/browser/sync/sessions/session_data_type_controller.h deleted file mode 100644 index 95cadda..0000000 --- a/chrome/browser/sync/sessions/session_data_type_controller.h +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SYNC_SESSIONS_SESSION_DATA_TYPE_CONTROLLER_H_ -#define CHROME_BROWSER_SYNC_SESSIONS_SESSION_DATA_TYPE_CONTROLLER_H_ - -#include "base/prefs/pref_change_registrar.h" -#include "components/sync_driver/local_device_info_provider.h" -#include "components/sync_driver/ui_data_type_controller.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" - -class Profile; - -namespace browser_sync { - -class SyncedWindowDelegatesGetter; - -// Overrides StartModels to avoid sync contention with sessions during -// a session restore operation at startup and to wait for the local -// device info to become available. -class SessionDataTypeController : public sync_driver::UIDataTypeController, - public content::NotificationObserver { - public: - SessionDataTypeController(const base::Closure& error_callback, - sync_driver::SyncClient* sync_client, - Profile* profile, - SyncedWindowDelegatesGetter* synced_window_getter, - sync_driver::LocalDeviceInfoProvider* local_device); - - // NotificationObserver interface. - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; - - // UIDataTypeController interface. - bool StartModels() override; - void StopModels() override; - bool ReadyForStart() const override; - - protected: - ~SessionDataTypeController() override; - - private: - bool IsWaiting(); - void MaybeCompleteLoading(); - void OnLocalDeviceInfoInitialized(); - void OnSavingBrowserHistoryPrefChanged(); - - sync_driver::SyncClient* const sync_client_; - Profile* const profile_; - - SyncedWindowDelegatesGetter* synced_window_getter_; - content::NotificationRegistrar notification_registrar_; - - sync_driver::LocalDeviceInfoProvider* const local_device_; - scoped_ptr<sync_driver::LocalDeviceInfoProvider::Subscription> subscription_; - - // Flags that indicate the reason for pending loading models. - bool waiting_on_session_restore_; - bool waiting_on_local_device_info_; - - PrefChangeRegistrar pref_registrar_; - - DISALLOW_COPY_AND_ASSIGN(SessionDataTypeController); -}; - -} // namespace browser_sync - -#endif // CHROME_BROWSER_SYNC_SESSIONS_SESSION_DATA_TYPE_CONTROLLER_H_
diff --git a/chrome/browser/sync/sessions/session_data_type_controller_unittest.cc b/chrome/browser/sync/sessions/session_data_type_controller_unittest.cc deleted file mode 100644 index 4ca52c24..0000000 --- a/chrome/browser/sync/sessions/session_data_type_controller_unittest.cc +++ /dev/null
@@ -1,256 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/bind.h" -#include "base/callback.h" -#include "base/memory/weak_ptr.h" -#include "base/run_loop.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/sync/sessions/session_data_type_controller.h" -#include "chrome/test/base/testing_profile.h" -#include "components/sync_driver/fake_sync_client.h" -#include "components/sync_driver/glue/synced_window_delegate.h" -#include "components/sync_driver/local_device_info_provider_mock.h" -#include "components/sync_driver/sessions/synced_window_delegates_getter.h" -#include "components/sync_driver/sync_api_component_factory_mock.h" -#include "content/public/browser/notification_service.h" -#include "content/public/test/test_browser_thread_bundle.h" -#include "testing/gtest/include/gtest/gtest.h" - -using sync_driver::LocalDeviceInfoProviderMock; - -namespace browser_sync { - -namespace { - -class MockSyncedWindowDelegate : public SyncedWindowDelegate { - public: - explicit MockSyncedWindowDelegate(Profile* profile) - : is_restore_in_progress_(false), - profile_(profile) {} - ~MockSyncedWindowDelegate() override {} - - bool HasWindow() const override { return false; } - SessionID::id_type GetSessionId() const override { return 0; } - int GetTabCount() const override { return 0; } - int GetActiveIndex() const override { return 0; } - bool IsApp() const override { return false; } - bool IsTypeTabbed() const override { return false; } - bool IsTypePopup() const override { return false; } - bool IsTabPinned(const SyncedTabDelegate* tab) const override { - return false; - } - SyncedTabDelegate* GetTabAt(int index) const override { return NULL; } - SessionID::id_type GetTabIdAt(int index) const override { return 0; } - - bool IsSessionRestoreInProgress() const override { - return is_restore_in_progress_; - } - - bool ShouldSync() const override { return false; } - - void SetSessionRestoreInProgress(bool is_restore_in_progress) { - is_restore_in_progress_ = is_restore_in_progress; - - if (!is_restore_in_progress_) { - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_SESSION_RESTORE_COMPLETE, - content::Source<Profile>(profile_), - content::NotificationService::NoDetails()); - } - } - - private: - bool is_restore_in_progress_; - Profile* profile_; -}; - -class MockSyncedWindowDelegatesGetter : public SyncedWindowDelegatesGetter { - public: - std::set<const SyncedWindowDelegate*> GetSyncedWindowDelegates() override { - return delegates_; - } - - const SyncedWindowDelegate* FindById(SessionID::id_type id) override { - return nullptr; - } - - void Add(SyncedWindowDelegate* delegate) { - delegates_.insert(delegate); - } - - private: - std::set<const SyncedWindowDelegate*> delegates_; -}; - -class SessionDataTypeControllerTest - : public testing::Test, public sync_driver::FakeSyncClient { - public: - SessionDataTypeControllerTest() - : sync_driver::FakeSyncClient(&profile_sync_factory_), - load_finished_(false), - thread_bundle_(content::TestBrowserThreadBundle::DEFAULT), - last_type_(syncer::UNSPECIFIED), - weak_ptr_factory_(this) {} - ~SessionDataTypeControllerTest() override {} - - // FakeSyncClient overrides. - PrefService* GetPrefService() override { - return profile_.GetPrefs(); - } - - void SetUp() override { - synced_window_delegate_.reset(new MockSyncedWindowDelegate(&profile_)); - synced_window_getter_.reset(new MockSyncedWindowDelegatesGetter()); - synced_window_getter_->Add(synced_window_delegate_.get()); - - local_device_.reset(new LocalDeviceInfoProviderMock( - "cache_guid", - "Wayne Gretzky's Hacking Box", - "Chromium 10k", - "Chrome 10k", - sync_pb::SyncEnums_DeviceType_TYPE_LINUX, - "device_id")); - - controller_ = new SessionDataTypeController( - base::Bind(&base::DoNothing), this, &profile_, - synced_window_getter_.get(), local_device_.get()); - - load_finished_ = false; - last_type_ = syncer::UNSPECIFIED; - last_error_ = syncer::SyncError(); - } - - void TearDown() override { - controller_ = NULL; - local_device_.reset(); - synced_window_getter_.reset(); - synced_window_delegate_.reset(); - } - - void Start() { - controller_->LoadModels( - base::Bind(&SessionDataTypeControllerTest::OnLoadFinished, - weak_ptr_factory_.GetWeakPtr())); - } - - void OnLoadFinished(syncer::ModelType type, syncer::SyncError error) { - load_finished_ = true; - last_type_ = type; - last_error_ = error; - } - - testing::AssertionResult LoadResult() { - if (!load_finished_) { - return testing::AssertionFailure() << - "OnLoadFinished wasn't called"; - } - - if (last_error_.IsSet()) { - return testing::AssertionFailure() << - "OnLoadFinished was called with a SyncError: " << - last_error_.ToString(); - } - - if (last_type_ != syncer::SESSIONS) { - return testing::AssertionFailure() << - "OnLoadFinished was called with a wrong sync type: " << - last_type_; - } - - return testing::AssertionSuccess(); - } - - protected: - scoped_refptr<SessionDataTypeController> controller_; - scoped_ptr<MockSyncedWindowDelegatesGetter> synced_window_getter_; - scoped_ptr<LocalDeviceInfoProviderMock> local_device_; - scoped_ptr<MockSyncedWindowDelegate> synced_window_delegate_; - bool load_finished_; - - private: - content::TestBrowserThreadBundle thread_bundle_; - SyncApiComponentFactoryMock profile_sync_factory_; - TestingProfile profile_; - syncer::ModelType last_type_; - syncer::SyncError last_error_; - base::WeakPtrFactory<SessionDataTypeControllerTest> weak_ptr_factory_; -}; - -TEST_F(SessionDataTypeControllerTest, StartModels) { - Start(); - EXPECT_EQ(sync_driver::DataTypeController::MODEL_LOADED, - controller_->state()); - EXPECT_TRUE(LoadResult()); -} - -TEST_F(SessionDataTypeControllerTest, StartModelsDelayedByLocalDevice) { - local_device_->SetInitialized(false); - Start(); - EXPECT_FALSE(load_finished_); - EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, - controller_->state()); - - local_device_->SetInitialized(true); - EXPECT_EQ(sync_driver::DataTypeController::MODEL_LOADED, - controller_->state()); - EXPECT_TRUE(LoadResult()); -} - -TEST_F(SessionDataTypeControllerTest, StartModelsDelayedByRestoreInProgress) { - synced_window_delegate_->SetSessionRestoreInProgress(true); - Start(); - EXPECT_FALSE(load_finished_); - EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, - controller_->state()); - - synced_window_delegate_->SetSessionRestoreInProgress(false); - EXPECT_EQ(sync_driver::DataTypeController::MODEL_LOADED, - controller_->state()); - EXPECT_TRUE(LoadResult()); -} - -TEST_F(SessionDataTypeControllerTest, - StartModelsDelayedByLocalDeviceThenRestoreInProgress) { - local_device_->SetInitialized(false); - synced_window_delegate_->SetSessionRestoreInProgress(true); - Start(); - EXPECT_FALSE(load_finished_); - EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, - controller_->state()); - - local_device_->SetInitialized(true); - EXPECT_FALSE(load_finished_); - EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, - controller_->state()); - - synced_window_delegate_->SetSessionRestoreInProgress(false); - EXPECT_EQ(sync_driver::DataTypeController::MODEL_LOADED, - controller_->state()); - EXPECT_TRUE(LoadResult()); -} - -TEST_F(SessionDataTypeControllerTest, - StartModelsDelayedByRestoreInProgressThenLocalDevice) { - local_device_->SetInitialized(false); - synced_window_delegate_->SetSessionRestoreInProgress(true); - Start(); - EXPECT_FALSE(load_finished_); - EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, - controller_->state()); - - synced_window_delegate_->SetSessionRestoreInProgress(false); - EXPECT_FALSE(load_finished_); - EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, - controller_->state()); - - local_device_->SetInitialized(true); - EXPECT_EQ(sync_driver::DataTypeController::MODEL_LOADED, - controller_->state()); - EXPECT_TRUE(LoadResult()); -} - -} // namespace - -} // namespace browser_sync
diff --git a/chrome/browser/sync/sessions/sessions_sync_manager.cc b/chrome/browser/sync/sessions/sessions_sync_manager.cc deleted file mode 100644 index 663e6f0a..0000000 --- a/chrome/browser/sync/sessions/sessions_sync_manager.cc +++ /dev/null
@@ -1,1116 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/sessions/sessions_sync_manager.h" - -#include <algorithm> - -#include "base/metrics/field_trial.h" -#include "chrome/browser/bookmarks/bookmark_model_factory.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/favicon/favicon_service_factory.h" -#include "chrome/browser/history/history_service_factory.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/search/search.h" -#include "components/sync_driver/glue/synced_window_delegate.h" -#include "components/sync_driver/local_device_info_provider.h" -#include "components/sync_driver/sessions/synced_window_delegates_getter.h" -#include "components/sync_sessions/sync_sessions_client.h" -#include "components/sync_sessions/synced_tab_delegate.h" -#include "content/public/browser/notification_details.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_source.h" -#include "sync/api/sync_error.h" -#include "sync/api/sync_error_factory.h" -#include "sync/api/sync_merge_result.h" -#include "sync/api/time.h" - -using sessions::SerializedNavigationEntry; -using sync_driver::DeviceInfo; -using sync_driver::LocalDeviceInfoProvider; -using syncer::SyncChange; -using syncer::SyncData; - -namespace browser_sync { - -namespace { - -// Maximum number of favicons to sync. -// TODO(zea): pull this from the server. -const int kMaxSyncFavicons = 200; - -// The maximum number of navigations in each direction we care to sync. -const int kMaxSyncNavigationCount = 6; - -// The URL at which the set of synced tabs is displayed. We treat it differently -// from all other URL's as accessing it triggers a sync refresh of Sessions. -const char kNTPOpenTabSyncURL[] = "chrome://newtab/#open_tabs"; - -// Default number of days without activity after which a session is considered -// stale and becomes a candidate for garbage collection. -const size_t kDefaultStaleSessionThresholdDays = 14; // 2 weeks. - -// Comparator function for use with std::sort that will sort tabs by -// descending timestamp (i.e., most recent first). -bool TabsRecencyComparator(const sessions::SessionTab* t1, - const sessions::SessionTab* t2) { - return t1->timestamp > t2->timestamp; -} - -// Comparator function for use with std::sort that will sort sessions by -// descending modified_time (i.e., most recent first). -bool SessionsRecencyComparator(const sync_driver::SyncedSession* s1, - const sync_driver::SyncedSession* s2) { - return s1->modified_time > s2->modified_time; -} - -} // namespace - -// |local_device| is owned by ProfileSyncService, its lifetime exceeds -// lifetime of SessionSyncManager. -SessionsSyncManager::SessionsSyncManager( - sync_sessions::SyncSessionsClient* sessions_client, - Profile* profile, - LocalDeviceInfoProvider* local_device, - scoped_ptr<LocalSessionEventRouter> router) - : sessions_client_(sessions_client), - session_tracker_(sessions_client), - favicon_cache_(FaviconServiceFactory::GetForProfile( - profile, - ServiceAccessType::EXPLICIT_ACCESS), - HistoryServiceFactory::GetForProfile( - profile, - ServiceAccessType::EXPLICIT_ACCESS), - kMaxSyncFavicons), - local_tab_pool_out_of_sync_(true), - sync_prefs_(profile->GetPrefs()), - profile_(profile), - local_device_(local_device), - local_session_header_node_id_(TabNodePool::kInvalidTabNodeID), - stale_session_threshold_days_(kDefaultStaleSessionThresholdDays), - local_event_router_(router.Pass()), - page_revisit_broadcaster_(this, - sessions_client, - HistoryServiceFactory::GetForProfile( - profile, - ServiceAccessType::EXPLICIT_ACCESS), - BookmarkModelFactory::GetForProfile(profile)) { - synced_window_getter_ = sessions_client_->GetSyncedWindowDelegatesGetter(); -} - -SessionsSyncManager::~SessionsSyncManager() { -} - -// Returns the GUID-based string that should be used for -// |SessionsSyncManager::current_machine_tag_|. -static std::string BuildMachineTag(const std::string& cache_guid) { - std::string machine_tag = "session_sync"; - machine_tag.append(cache_guid); - return machine_tag; -} - -syncer::SyncMergeResult SessionsSyncManager::MergeDataAndStartSyncing( - syncer::ModelType type, - const syncer::SyncDataList& initial_sync_data, - scoped_ptr<syncer::SyncChangeProcessor> sync_processor, - scoped_ptr<syncer::SyncErrorFactory> error_handler) { - syncer::SyncMergeResult merge_result(type); - DCHECK(session_tracker_.Empty()); - DCHECK_EQ(0U, local_tab_pool_.Capacity()); - - error_handler_ = error_handler.Pass(); - sync_processor_ = sync_processor.Pass(); - - local_session_header_node_id_ = TabNodePool::kInvalidTabNodeID; - - // Make sure we have a machine tag. We do this now (versus earlier) as it's - // a conveniently safe time to assert sync is ready and the cache_guid is - // initialized. - if (current_machine_tag_.empty()) { - InitializeCurrentMachineTag(); - } - - // SessionDataTypeController ensures that the local device info - // is available before activating this datatype. - DCHECK(local_device_); - const DeviceInfo* local_device_info = local_device_->GetLocalDeviceInfo(); - if (local_device_info) { - current_session_name_ = local_device_info->client_name(); - } else { - merge_result.set_error(error_handler_->CreateAndUploadError( - FROM_HERE, - "Failed to get local device info.")); - return merge_result; - } - - session_tracker_.SetLocalSessionTag(current_machine_tag_); - - syncer::SyncChangeList new_changes; - - // First, we iterate over sync data to update our session_tracker_. - syncer::SyncDataList restored_tabs; - if (!InitFromSyncModel(initial_sync_data, &restored_tabs, &new_changes)) { - // The sync db didn't have a header node for us. Create one. - sync_pb::EntitySpecifics specifics; - sync_pb::SessionSpecifics* base_specifics = specifics.mutable_session(); - base_specifics->set_session_tag(current_machine_tag()); - sync_pb::SessionHeader* header_s = base_specifics->mutable_header(); - header_s->set_client_name(current_session_name_); - header_s->set_device_type(local_device_info->device_type()); - syncer::SyncData data = syncer::SyncData::CreateLocalData( - current_machine_tag(), current_session_name_, specifics); - new_changes.push_back(syncer::SyncChange( - FROM_HERE, syncer::SyncChange::ACTION_ADD, data)); - } - -#if defined(OS_ANDROID) - std::string sync_machine_tag(BuildMachineTag( - local_device_->GetLocalSyncCacheGUID())); - if (current_machine_tag_.compare(sync_machine_tag) != 0) - DeleteForeignSessionInternal(sync_machine_tag, &new_changes); -#endif - - // Check if anything has changed on the local client side. - AssociateWindows(RELOAD_TABS, restored_tabs, &new_changes); - local_tab_pool_out_of_sync_ = false; - - merge_result.set_error( - sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes)); - - local_event_router_->StartRoutingTo(this); - return merge_result; -} - -void SessionsSyncManager::AssociateWindows( - ReloadTabsOption option, - const syncer::SyncDataList& restored_tabs, - syncer::SyncChangeList* change_output) { - const std::string local_tag = current_machine_tag(); - sync_pb::SessionSpecifics specifics; - specifics.set_session_tag(local_tag); - sync_pb::SessionHeader* header_s = specifics.mutable_header(); - sync_driver::SyncedSession* current_session = - session_tracker_.GetSession(local_tag); - current_session->modified_time = base::Time::Now(); - header_s->set_client_name(current_session_name_); - // SessionDataTypeController ensures that the local device info - // is available before activating this datatype. - DCHECK(local_device_); - const DeviceInfo* local_device_info = local_device_->GetLocalDeviceInfo(); - header_s->set_device_type(local_device_info->device_type()); - - session_tracker_.ResetSessionTracking(local_tag); - std::set<const SyncedWindowDelegate*> windows = - GetSyncedWindowDelegatesGetter()->GetSyncedWindowDelegates(); - - for (std::set<const SyncedWindowDelegate*>::const_iterator i = - windows.begin(); i != windows.end(); ++i) { - // Make sure the window has tabs and a viewable window. The viewable window - // check is necessary because, for example, when a browser is closed the - // destructor is not necessarily run immediately. This means its possible - // for us to get a handle to a browser that is about to be removed. If - // the tab count is 0 or the window is NULL, the browser is about to be - // deleted, so we ignore it. - if ((*i)->ShouldSync() && (*i)->GetTabCount() && (*i)->HasWindow()) { - sync_pb::SessionWindow window_s; - SessionID::id_type window_id = (*i)->GetSessionId(); - DVLOG(1) << "Associating window " << window_id << " with " - << (*i)->GetTabCount() << " tabs."; - window_s.set_window_id(window_id); - // Note: We don't bother to set selected tab index anymore. We still - // consume it when receiving foreign sessions, as reading it is free, but - // it triggers too many sync cycles with too little value to make setting - // it worthwhile. - if ((*i)->IsTypeTabbed()) { - window_s.set_browser_type( - sync_pb::SessionWindow_BrowserType_TYPE_TABBED); - } else { - window_s.set_browser_type( - sync_pb::SessionWindow_BrowserType_TYPE_POPUP); - } - - bool found_tabs = false; - for (int j = 0; j < (*i)->GetTabCount(); ++j) { - SessionID::id_type tab_id = (*i)->GetTabIdAt(j); - SyncedTabDelegate* synced_tab = (*i)->GetTabAt(j); - - // GetTabAt can return a null tab; in that case just skip it. - if (!synced_tab) - continue; - - if (synced_tab->IsPlaceholderTab()) { - // For tabs without WebContents update the |tab_id|, as it could have - // changed after a session restore. - // Note: We cannot check if a tab is valid if it has no WebContents. - // We assume any such tab is valid and leave the contents of - // corresponding sync node unchanged. - if (synced_tab->GetSyncId() > TabNodePool::kInvalidTabNodeID && - tab_id > TabNodePool::kInvalidTabID) { - AssociateRestoredPlaceholderTab(*synced_tab, tab_id, - restored_tabs, change_output); - found_tabs = true; - window_s.add_tab(tab_id); - } - continue; - } - - if (RELOAD_TABS == option) - AssociateTab(synced_tab, change_output); - - // If the tab is valid, it would have been added to the tracker either - // by the above AssociateTab call (at association time), or by the - // change processor calling AssociateTab for all modified tabs. - // Therefore, we can key whether this window has valid tabs based on - // the tab's presence in the tracker. - const sessions::SessionTab* tab = NULL; - if (session_tracker_.LookupSessionTab(local_tag, tab_id, &tab)) { - found_tabs = true; - window_s.add_tab(tab_id); - } - } - if (found_tabs) { - sync_pb::SessionWindow* header_window = header_s->add_window(); - *header_window = window_s; - - // Update this window's representation in the synced session tracker. - session_tracker_.PutWindowInSession(local_tag, window_id); - BuildSyncedSessionFromSpecifics(local_tag, - window_s, - current_session->modified_time, - current_session->windows[window_id]); - } - } - } - local_tab_pool_.DeleteUnassociatedTabNodes(change_output); - session_tracker_.CleanupSession(local_tag); - - // Always update the header. Sync takes care of dropping this update - // if the entity specifics are identical (i.e windows, client name did - // not change). - sync_pb::EntitySpecifics entity; - entity.mutable_session()->CopyFrom(specifics); - syncer::SyncData data = syncer::SyncData::CreateLocalData( - current_machine_tag(), current_session_name_, entity); - change_output->push_back(syncer::SyncChange( - FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); -} - -void SessionsSyncManager::AssociateTab(SyncedTabDelegate* const tab, - syncer::SyncChangeList* change_output) { - DCHECK(!tab->IsPlaceholderTab()); - SessionID::id_type tab_id = tab->GetSessionId(); - - if (tab->IsBeingDestroyed()) { - // This tab is closing. - TabLinksMap::iterator tab_iter = local_tab_map_.find(tab_id); - if (tab_iter == local_tab_map_.end()) { - // We aren't tracking this tab (for example, sync setting page). - return; - } - local_tab_pool_.FreeTabNode(tab_iter->second->tab_node_id(), - change_output); - local_tab_map_.erase(tab_iter); - return; - } - - if (!tab->ShouldSync(sessions_client_)) - return; - - TabLinksMap::iterator local_tab_map_iter = local_tab_map_.find(tab_id); - TabLink* tab_link = NULL; - - if (local_tab_map_iter == local_tab_map_.end()) { - int tab_node_id = tab->GetSyncId(); - // If there is an old sync node for the tab, reuse it. If this is a new - // tab, get a sync node for it. - if (!local_tab_pool_.IsUnassociatedTabNode(tab_node_id)) { - tab_node_id = local_tab_pool_.GetFreeTabNode(change_output); - tab->SetSyncId(tab_node_id); - } - local_tab_pool_.AssociateTabNode(tab_node_id, tab_id); - tab_link = new TabLink(tab_node_id, tab); - local_tab_map_[tab_id] = make_linked_ptr<TabLink>(tab_link); - } else { - // This tab is already associated with a sync node, reuse it. - // Note: on some platforms the tab object may have changed, so we ensure - // the tab link is up to date. - tab_link = local_tab_map_iter->second.get(); - local_tab_map_iter->second->set_tab(tab); - } - DCHECK(tab_link); - DCHECK_NE(tab_link->tab_node_id(), TabNodePool::kInvalidTabNodeID); - DVLOG(1) << "Reloading tab " << tab_id << " from window " - << tab->GetWindowId(); - - // Write to sync model. - sync_pb::EntitySpecifics specifics; - LocalTabDelegateToSpecifics(*tab, specifics.mutable_session()); - syncer::SyncData data = syncer::SyncData::CreateLocalData( - TabNodePool::TabIdToTag(current_machine_tag_, - tab_link->tab_node_id()), - current_session_name_, - specifics); - change_output->push_back(syncer::SyncChange( - FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); - - int current_index = tab->GetCurrentEntryIndex(); - const GURL new_url = tab->GetVirtualURLAtIndex(current_index); - if (new_url != tab_link->url()) { - tab_link->set_url(new_url); - favicon_cache_.OnFaviconVisited(new_url, - tab->GetFaviconURLAtIndex(current_index)); - page_revisit_broadcaster_.OnPageVisit( - new_url, tab->GetTransitionAtIndex(current_index)); - } - - session_tracker_.GetSession(current_machine_tag())->modified_time = - base::Time::Now(); -} - -void SessionsSyncManager::RebuildAssociations() { - syncer::SyncDataList data( - sync_processor_->GetAllSyncData(syncer::SESSIONS)); - scoped_ptr<syncer::SyncErrorFactory> error_handler(error_handler_.Pass()); - scoped_ptr<syncer::SyncChangeProcessor> processor(sync_processor_.Pass()); - - StopSyncing(syncer::SESSIONS); - MergeDataAndStartSyncing( - syncer::SESSIONS, data, processor.Pass(), error_handler.Pass()); -} - -bool SessionsSyncManager::IsValidSessionHeader( - const sync_pb::SessionHeader& header) { - // Verify that tab IDs appear only once within a session. - // Intended to prevent http://crbug.com/360822. - std::set<int> session_tab_ids; - for (int i = 0; i < header.window_size(); ++i) { - const sync_pb::SessionWindow& window = header.window(i); - for (int j = 0; j < window.tab_size(); ++j) { - const int tab_id = window.tab(j); - bool success = session_tab_ids.insert(tab_id).second; - if (!success) - return false; - } - } - - return true; -} - -void SessionsSyncManager::OnLocalTabModified(SyncedTabDelegate* modified_tab) { - GURL virtual_url = - modified_tab->GetVirtualURLAtIndex(modified_tab->GetCurrentEntryIndex()); - if (!modified_tab->IsBeingDestroyed() && virtual_url.is_valid() && - virtual_url.spec() == kNTPOpenTabSyncURL) { - DVLOG(1) << "Triggering sync refresh for sessions datatype."; - const syncer::ModelTypeSet types(syncer::SESSIONS); - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_SYNC_REFRESH_LOCAL, - content::Source<Profile>(profile_), - content::Details<const syncer::ModelTypeSet>(&types)); - } - - if (local_tab_pool_out_of_sync_) { - // If our tab pool is corrupt, pay the price of a full re-association to - // fix things up. This takes care of the new tab modification as well. - RebuildAssociations(); - DCHECK(!local_tab_pool_out_of_sync_); - return; - } - - syncer::SyncChangeList changes; - AssociateTab(modified_tab, &changes); - // Note, we always associate windows because it's possible a tab became - // "interesting" by going to a valid URL, in which case it needs to be added - // to the window's tab information. Similarly, if a tab became - // "uninteresting", we remove it from the window's tab information. - AssociateWindows(DONT_RELOAD_TABS, syncer::SyncDataList(), &changes); - sync_processor_->ProcessSyncChanges(FROM_HERE, changes); -} - -void SessionsSyncManager::OnFaviconsChanged( - const std::set<GURL>& page_urls, - const GURL& /* icon_url */) { - // TODO(zea): consider a separate container for tabs with outstanding favicon - // loads so we don't have to iterate through all tabs comparing urls. - for (const GURL& page_url : page_urls) { - for (TabLinksMap::iterator tab_iter = local_tab_map_.begin(); - tab_iter != local_tab_map_.end(); - ++tab_iter) { - if (tab_iter->second->url() == page_url) - favicon_cache_.OnPageFaviconUpdated(page_url); - } - } -} - -void SessionsSyncManager::StopSyncing(syncer::ModelType type) { - local_event_router_->Stop(); - sync_processor_.reset(NULL); - error_handler_.reset(); - session_tracker_.Clear(); - local_tab_map_.clear(); - local_tab_pool_.Clear(); - current_machine_tag_.clear(); - current_session_name_.clear(); - local_session_header_node_id_ = TabNodePool::kInvalidTabNodeID; -} - -syncer::SyncDataList SessionsSyncManager::GetAllSyncData( - syncer::ModelType type) const { - syncer::SyncDataList list; - const sync_driver::SyncedSession* session = NULL; - if (!session_tracker_.LookupLocalSession(&session)) - return syncer::SyncDataList(); - - // First construct the header node. - sync_pb::EntitySpecifics header_entity; - header_entity.mutable_session()->set_session_tag(current_machine_tag()); - sync_pb::SessionHeader* header_specifics = - header_entity.mutable_session()->mutable_header(); - header_specifics->MergeFrom(session->ToSessionHeader()); - syncer::SyncData data = syncer::SyncData::CreateLocalData( - current_machine_tag(), current_session_name_, header_entity); - list.push_back(data); - - sync_driver::SyncedSession::SyncedWindowMap::const_iterator win_iter; - for (win_iter = session->windows.begin(); - win_iter != session->windows.end(); ++win_iter) { - std::vector<sessions::SessionTab*>::const_iterator tabs_iter; - for (tabs_iter = win_iter->second->tabs.begin(); - tabs_iter != win_iter->second->tabs.end(); ++tabs_iter) { - sync_pb::EntitySpecifics entity; - sync_pb::SessionSpecifics* specifics = entity.mutable_session(); - specifics->mutable_tab()->MergeFrom((*tabs_iter)->ToSyncData()); - specifics->set_session_tag(current_machine_tag_); - - TabLinksMap::const_iterator tab_map_iter = local_tab_map_.find( - (*tabs_iter)->tab_id.id()); - DCHECK(tab_map_iter != local_tab_map_.end()); - specifics->set_tab_node_id(tab_map_iter->second->tab_node_id()); - syncer::SyncData data = syncer::SyncData::CreateLocalData( - TabNodePool::TabIdToTag(current_machine_tag_, - specifics->tab_node_id()), - current_session_name_, - entity); - list.push_back(data); - } - } - return list; -} - -bool SessionsSyncManager::GetLocalSession( - const sync_driver::SyncedSession** local_session) { - if (current_machine_tag_.empty()) - return false; - *local_session = session_tracker_.GetSession(current_machine_tag()); - return true; -} - -syncer::SyncError SessionsSyncManager::ProcessSyncChanges( - const tracked_objects::Location& from_here, - const syncer::SyncChangeList& change_list) { - if (!sync_processor_.get()) { - syncer::SyncError error(FROM_HERE, - syncer::SyncError::DATATYPE_ERROR, - "Models not yet associated.", - syncer::SESSIONS); - return error; - } - - for (syncer::SyncChangeList::const_iterator it = change_list.begin(); - it != change_list.end(); ++it) { - DCHECK(it->IsValid()); - DCHECK(it->sync_data().GetSpecifics().has_session()); - const sync_pb::SessionSpecifics& session = - it->sync_data().GetSpecifics().session(); - switch (it->change_type()) { - case syncer::SyncChange::ACTION_DELETE: - // Deletions are all or nothing (since we only ever delete entire - // sessions). Therefore we don't care if it's a tab node or meta node, - // and just ensure we've disassociated. - if (current_machine_tag() == session.session_tag()) { - // Another client has attempted to delete our local data (possibly by - // error or a clock is inaccurate). Just ignore the deletion for now - // to avoid any possible ping-pong delete/reassociate sequence, but - // remember that this happened as our TabNodePool is inconsistent. - local_tab_pool_out_of_sync_ = true; - LOG(WARNING) << "Local session data deleted. Ignoring until next " - << "local navigation event."; - } else if (session.has_header()) { - // Disassociate only when header node is deleted. For tab node - // deletions, the header node will be updated and foreign tab will - // get deleted. - DisassociateForeignSession(session.session_tag()); - } - break; - case syncer::SyncChange::ACTION_ADD: - case syncer::SyncChange::ACTION_UPDATE: - if (current_machine_tag() == session.session_tag()) { - // We should only ever receive a change to our own machine's session - // info if encryption was turned on. In that case, the data is still - // the same, so we can ignore. - // TODO(skym): Is it really safe to return here? Why not continue? - // Couldn't there be multiple SessionSpecifics in the SyncChangeList - // that contain different session tags? - LOG(WARNING) << "Dropping modification to local session."; - return syncer::SyncError(); - } - UpdateTrackerWithForeignSession( - session, syncer::SyncDataRemote(it->sync_data()).GetModifiedTime()); - break; - default: - NOTREACHED() << "Processing sync changes failed, unknown change type."; - } - } - - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED, - content::Source<Profile>(profile_), - content::NotificationService::NoDetails()); - return syncer::SyncError(); -} - -syncer::SyncChange SessionsSyncManager::TombstoneTab( - const sync_pb::SessionSpecifics& tab) { - if (!tab.has_tab_node_id()) { - LOG(WARNING) << "Old sessions node without tab node id; can't tombstone."; - return syncer::SyncChange(); - } else { - return syncer::SyncChange( - FROM_HERE, - SyncChange::ACTION_DELETE, - SyncData::CreateLocalDelete( - TabNodePool::TabIdToTag(current_machine_tag(), - tab.tab_node_id()), - syncer::SESSIONS)); - } -} - -bool SessionsSyncManager::GetAllForeignSessions( - std::vector<const sync_driver::SyncedSession*>* sessions) { - if (!session_tracker_.LookupAllForeignSessions(sessions)) - return false; - std::sort(sessions->begin(), sessions->end(), SessionsRecencyComparator); - return true; -} - -bool SessionsSyncManager::InitFromSyncModel( - const syncer::SyncDataList& sync_data, - syncer::SyncDataList* restored_tabs, - syncer::SyncChangeList* new_changes) { - bool found_current_header = false; - for (syncer::SyncDataList::const_iterator it = sync_data.begin(); - it != sync_data.end(); - ++it) { - // TODO(skym): Why don't we ever look at data.change_type()? Why is this - // code path so much different from ProcessSyncChanges? - const syncer::SyncData& data = *it; - DCHECK(data.GetSpecifics().has_session()); - const sync_pb::SessionSpecifics& specifics = data.GetSpecifics().session(); - if (specifics.session_tag().empty() || - (specifics.has_tab() && (!specifics.has_tab_node_id() || - !specifics.tab().has_tab_id()))) { - syncer::SyncChange tombstone(TombstoneTab(specifics)); - if (tombstone.IsValid()) - new_changes->push_back(tombstone); - } else if (specifics.session_tag() != current_machine_tag()) { - UpdateTrackerWithForeignSession( - specifics, syncer::SyncDataRemote(data).GetModifiedTime()); - } else { - // This is previously stored local session information. - if (specifics.has_header() && !found_current_header) { - // This is our previous header node, reuse it. - found_current_header = true; - if (specifics.header().has_client_name()) - current_session_name_ = specifics.header().client_name(); - } else { - if (specifics.has_header() || !specifics.has_tab()) { - LOG(WARNING) << "Found more than one session header node with local " - << "tag."; - syncer::SyncChange tombstone(TombstoneTab(specifics)); - if (tombstone.IsValid()) - new_changes->push_back(tombstone); - } else { - // This is a valid old tab node, add it to the pool so it can be - // reused for reassociation. - local_tab_pool_.AddTabNode(specifics.tab_node_id()); - restored_tabs->push_back(*it); - } - } - } - } - return found_current_header; -} - -void SessionsSyncManager::UpdateTrackerWithForeignSession( - const sync_pb::SessionSpecifics& specifics, - const base::Time& modification_time) { - std::string foreign_session_tag = specifics.session_tag(); - DCHECK_NE(foreign_session_tag, current_machine_tag()); - - sync_driver::SyncedSession* foreign_session = - session_tracker_.GetSession(foreign_session_tag); - if (specifics.has_header()) { - // Read in the header data for this foreign session. Header data is - // essentially a collection of windows, each of which has an ordered id list - // for their tabs. - - if (!IsValidSessionHeader(specifics.header())) { - LOG(WARNING) << "Ignoring foreign session node with invalid header " - << "and tag " << foreign_session_tag << "."; - return; - } - - // Load (or create) the SyncedSession object for this client. - const sync_pb::SessionHeader& header = specifics.header(); - PopulateSessionHeaderFromSpecifics(header, - modification_time, - foreign_session); - - // Reset the tab/window tracking for this session (must do this before - // we start calling PutWindowInSession and PutTabInWindow so that all - // unused tabs/windows get cleared by the CleanupSession(...) call). - session_tracker_.ResetSessionTracking(foreign_session_tag); - - // Process all the windows and their tab information. - int num_windows = header.window_size(); - DVLOG(1) << "Associating " << foreign_session_tag << " with " - << num_windows << " windows."; - - for (int i = 0; i < num_windows; ++i) { - const sync_pb::SessionWindow& window_s = header.window(i); - SessionID::id_type window_id = window_s.window_id(); - session_tracker_.PutWindowInSession(foreign_session_tag, - window_id); - BuildSyncedSessionFromSpecifics(foreign_session_tag, - window_s, - modification_time, - foreign_session->windows[window_id]); - } - // Delete any closed windows and unused tabs as necessary. - session_tracker_.CleanupSession(foreign_session_tag); - } else if (specifics.has_tab()) { - const sync_pb::SessionTab& tab_s = specifics.tab(); - SessionID::id_type tab_id = tab_s.tab_id(); - - const sessions::SessionTab* existing_tab; - if (session_tracker_.LookupSessionTab( - foreign_session_tag, tab_id, &existing_tab) && - existing_tab->timestamp > modification_time) { - DVLOG(1) << "Ignoring " << foreign_session_tag << "'s session tab " - << tab_id << " with earlier modification time"; - return; - } - - sessions::SessionTab* tab = - session_tracker_.GetTab(foreign_session_tag, - tab_id, - specifics.tab_node_id()); - - // Update SessionTab based on protobuf. - tab->SetFromSyncData(tab_s, modification_time); - - // If a favicon or favicon urls are present, load the URLs and visit - // times into the in-memory favicon cache. - RefreshFaviconVisitTimesFromForeignTab(tab_s, modification_time); - - // Update the last modified time. - if (foreign_session->modified_time < modification_time) - foreign_session->modified_time = modification_time; - } else { - LOG(WARNING) << "Ignoring foreign session node with missing header/tab " - << "fields and tag " << foreign_session_tag << "."; - } -} - -void SessionsSyncManager::InitializeCurrentMachineTag() { - DCHECK(current_machine_tag_.empty()); - std::string persisted_guid; - persisted_guid = sync_prefs_.GetSyncSessionsGUID(); - if (!persisted_guid.empty()) { - current_machine_tag_ = persisted_guid; - DVLOG(1) << "Restoring persisted session sync guid: " << persisted_guid; - } else { - DCHECK(local_device_); - std::string cache_guid = local_device_->GetLocalSyncCacheGUID(); - DCHECK(!cache_guid.empty()); - current_machine_tag_ = BuildMachineTag(cache_guid); - DVLOG(1) << "Creating session sync guid: " << current_machine_tag_; - sync_prefs_.SetSyncSessionsGUID(current_machine_tag_); - } - - local_tab_pool_.SetMachineTag(current_machine_tag_); -} - -// static -void SessionsSyncManager::PopulateSessionHeaderFromSpecifics( - const sync_pb::SessionHeader& header_specifics, - base::Time mtime, - sync_driver::SyncedSession* session_header) { - if (header_specifics.has_client_name()) - session_header->session_name = header_specifics.client_name(); - if (header_specifics.has_device_type()) { - switch (header_specifics.device_type()) { - case sync_pb::SyncEnums_DeviceType_TYPE_WIN: - session_header->device_type = sync_driver::SyncedSession::TYPE_WIN; - break; - case sync_pb::SyncEnums_DeviceType_TYPE_MAC: - session_header->device_type = sync_driver::SyncedSession::TYPE_MACOSX; - break; - case sync_pb::SyncEnums_DeviceType_TYPE_LINUX: - session_header->device_type = sync_driver::SyncedSession::TYPE_LINUX; - break; - case sync_pb::SyncEnums_DeviceType_TYPE_CROS: - session_header->device_type = sync_driver::SyncedSession::TYPE_CHROMEOS; - break; - case sync_pb::SyncEnums_DeviceType_TYPE_PHONE: - session_header->device_type = sync_driver::SyncedSession::TYPE_PHONE; - break; - case sync_pb::SyncEnums_DeviceType_TYPE_TABLET: - session_header->device_type = sync_driver::SyncedSession::TYPE_TABLET; - break; - case sync_pb::SyncEnums_DeviceType_TYPE_OTHER: - // Intentionally fall-through - default: - session_header->device_type = sync_driver::SyncedSession::TYPE_OTHER; - break; - } - } - session_header->modified_time = mtime; -} - -// static -void SessionsSyncManager::BuildSyncedSessionFromSpecifics( - const std::string& session_tag, - const sync_pb::SessionWindow& specifics, - base::Time mtime, - sessions::SessionWindow* session_window) { - if (specifics.has_window_id()) - session_window->window_id.set_id(specifics.window_id()); - if (specifics.has_selected_tab_index()) - session_window->selected_tab_index = specifics.selected_tab_index(); - if (specifics.has_browser_type()) { - // TODO(skuhne): Sync data writes |BrowserType| not - // |SessionWindow::WindowType|. This should get changed. - if (specifics.browser_type() == - sync_pb::SessionWindow_BrowserType_TYPE_TABBED) { - session_window->type = sessions::SessionWindow::TYPE_TABBED; - } else { - session_window->type = sessions::SessionWindow::TYPE_POPUP; - } - } - session_window->timestamp = mtime; - session_window->tabs.resize(specifics.tab_size(), NULL); - for (int i = 0; i < specifics.tab_size(); i++) { - SessionID::id_type tab_id = specifics.tab(i); - session_tracker_.PutTabInWindow(session_tag, - session_window->window_id.id(), - tab_id, - i); - } -} - -void SessionsSyncManager::RefreshFaviconVisitTimesFromForeignTab( - const sync_pb::SessionTab& tab, const base::Time& modification_time) { - // First go through and iterate over all the navigations, checking if any - // have valid favicon urls. - for (int i = 0; i < tab.navigation_size(); ++i) { - if (!tab.navigation(i).favicon_url().empty()) { - const std::string& page_url = tab.navigation(i).virtual_url(); - const std::string& favicon_url = tab.navigation(i).favicon_url(); - favicon_cache_.OnReceivedSyncFavicon(GURL(page_url), - GURL(favicon_url), - std::string(), - syncer::TimeToProtoTime( - modification_time)); - } - } -} - -bool SessionsSyncManager::GetSyncedFaviconForPageURL( - const std::string& page_url, - scoped_refptr<base::RefCountedMemory>* favicon_png) const { - return favicon_cache_.GetSyncedFaviconForPageURL(GURL(page_url), favicon_png); -} - -void SessionsSyncManager::DeleteForeignSession(const std::string& tag) { - syncer::SyncChangeList changes; - DeleteForeignSessionInternal(tag, &changes); - sync_processor_->ProcessSyncChanges(FROM_HERE, changes); -} - -void SessionsSyncManager::DeleteForeignSessionInternal( - const std::string& tag, syncer::SyncChangeList* change_output) { - if (tag == current_machine_tag()) { - LOG(ERROR) << "Attempting to delete local session. This is not currently " - << "supported."; - return; - } - - std::set<int> tab_node_ids_to_delete; - session_tracker_.LookupTabNodeIds(tag, &tab_node_ids_to_delete); - if (!DisassociateForeignSession(tag)) { - // We don't have any data for this session, our work here is done! - return; - } - - // Prepare deletes for the meta-node as well as individual tab nodes. - change_output->push_back(syncer::SyncChange( - FROM_HERE, - SyncChange::ACTION_DELETE, - SyncData::CreateLocalDelete(tag, syncer::SESSIONS))); - - for (std::set<int>::const_iterator it = tab_node_ids_to_delete.begin(); - it != tab_node_ids_to_delete.end(); - ++it) { - change_output->push_back(syncer::SyncChange( - FROM_HERE, - SyncChange::ACTION_DELETE, - SyncData::CreateLocalDelete(TabNodePool::TabIdToTag(tag, *it), - syncer::SESSIONS))); - } - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED, - content::Source<Profile>(profile_), - content::NotificationService::NoDetails()); -} - -bool SessionsSyncManager::DisassociateForeignSession( - const std::string& foreign_session_tag) { - if (foreign_session_tag == current_machine_tag()) { - DVLOG(1) << "Local session deleted! Doing nothing until a navigation is " - << "triggered."; - return false; - } - DVLOG(1) << "Disassociating session " << foreign_session_tag; - return session_tracker_.DeleteSession(foreign_session_tag); -} - -bool SessionsSyncManager::GetForeignSession( - const std::string& tag, - std::vector<const sessions::SessionWindow*>* windows) { - return session_tracker_.LookupSessionWindows(tag, windows); -} - -bool SessionsSyncManager::GetForeignSessionTabs( - const std::string& tag, - std::vector<const sessions::SessionTab*>* tabs) { - std::vector<const sessions::SessionWindow*> windows; - if (!session_tracker_.LookupSessionWindows(tag, &windows)) - return false; - - // Prune those tabs that are not syncable or are NewTabPage, then sort them - // from most recent to least recent, independent of which window the tabs were - // from. - for (size_t j = 0; j < windows.size(); ++j) { - const sessions::SessionWindow* window = windows[j]; - for (size_t t = 0; t < window->tabs.size(); ++t) { - sessions::SessionTab* const tab = window->tabs[t]; - if (tab->navigations.empty()) - continue; - const sessions::SerializedNavigationEntry& current_navigation = - tab->navigations.at(tab->normalized_navigation_index()); - if (search::IsNTPURL(current_navigation.virtual_url(), profile_)) { - continue; - } - tabs->push_back(tab); - } - } - std::sort(tabs->begin(), tabs->end(), TabsRecencyComparator); - return true; -} - -bool SessionsSyncManager::GetForeignTab( - const std::string& tag, - const SessionID::id_type tab_id, - const sessions::SessionTab** tab) { - const sessions::SessionTab* synced_tab = NULL; - bool success = session_tracker_.LookupSessionTab(tag, - tab_id, - &synced_tab); - if (success) - *tab = synced_tab; - return success; -} - -void SessionsSyncManager::LocalTabDelegateToSpecifics( - const SyncedTabDelegate& tab_delegate, - sync_pb::SessionSpecifics* specifics) { - sessions::SessionTab* session_tab = NULL; - session_tab = - session_tracker_.GetTab(current_machine_tag(), - tab_delegate.GetSessionId(), - tab_delegate.GetSyncId()); - SetSessionTabFromDelegate(GetSyncedWindowDelegatesGetter(), tab_delegate, - base::Time::Now(), session_tab); - SetVariationIds(session_tab); - sync_pb::SessionTab tab_s = session_tab->ToSyncData(); - specifics->set_session_tag(current_machine_tag_); - specifics->set_tab_node_id(tab_delegate.GetSyncId()); - specifics->mutable_tab()->CopyFrom(tab_s); -} - -void SessionsSyncManager::AssociateRestoredPlaceholderTab( - const SyncedTabDelegate& tab_delegate, - SessionID::id_type new_tab_id, - const syncer::SyncDataList& restored_tabs, - syncer::SyncChangeList* change_output) { - DCHECK_NE(tab_delegate.GetSyncId(), TabNodePool::kInvalidTabNodeID); - // Rewrite the tab using |restored_tabs| to retrieve the specifics. - if (restored_tabs.empty()) { - DLOG(WARNING) << "Can't Update tab ID."; - return; - } - - for (syncer::SyncDataList::const_iterator it = restored_tabs.begin(); - it != restored_tabs.end(); - ++it) { - if (it->GetSpecifics().session().tab_node_id() != - tab_delegate.GetSyncId()) { - continue; - } - - sync_pb::EntitySpecifics entity; - sync_pb::SessionSpecifics* specifics = entity.mutable_session(); - specifics->CopyFrom(it->GetSpecifics().session()); - DCHECK(specifics->has_tab()); - - // Update tab node pool with the new association. - local_tab_pool_.ReassociateTabNode(tab_delegate.GetSyncId(), - new_tab_id); - TabLink* tab_link = new TabLink(tab_delegate.GetSyncId(), - &tab_delegate); - local_tab_map_[new_tab_id] = make_linked_ptr<TabLink>(tab_link); - - if (specifics->tab().tab_id() == new_tab_id) - return; - - // The tab_id changed (e.g due to session restore), so update sync. - specifics->mutable_tab()->set_tab_id(new_tab_id); - syncer::SyncData data = syncer::SyncData::CreateLocalData( - TabNodePool::TabIdToTag(current_machine_tag_, - specifics->tab_node_id()), - current_session_name_, - entity); - change_output->push_back(syncer::SyncChange( - FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); - return; - } -} - -// static -void SessionsSyncManager::SetSessionTabFromDelegate( - SyncedWindowDelegatesGetter* synced_window_getter, - const SyncedTabDelegate& tab_delegate, - base::Time mtime, - sessions::SessionTab* session_tab) { - DCHECK(session_tab); - session_tab->window_id.set_id(tab_delegate.GetWindowId()); - session_tab->tab_id.set_id(tab_delegate.GetSessionId()); - session_tab->tab_visual_index = 0; - // Use -1 to indicate that the index hasn't been set properly yet. - session_tab->current_navigation_index = -1; - const SyncedWindowDelegate* window_delegate = - synced_window_getter->FindById(tab_delegate.GetWindowId()); - session_tab->pinned = - window_delegate ? window_delegate->IsTabPinned(&tab_delegate) : false; - session_tab->extension_app_id = tab_delegate.GetExtensionAppId(); - session_tab->user_agent_override.clear(); - session_tab->timestamp = mtime; - const int current_index = tab_delegate.GetCurrentEntryIndex(); - const int min_index = std::max(0, current_index - kMaxSyncNavigationCount); - const int max_index = std::min(current_index + kMaxSyncNavigationCount, - tab_delegate.GetEntryCount()); - bool is_supervised = tab_delegate.ProfileIsSupervised(); - session_tab->navigations.clear(); - - for (int i = min_index; i < max_index; ++i) { - if (!tab_delegate.GetVirtualURLAtIndex(i).is_valid()) - continue; - sessions::SerializedNavigationEntry serialized_entry; - tab_delegate.GetSerializedNavigationAtIndex(i, &serialized_entry); - - // Set current_navigation_index to the index in navigations. - if (i == current_index) - session_tab->current_navigation_index = session_tab->navigations.size(); - - session_tab->navigations.push_back(serialized_entry); - if (is_supervised) { - session_tab->navigations.back().set_blocked_state( - SerializedNavigationEntry::STATE_ALLOWED); - } - } - - // If the current navigation is invalid, set the index to the end of the - // navigation array. - if (session_tab->current_navigation_index < 0) { - session_tab->current_navigation_index = - session_tab->navigations.size() - 1; - } - - if (is_supervised) { - int offset = session_tab->navigations.size(); - const std::vector<const SerializedNavigationEntry*>& blocked_navigations = - *tab_delegate.GetBlockedNavigations(); - for (size_t i = 0; i < blocked_navigations.size(); ++i) { - session_tab->navigations.push_back(*blocked_navigations[i]); - session_tab->navigations.back().set_index(offset + i); - session_tab->navigations.back().set_blocked_state( - SerializedNavigationEntry::STATE_BLOCKED); - // TODO(bauerb): Add categories - } - } - session_tab->session_storage_persistent_id.clear(); -} - -// static -void SessionsSyncManager::SetVariationIds(sessions::SessionTab* session_tab) { - base::FieldTrial::ActiveGroups active_groups; - base::FieldTrialList::GetActiveFieldTrialGroups(&active_groups); - for (const base::FieldTrial::ActiveGroup& group : active_groups) { - const variations::VariationID id = - variations::GetGoogleVariationID(variations::CHROME_SYNC_SERVICE, - group.trial_name, group.group_name); - if (id != variations::EMPTY_ID) - session_tab->variation_ids.push_back(id); - } -} - -FaviconCache* SessionsSyncManager::GetFaviconCache() { - return &favicon_cache_; -} - -SyncedWindowDelegatesGetter* -SessionsSyncManager::GetSyncedWindowDelegatesGetter() const { - return synced_window_getter_; -} - -void SessionsSyncManager::DoGarbageCollection() { - std::vector<const sync_driver::SyncedSession*> sessions; - if (!GetAllForeignSessions(&sessions)) - return; // No foreign sessions. - - // Iterate through all the sessions and delete any with age older than - // |stale_session_threshold_days_|. - syncer::SyncChangeList changes; - for (std::vector<const sync_driver::SyncedSession*>::const_iterator iter = - sessions.begin(); - iter != sessions.end(); ++iter) { - const sync_driver::SyncedSession* session = *iter; - int session_age_in_days = - (base::Time::Now() - session->modified_time).InDays(); - std::string session_tag = session->session_tag; - if (session_age_in_days > 0 && // If false, local clock is not trustworty. - static_cast<size_t>(session_age_in_days) > - stale_session_threshold_days_) { - DVLOG(1) << "Found stale session " << session_tag - << " with age " << session_age_in_days << ", deleting."; - DeleteForeignSessionInternal(session_tag, &changes); - } - } - - if (!changes.empty()) - sync_processor_->ProcessSyncChanges(FROM_HERE, changes); -} - -}; // namespace browser_sync
diff --git a/chrome/browser/sync/sessions/sessions_sync_manager.h b/chrome/browser/sync/sessions/sessions_sync_manager.h deleted file mode 100644 index b85862c..0000000 --- a/chrome/browser/sync/sessions/sessions_sync_manager.h +++ /dev/null
@@ -1,366 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SYNC_SESSIONS_SESSIONS_SYNC_MANAGER_H_ -#define CHROME_BROWSER_SYNC_SESSIONS_SESSIONS_SYNC_MANAGER_H_ - -#include <map> -#include <set> -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/gtest_prod_util.h" -#include "base/memory/weak_ptr.h" -#include "base/time/time.h" -#include "chrome/browser/sync/sessions/page_revisit_broadcaster.h" -#include "components/sessions/core/session_id.h" -#include "components/sessions/core/session_types.h" -#include "components/sync_driver/device_info.h" -#include "components/sync_driver/glue/synced_session.h" -#include "components/sync_driver/open_tabs_ui_delegate.h" -#include "components/sync_driver/sync_prefs.h" -#include "components/sync_driver/tab_node_pool.h" -#include "components/sync_sessions/favicon_cache.h" -#include "components/sync_sessions/local_session_event_router.h" -#include "components/sync_sessions/synced_session_tracker.h" -#include "components/variations/variations_associated_data.h" -#include "sync/api/syncable_service.h" - -class Profile; - -namespace syncer { -class SyncErrorFactory; -} - -namespace sync_driver { -class LocalDeviceInfoProvider; -} - -namespace sync_pb { -class SessionHeader; -class SessionSpecifics; -class SessionTab; -class SessionWindow; -class TabNavigation; -} // namespace sync_pb - -namespace browser_sync { - -class DataTypeErrorHandler; -class SyncedTabDelegate; -class SyncedWindowDelegatesGetter; - -// Contains all logic for associating the Chrome sessions model and -// the sync sessions model. -class SessionsSyncManager : public syncer::SyncableService, - public sync_driver::OpenTabsUIDelegate, - public LocalSessionEventHandler { - public: - SessionsSyncManager(sync_sessions::SyncSessionsClient* sessions_client, - Profile* profile, - sync_driver::LocalDeviceInfoProvider* local_device, - scoped_ptr<LocalSessionEventRouter> router); - ~SessionsSyncManager() override; - - // syncer::SyncableService implementation. - syncer::SyncMergeResult MergeDataAndStartSyncing( - syncer::ModelType type, - const syncer::SyncDataList& initial_sync_data, - scoped_ptr<syncer::SyncChangeProcessor> sync_processor, - scoped_ptr<syncer::SyncErrorFactory> error_handler) override; - void StopSyncing(syncer::ModelType type) override; - syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override; - syncer::SyncError ProcessSyncChanges( - const tracked_objects::Location& from_here, - const syncer::SyncChangeList& change_list) override; - - // OpenTabsUIDelegate implementation. - bool GetSyncedFaviconForPageURL( - const std::string& pageurl, - scoped_refptr<base::RefCountedMemory>* favicon_png) const override; - bool GetAllForeignSessions( - std::vector<const sync_driver::SyncedSession*>* sessions) override; - bool GetForeignSession( - const std::string& tag, - std::vector<const sessions::SessionWindow*>* windows) override; - bool GetForeignTab(const std::string& tag, - const SessionID::id_type tab_id, - const sessions::SessionTab** tab) override; - bool GetForeignSessionTabs( - const std::string& tag, - std::vector<const sessions::SessionTab*>* tabs) override; - void DeleteForeignSession(const std::string& tag) override; - bool GetLocalSession( - const sync_driver::SyncedSession** local_session) override; - - // LocalSessionEventHandler implementation. - void OnLocalTabModified(SyncedTabDelegate* modified_tab) override; - void OnFaviconsChanged(const std::set<GURL>& page_urls, - const GURL& icon_url) override; - - // Returns the tag used to uniquely identify this machine's session in the - // sync model. - const std::string& current_machine_tag() const { - DCHECK(!current_machine_tag_.empty()); - return current_machine_tag_; - } - - FaviconCache* GetFaviconCache(); - - SyncedWindowDelegatesGetter* GetSyncedWindowDelegatesGetter() const; - - // Triggers garbage collection of stale sessions (as defined by - // |stale_session_threshold_days_|). This is called automatically every - // time we start up (via AssociateModels) and when new sessions data is - // downloaded (sync cycles complete). - void DoGarbageCollection(); - - private: - // Keep all the links to local tab data in one place. A tab_node_id and tab - // must be passed at creation. The tab_node_id is not mutable, although - // all other fields are. - class TabLink { - public: - TabLink(int tab_node_id, const SyncedTabDelegate* tab) - : tab_node_id_(tab_node_id), - tab_(tab) {} - - void set_tab(const SyncedTabDelegate* tab) { tab_ = tab; } - void set_url(const GURL& url) { url_ = url; } - - int tab_node_id() const { return tab_node_id_; } - const SyncedTabDelegate* tab() const { return tab_; } - const GURL& url() const { return url_; } - - private: - // The id for the sync node this tab is stored in. - const int tab_node_id_; - - // The tab object itself. - const SyncedTabDelegate* tab_; - - // The currently visible url of the tab (used for syncing favicons). - GURL url_; - - DISALLOW_COPY_AND_ASSIGN(TabLink); - }; - - // Container for accessing local tab data by tab id. - typedef std::map<SessionID::id_type, linked_ptr<TabLink> > TabLinksMap; - - FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, PopulateSessionHeader); - FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, PopulateSessionWindow); - FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, ValidTabs); - FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, SetSessionTabFromDelegate); - FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, - SetSessionTabFromDelegateNavigationIndex); - FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, - SetSessionTabFromDelegateCurrentInvalid); - FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, BlockedNavigations); - FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, DeleteForeignSession); - FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, - SaveUnassociatedNodesForReassociation); - FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, MergeDeletesCorruptNode); - FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, - MergeLocalSessionExistingTabs); - FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, - CheckPrerenderedWebContentsSwap); - FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, - AssociateWindowsDontReloadTabs); - FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, - SwappedOutOnRestore); - FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, - ProcessRemoteDeleteOfLocalSession); - FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, - SetVariationIds); - - void InitializeCurrentMachineTag(); - - // Load and add window or tab data for a foreign session to our internal - // tracking. - void UpdateTrackerWithForeignSession( - const sync_pb::SessionSpecifics& specifics, - const base::Time& modification_time); - - // Returns true if |sync_data| contained a header node for the current - // machine, false otherwise. |restored_tabs| is a filtered tab-only - // subset of |sync_data| returned by this function for convenience. - // |new_changes| is a link to the SyncChange pipeline that exists in the - // caller's context. This function will append necessary changes for - // processing later. - bool InitFromSyncModel(const syncer::SyncDataList& sync_data, - syncer::SyncDataList* restored_tabs, - syncer::SyncChangeList* new_changes); - - // Helper to construct a deletion SyncChange for a *tab node*. - // Caller should check IsValid() on the returned change, as it's possible - // this node could not be deleted. - syncer::SyncChange TombstoneTab(const sync_pb::SessionSpecifics& tab); - - // Helper method to load the favicon data from the tab specifics. If the - // favicon is valid, stores the favicon data into the favicon cache. - void RefreshFaviconVisitTimesFromForeignTab( - const sync_pb::SessionTab& tab, const base::Time& modification_time); - - // Removes a foreign session from our internal bookkeeping. - // Returns true if the session was found and deleted, false if no data was - // found for that session. This will *NOT* trigger sync deletions. See - // DeleteForeignSession below. - bool DisassociateForeignSession(const std::string& foreign_session_tag); - - // Delete a foreign session and all its sync data. - // |change_output| *must* be provided as a link to the SyncChange pipeline - // that exists in the caller's context. This function will append necessary - // changes for processing later. - void DeleteForeignSessionInternal(const std::string& tag, - syncer::SyncChangeList* change_output); - - // Used to populate a session header from the session specifics header - // provided. - static void PopulateSessionHeaderFromSpecifics( - const sync_pb::SessionHeader& header_specifics, - base::Time mtime, - sync_driver::SyncedSession* session_header); - - // Builds |session_window| from the session specifics window - // provided and updates the SessionTracker with foreign session data created. - void BuildSyncedSessionFromSpecifics( - const std::string& session_tag, - const sync_pb::SessionWindow& specifics, - base::Time mtime, - sessions::SessionWindow* session_window); - - // Resync local window information. Updates the local sessions header node - // with the status of open windows and the order of tabs they contain. Should - // only be called for changes that affect a window, not a change within a - // single tab. - // - // RELOAD_TABS will additionally cause a resync of all tabs (same as calling - // AssociateTabs with a vector of all tabs). - // - // |restored_tabs| is a filtered tab-only subset of initial sync data, if - // available (during MergeDataAndStartSyncing). It can be used to obtain - // baseline SessionSpecifics for tabs we can't fully associate any other - // way because they don't yet have a WebContents. - // - // Returns: false if the local session's sync nodes were deleted and - // reassociation is necessary, true otherwise. - // - // |change_output| *must* be provided as a link to the SyncChange pipeline - // that exists in the caller's context. This function will append necessary - // changes for processing later. - enum ReloadTabsOption { - RELOAD_TABS, - DONT_RELOAD_TABS - }; - void AssociateWindows(ReloadTabsOption option, - const syncer::SyncDataList& restored_tabs, - syncer::SyncChangeList* change_output); - - // Loads and reassociates the local tabs referenced in |tabs|. - // |change_output| *must* be provided as a link to the SyncChange pipeline - // that exists in the caller's context. This function will append necessary - // changes for processing later. - void AssociateTab(SyncedTabDelegate* const tab, - syncer::SyncChangeList* change_output); - - // Set |session_tab| from |tab_delegate| and |mtime|. - static void SetSessionTabFromDelegate( - SyncedWindowDelegatesGetter* synced_window_getter, - const SyncedTabDelegate& tab_delegate, - base::Time mtime, - sessions::SessionTab* session_tab); - - // Sets |variation_ids| field of |session_tab| with the ids of the currently - // assigned variations which should be sent to sync. - static void SetVariationIds(sessions::SessionTab* session_tab); - - // Populates |specifics| based on the data in |tab_delegate|. - void LocalTabDelegateToSpecifics(const SyncedTabDelegate& tab_delegate, - sync_pb::SessionSpecifics* specifics); - - // It's possible that when we associate windows, tabs aren't all loaded - // into memory yet (e.g on android) and we don't have a WebContents. In this - // case we can't do a full association, but we still want to update tab IDs - // as they may have changed after a session was restored. This method - // compares new_tab_id against the previously persisted tab ID (from - // our TabNodePool) and updates it if it differs. - // |restored_tabs| is a filtered tab-only subset of initial sync data, if - // available (during MergeDataAndStartSyncing). It can be used to obtain - // baseline SessionSpecifics for tabs we can't fully associate any other - // way because they don't yet have a WebContents. - // TODO(tim): Bug 98892. We should be able to test this for this on android - // even though we didn't have tests for old API-based sessions sync. - void AssociateRestoredPlaceholderTab( - const SyncedTabDelegate& tab_delegate, - SessionID::id_type new_tab_id, - const syncer::SyncDataList& restored_tabs, - syncer::SyncChangeList* change_output); - - // Stops and re-starts syncing to rebuild association mappings. - // See |local_tab_pool_out_of_sync_|. - void RebuildAssociations(); - - // Validates the content of a SessionHeader protobuf. - // Returns false if validation fails. - static bool IsValidSessionHeader(const sync_pb::SessionHeader& header); - - // The client of this sync sessions datatype. - sync_sessions::SyncSessionsClient* const sessions_client_; - - // Mapping of current open (local) tabs to their sync identifiers. - TabLinksMap local_tab_map_; - - SyncedSessionTracker session_tracker_; - FaviconCache favicon_cache_; - - // Pool of used/available sync nodes associated with local tabs. - TabNodePool local_tab_pool_; - - // Tracks whether our local representation of which sync nodes map to what - // tabs (belonging to the current local session) is inconsistent. This can - // happen if a foreign client deems our session as "stale" and decides to - // delete it. Rather than respond by bullishly re-creating our nodes - // immediately, which could lead to ping-pong sequences, we give the benefit - // of the doubt and hold off until another local navigation occurs, which - // proves that we are still relevant. - bool local_tab_pool_out_of_sync_; - - sync_driver::SyncPrefs sync_prefs_; - - Profile* const profile_; - - scoped_ptr<syncer::SyncErrorFactory> error_handler_; - scoped_ptr<syncer::SyncChangeProcessor> sync_processor_; - - // Local device info provider, owned by ProfileSyncService. - const sync_driver::LocalDeviceInfoProvider* const local_device_; - - // Unique client tag. - std::string current_machine_tag_; - - // User-visible machine name. - std::string current_session_name_; - - // SyncID for the sync node containing all the window information for this - // client. - int local_session_header_node_id_; - - // Number of days without activity after which we consider a session to be - // stale and a candidate for garbage collection. - size_t stale_session_threshold_days_; - - scoped_ptr<LocalSessionEventRouter> local_event_router_; - SyncedWindowDelegatesGetter* synced_window_getter_; - - // Owns revisiting instrumentation logic for page visit events. - PageRevisitBroadcaster page_revisit_broadcaster_; - - DISALLOW_COPY_AND_ASSIGN(SessionsSyncManager); -}; - -} // namespace browser_sync - -#endif // CHROME_BROWSER_SYNC_SESSIONS_SESSIONS_SYNC_MANAGER_H_
diff --git a/chrome/browser/sync/sessions/sessions_sync_manager_unittest.cc b/chrome/browser/sync/sessions/sessions_sync_manager_unittest.cc index e91cb64..9d052ed1 100644 --- a/chrome/browser/sync/sessions/sessions_sync_manager_unittest.cc +++ b/chrome/browser/sync/sessions/sessions_sync_manager_unittest.cc
@@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/sync/sessions/sessions_sync_manager.h" +#include "components/sync_sessions/sessions_sync_manager.h" #include "base/strings/string_util.h" -#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/sessions/session_tab_helper.h" #include "chrome/browser/sync/chrome_sync_client.h" #include "chrome/browser/sync/glue/session_sync_test_helper.h" @@ -25,9 +24,6 @@ #include "components/sync_driver/sync_api_component_factory.h" #include "components/sync_sessions/synced_tab_delegate.h" #include "content/public/browser/navigation_entry.h" -#include "content/public/browser/notification_details.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_source.h" #include "content/public/browser/web_contents.h" #include "sync/api/attachments/attachment_id.h" #include "sync/api/sync_error_factory_mock.h" @@ -49,6 +45,26 @@ namespace { +class SessionNotificationObserver { + public: + SessionNotificationObserver() + : notified_of_update_(false), notified_of_refresh_(false) {} + void NotifyOfUpdate() { notified_of_update_ = true; } + void NotifyOfRefresh() { notified_of_refresh_ = true; } + + bool notified_of_update() const { return notified_of_update_; } + bool notified_of_refresh() const { return notified_of_refresh_; } + + void Reset() { + notified_of_update_ = false; + notified_of_refresh_ = false; + } + + private: + bool notified_of_update_; + bool notified_of_refresh_; +}; + class SyncedWindowDelegateOverride : public SyncedWindowDelegate { public: explicit SyncedWindowDelegateOverride(const SyncedWindowDelegate* wrapped) @@ -266,14 +282,20 @@ new browser_sync::NotificationServiceSessionsRouter( profile(), GetSyncSessionsClient(), syncer::SyncableService::StartSyncFlare())); + sync_prefs_.reset(new sync_driver::SyncPrefs(profile()->GetPrefs())); manager_.reset(new SessionsSyncManager( - GetSyncSessionsClient(), profile(), local_device_.get(), - scoped_ptr<LocalSessionEventRouter>(router))); + GetSyncSessionsClient(), sync_prefs_.get(), local_device_.get(), + scoped_ptr<LocalSessionEventRouter>(router), + base::Bind(&SessionNotificationObserver::NotifyOfUpdate, + base::Unretained(&observer_)), + base::Bind(&SessionNotificationObserver::NotifyOfRefresh, + base::Unretained(&observer_)))); } void TearDown() override { test_processor_ = NULL; helper()->Reset(); + sync_prefs_.reset(); manager_.reset(); BrowserWithTestWindowTest::TearDown(); } @@ -285,6 +307,7 @@ SessionsSyncManager* manager() { return manager_.get(); } SessionSyncTestHelper* helper() { return &helper_; } LocalDeviceInfoProvider* local_device() { return local_device_.get(); } + SessionNotificationObserver* observer() { return &observer_; } void InitWithSyncDataTakeOutput(const syncer::SyncDataList& initial_data, syncer::SyncChangeList* output) { @@ -334,8 +357,12 @@ return sync_client_->GetSyncSessionsClient(); } + sync_driver::SyncPrefs* sync_prefs() { return sync_prefs_.get(); } + private: scoped_ptr<browser_sync::ChromeSyncClient> sync_client_; + scoped_ptr<sync_driver::SyncPrefs> sync_prefs_; + SessionNotificationObserver observer_; scoped_ptr<SessionsSyncManager> manager_; SessionSyncTestHelper helper_; TestSyncProcessorStub* test_processor_; @@ -822,8 +849,9 @@ syncer::AttachmentServiceProxyForTest::Create())); syncer::SyncDataList in(&d, &d + 1); out.clear(); - SessionsSyncManager manager2(GetSyncSessionsClient(), profile(), - local_device(), NewDummyRouter()); + SessionsSyncManager manager2(GetSyncSessionsClient(), sync_prefs(), + local_device(), NewDummyRouter(), + base::Closure(), base::Closure()); syncer::SyncMergeResult result = manager2.MergeDataAndStartSyncing( syncer::SESSIONS, in, scoped_ptr<syncer::SyncChangeProcessor>( @@ -1412,8 +1440,9 @@ syncer::AttachmentServiceProxyForTest::Create())); syncer::SyncDataList in(&d, &d + 1); changes.clear(); - SessionsSyncManager manager2(GetSyncSessionsClient(), profile(), - local_device(), NewDummyRouter()); + SessionsSyncManager manager2(GetSyncSessionsClient(), sync_prefs(), + local_device(), NewDummyRouter(), + base::Closure(), base::Closure()); syncer::SyncMergeResult result = manager2.MergeDataAndStartSyncing( syncer::SESSIONS, in, scoped_ptr<syncer::SyncChangeProcessor>( @@ -1908,49 +1937,10 @@ ASSERT_EQ(19U, out.size()); } -namespace { -class SessionNotificationObserver : public content::NotificationObserver { - public: - SessionNotificationObserver() : notified_of_update_(false), - notified_of_refresh_(false) { - registrar_.Add(this, chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED, - content::NotificationService::AllSources()); - registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL, - content::NotificationService::AllSources()); - } - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override { - switch (type) { - case chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED: - notified_of_update_ = true; - break; - case chrome::NOTIFICATION_SYNC_REFRESH_LOCAL: - notified_of_refresh_ = true; - break; - default: - NOTREACHED(); - break; - } - } - bool notified_of_update() const { return notified_of_update_; } - bool notified_of_refresh() const { return notified_of_refresh_; } - void Reset() { - notified_of_update_ = false; - notified_of_refresh_ = false; - } - private: - content::NotificationRegistrar registrar_; - bool notified_of_update_; - bool notified_of_refresh_; -}; -} // namespace - // Test that NOTIFICATION_FOREIGN_SESSION_UPDATED is sent when processing // sync changes. TEST_F(SessionsSyncManagerTest, NotifiedOfUpdates) { - SessionNotificationObserver observer; - ASSERT_FALSE(observer.notified_of_update()); + ASSERT_FALSE(observer()->notified_of_update()); InitWithNoSyncData(); SessionID::id_type n[] = {5}; @@ -1962,19 +1952,19 @@ syncer::SyncChangeList changes; changes.push_back(MakeRemoteChange(1, meta, SyncChange::ACTION_ADD)); manager()->ProcessSyncChanges(FROM_HERE, changes); - EXPECT_TRUE(observer.notified_of_update()); + EXPECT_TRUE(observer()->notified_of_update()); changes.clear(); - observer.Reset(); + observer()->Reset(); AddTabsToChangeList(tabs1, SyncChange::ACTION_ADD, &changes); manager()->ProcessSyncChanges(FROM_HERE, changes); - EXPECT_TRUE(observer.notified_of_update()); + EXPECT_TRUE(observer()->notified_of_update()); changes.clear(); - observer.Reset(); + observer()->Reset(); changes.push_back(MakeRemoteChange(1, meta, SyncChange::ACTION_DELETE)); manager()->ProcessSyncChanges(FROM_HERE, changes); - EXPECT_TRUE(observer.notified_of_update()); + EXPECT_TRUE(observer()->notified_of_update()); } // Test that NOTIFICATION_FOREIGN_SESSION_UPDATED is sent when handling @@ -1992,10 +1982,10 @@ changes.push_back(MakeRemoteChange(1, meta, SyncChange::ACTION_ADD)); manager()->ProcessSyncChanges(FROM_HERE, changes); - SessionNotificationObserver observer; - ASSERT_FALSE(observer.notified_of_update()); + observer()->Reset(); + ASSERT_FALSE(observer()->notified_of_update()); manager()->DeleteForeignSession(tag); - ASSERT_TRUE(observer.notified_of_update()); + ASSERT_TRUE(observer()->notified_of_update()); } #if defined(OS_ANDROID) || defined(OS_IOS) @@ -2003,13 +1993,12 @@ // This page only exists on mobile platforms today; desktop has a // search-enhanced NTP without other devices. TEST_F(SessionsSyncManagerTest, NotifiedOfRefresh) { - SessionNotificationObserver observer; - ASSERT_FALSE(observer.notified_of_refresh()); + ASSERT_FALSE(observer()->notified_of_refresh()); InitWithNoSyncData(); AddTab(browser(), GURL("http://foo1")); - EXPECT_FALSE(observer.notified_of_refresh()); + EXPECT_FALSE(observer()->notified_of_refresh()); NavigateAndCommitActiveTab(GURL("chrome://newtab/#open_tabs")); - EXPECT_TRUE(observer.notified_of_refresh()); + EXPECT_TRUE(observer()->notified_of_refresh()); } #endif // defined(OS_ANDROID) || defined(OS_IOS)
diff --git a/chrome/browser/sync/test/integration/password_manager_setting_migrator_helper.cc b/chrome/browser/sync/test/integration/password_manager_setting_migrator_helper.cc index 94b1e55..cb0f919 100644 --- a/chrome/browser/sync/test/integration/password_manager_setting_migrator_helper.cc +++ b/chrome/browser/sync/test/integration/password_manager_setting_migrator_helper.cc
@@ -7,13 +7,13 @@ #include "base/metrics/field_trial.h" #include "base/prefs/pref_service.h" #include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/password_manager/password_manager_setting_migrator_service.h" #include "chrome/browser/password_manager/password_manager_setting_migrator_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/sync/test/integration/preferences_helper.h" #include "components/password_manager/core/common/password_manager_pref_names.h" +#include "components/password_manager/sync/browser/password_manager_setting_migrator_service.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h"
diff --git a/chrome/browser/sync/test/integration/sessions_helper.cc b/chrome/browser/sync/test/integration/sessions_helper.cc index eb72f7e0..187d9c5 100644 --- a/chrome/browser/sync/test/integration/sessions_helper.cc +++ b/chrome/browser/sync/test/integration/sessions_helper.cc
@@ -19,7 +19,6 @@ #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/sync/sessions/notification_service_sessions_router.h" -#include "chrome/browser/sync/sessions/sessions_sync_manager.h" #include "chrome/browser/sync/test/integration/multi_client_status_change_checker.h" #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" #include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
diff --git a/chrome/browser/translate/translate_browsertest.cc b/chrome/browser/translate/translate_browsertest.cc index eaa53a5..ff7ebbac 100644 --- a/chrome/browser/translate/translate_browsertest.cc +++ b/chrome/browser/translate/translate_browsertest.cc
@@ -8,6 +8,7 @@ #include "base/command_line.h" #include "base/files/file_path.h" +#include "base/path_service.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/chrome_notification_types.h" @@ -15,6 +16,7 @@ #include "chrome/browser/translate/translate_service.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/chrome_paths.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/test_switches.h" #include "chrome/test/base/ui_test_utils.h" @@ -35,55 +37,59 @@ const base::FilePath::CharType kTranslateRoot[] = FILE_PATH_LITERAL("chrome/test/data/translate"); -const char kNonSecurePrefix[] = "/translate/"; +const char kNonSecurePrefix[] = "translate/"; const char kSecurePrefix[] = "files/"; -const char kFrenchTestPath[] = "fr_test.html"; -const char kRefreshMetaTagTestPath[] = "refresh_meta_tag.html"; +const char kFrenchTestPath[] = "/fr_test.html"; +const char kBasicFrenchTestPath[] = "/basic_fr_test.html"; +const char kRefreshMetaTagTestPath[] = "/refresh_meta_tag.html"; const char kRefreshMetaTagCaseInsensitiveTestPath[] = - "refresh_meta_tag_casei.html"; + "/refresh_meta_tag_casei.html"; const char kRefreshMetaTagAtOnloadTestPath[] = - "refresh_meta_tag_at_onload.html"; -const char kUpdateLocationTestPath[] = "update_location.html"; -const char kUpdateLocationAtOnloadTestPath[] = "update_location_at_onload.html"; -const char kMainScriptPath[] = "pseudo_main.js"; -const char kElementMainScriptPath[] = "pseudo_element_main.js"; + "/refresh_meta_tag_at_onload.html"; +const char kUpdateLocationTestPath[] = "/update_location.html"; +const char kUpdateLocationAtOnloadTestPath[] = + "/update_location_at_onload.html"; +const char kMainScriptPath[] = "/pseudo_main.js"; +const char kElementMainScriptPath[] = "/pseudo_element_main.js"; }; // namespace -class TranslateBrowserTest : public InProcessBrowserTest { +// Basic translate browser test with an embedded non-secure test server. +class TranslateBaseBrowserTest : public InProcessBrowserTest { public: - TranslateBrowserTest() - : https_server_(net::SpawnedTestServer::TYPE_HTTPS, - SSLOptions(SSLOptions::CERT_OK), - base::FilePath(kTranslateRoot)), - infobar_service_(NULL) {} + TranslateBaseBrowserTest() {} void SetUp() override { + set_open_about_blank_on_browser_launch(false); translate::TranslateManager::SetIgnoreMissingKeyForTesting(true); InProcessBrowserTest::SetUp(); } - void SetUpCommandLine(base::CommandLine* command_line) override { - ASSERT_TRUE(https_server_.Start()); - // Setup alternate security origin for testing in order to allow XHR against - // local test server. Note that this flag shows a confirm infobar in tests. - GURL base_url = GetSecureURL(""); - command_line->AppendSwitchASCII( - translate::switches::kTranslateSecurityOrigin, - base_url.GetOrigin().spec()); + void SetUpOnMainThread() override { + net::test_server::EmbeddedTestServer* test_server = embedded_test_server(); + base::FilePath test_data_dir; + PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir); + test_data_dir = test_data_dir.AppendASCII(kNonSecurePrefix); + test_server->ServeFilesFromDirectory(test_data_dir); + ASSERT_TRUE(test_server->InitializeAndWaitUntilReady()); + InProcessBrowserTest::SetUpOnMainThread(); } protected: GURL GetNonSecureURL(const std::string& path) const { - std::string prefix(kNonSecurePrefix); - return embedded_test_server()->GetURL(prefix + path); + return embedded_test_server()->GetURL(path); } - GURL GetSecureURL(const std::string& path) const { - std::string prefix(kSecurePrefix); - return https_server_.GetURL(prefix + path); - } + private: + DISALLOW_COPY_AND_ASSIGN(TranslateBaseBrowserTest); +}; +// Translate browser test for loading a page and checking infobar UI. +class TranslateBrowserTest : public TranslateBaseBrowserTest { + public: + TranslateBrowserTest() : infobar_service_(NULL) {} + + protected: translate::TranslateInfoBarDelegate* GetExistingTranslateInfoBarDelegate() { if (!infobar_service_) { content::WebContents* web_contents = @@ -103,14 +109,13 @@ // This infobar appears in all tests of TranslateBrowserTest and can be // ignored here. if (infobar_service_->infobar_at(i)->delegate()-> - AsConfirmInfoBarDelegate()) { + AsConfirmInfoBarDelegate()) { continue; } translate::TranslateInfoBarDelegate* translate = - infobar_service_->infobar_at(i) - ->delegate() - ->AsTranslateInfoBarDelegate(); + infobar_service_->infobar_at(i)->delegate()-> + AsTranslateInfoBarDelegate(); if (translate) { EXPECT_FALSE(delegate) << "multiple infobars are shown unexpectedly"; delegate = translate; @@ -123,32 +128,108 @@ return delegate; } + void LoadPageWithInfobar(const std::string& path) { + // Setup infobar observer. + content::WindowedNotificationObserver infobar( + chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED, + content::NotificationService::AllSources()); + + // Visit non-secure page which is going to be translated. + ui_test_utils::NavigateToURL(browser(), GetNonSecureURL(path)); + + // Wait for Chrome Translate infobar. + infobar.Wait(); + } + + void LoadPageWithoutInfobar(const std::string& path) { + // If infobar won't be triggered, we need to use another observer. + // Setup page title observer. + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + ASSERT_TRUE(web_contents); + content::TitleWatcher watcher(web_contents, base::ASCIIToUTF16("PASS")); + watcher.AlsoWaitForTitle(base::ASCIIToUTF16("FAIL")); + + // Visit non-secure page which is going to be translated. + ui_test_utils::NavigateToURL(browser(), GetNonSecureURL(path)); + + // Wait for the page title is changed after the test finished. + const base::string16 result = watcher.WaitAndGetTitle(); + EXPECT_EQ("PASS", base::UTF16ToASCII(result)); + } + + void CheckForTranslateUI(const std::string& path, bool should_trigger_UI) { + ASSERT_FALSE(TranslateService::IsTranslateBubbleEnabled()); + // Check if there is no Translate infobar. + translate::TranslateInfoBarDelegate* delegate = + GetExistingTranslateInfoBarDelegate(); + EXPECT_FALSE(delegate); + + if (should_trigger_UI) { + ASSERT_NO_FATAL_FAILURE(LoadPageWithInfobar(path)); + } else { + ASSERT_NO_FATAL_FAILURE(LoadPageWithoutInfobar(path)); + } + + // Check whether the translate infobar showed up. + delegate = GetExistingTranslateInfoBarDelegate(); + if (should_trigger_UI) { + // Check if there is a translate infobar. + EXPECT_TRUE(delegate); + } else { + // Check if there is no translate infobar. + EXPECT_FALSE(delegate); + } + } + + void Translate() { + translate::TranslateInfoBarDelegate* delegate = + GetExistingTranslateInfoBarDelegate(); + ASSERT_TRUE(delegate); + delegate->Translate(); + } + + private: + InfoBarService* infobar_service_; +}; + +// Translate browser test with a seperate secure server setup. +class TranslateWithSecureServerBrowserTest : public TranslateBrowserTest { + public: + TranslateWithSecureServerBrowserTest() + : https_server_(net::SpawnedTestServer::TYPE_HTTPS, + SSLOptions(SSLOptions::CERT_OK), + base::FilePath(kTranslateRoot)) {} + + void SetUpCommandLine(base::CommandLine* command_line) override { + ASSERT_TRUE(https_server_.Start()); + // Setup alternate security origin for testing in order to allow XHR against + // local test server. Note that this flag shows a confirm infobar in tests. + GURL base_url = GetSecureURL(""); + command_line->AppendSwitchASCII( + translate::switches::kTranslateSecurityOrigin, + base_url.GetOrigin().spec()); + TranslateBrowserTest::SetUpCommandLine(command_line); + } + + protected: + GURL GetSecureURL(const std::string& path) const { + std::string prefix(kSecurePrefix); + return https_server_.GetURL(prefix + path); + } + private: net::SpawnedTestServer https_server_; - InfoBarService* infobar_service_; typedef net::SpawnedTestServer::SSLOptions SSLOptions; - DISALLOW_COPY_AND_ASSIGN(TranslateBrowserTest); + DISALLOW_COPY_AND_ASSIGN(TranslateWithSecureServerBrowserTest); }; -IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, TranslateInIsolatedWorld) { - // TODO(port): Test corresponding bubble translate UX: http://crbug.com/383235 - if (TranslateService::IsTranslateBubbleEnabled()) - return; - +IN_PROC_BROWSER_TEST_F(TranslateWithSecureServerBrowserTest, + TranslateInIsolatedWorld) { net::TestURLFetcherFactory factory; - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); - - // Check if there is no Translate infobar. - translate::TranslateInfoBarDelegate* translate = - GetExistingTranslateInfoBarDelegate(); - EXPECT_FALSE(translate); - - // Setup infobar observer. - content::WindowedNotificationObserver infobar( - chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED, - content::NotificationService::AllSources()); + ASSERT_NO_FATAL_FAILURE(CheckForTranslateUI(kFrenchTestPath, true)); // Setup page title observer. content::WebContents* web_contents = @@ -157,16 +238,8 @@ content::TitleWatcher watcher(web_contents, base::ASCIIToUTF16("PASS")); watcher.AlsoWaitForTitle(base::ASCIIToUTF16("FAIL")); - // Visit non-secure page which is going to be translated. - ui_test_utils::NavigateToURL(browser(), GetNonSecureURL(kFrenchTestPath)); - - // Wait for Chrome Translate infobar. - infobar.Wait(); - - // Perform Chrome Translate. - translate = GetExistingTranslateInfoBarDelegate(); - ASSERT_TRUE(translate); - translate->Translate(); + // Perform translate. + ASSERT_NO_FATAL_FAILURE(Translate()); // Hook URLFetcher for element.js. GURL script1_url = GetSecureURL(kMainScriptPath); @@ -198,169 +271,33 @@ EXPECT_EQ("PASS", base::UTF16ToASCII(result)); } +IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, BasicTranslation) { + ASSERT_NO_FATAL_FAILURE(CheckForTranslateUI(kBasicFrenchTestPath, true)); +} + IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, IgnoreRefreshMetaTag) { - // TODO(port): Test corresponding bubble translate UX: http://crbug.com/383235 - if (TranslateService::IsTranslateBubbleEnabled()) - return; - - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); - - // Check if there is no Translate infobar. - translate::TranslateInfoBarDelegate* translate = - GetExistingTranslateInfoBarDelegate(); - EXPECT_FALSE(translate); - - // Setup page title observer. - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - ASSERT_TRUE(web_contents); - content::TitleWatcher watcher(web_contents, base::ASCIIToUTF16("PASS")); - watcher.AlsoWaitForTitle(base::ASCIIToUTF16("FAIL")); - - // Visit a test page. - ui_test_utils::NavigateToURL( - browser(), - GetNonSecureURL(kRefreshMetaTagTestPath)); - - // Wait for the page title is changed after the test finished. - const base::string16 result = watcher.WaitAndGetTitle(); - EXPECT_EQ("PASS", base::UTF16ToASCII(result)); - - // Check if there is no Translate infobar. - translate = GetExistingTranslateInfoBarDelegate(); - EXPECT_FALSE(translate); + ASSERT_NO_FATAL_FAILURE(CheckForTranslateUI( + kRefreshMetaTagTestPath, false)); } IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, IgnoreRefreshMetaTagInCaseInsensitive) { - // TODO(port): Test corresponding bubble translate UX: http://crbug.com/383235 - if (TranslateService::IsTranslateBubbleEnabled()) - return; - - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); - - // Check if there is no Translate infobar. - translate::TranslateInfoBarDelegate* translate = - GetExistingTranslateInfoBarDelegate(); - EXPECT_FALSE(translate); - - // Setup page title observer. - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - ASSERT_TRUE(web_contents); - content::TitleWatcher watcher(web_contents, base::ASCIIToUTF16("PASS")); - watcher.AlsoWaitForTitle(base::ASCIIToUTF16("FAIL")); - - // Visit a test page. - ui_test_utils::NavigateToURL( - browser(), - GetNonSecureURL(kRefreshMetaTagCaseInsensitiveTestPath)); - - // Wait for the page title is changed after the test finished. - const base::string16 result = watcher.WaitAndGetTitle(); - EXPECT_EQ("PASS", base::UTF16ToASCII(result)); - - // Check if there is no Translate infobar. - translate = GetExistingTranslateInfoBarDelegate(); - EXPECT_FALSE(translate); + ASSERT_NO_FATAL_FAILURE(CheckForTranslateUI( + kRefreshMetaTagCaseInsensitiveTestPath, false)); } IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, IgnoreRefreshMetaTagAtOnload) { - // TODO(port): Test corresponding bubble translate UX: http://crbug.com/383235 - if (TranslateService::IsTranslateBubbleEnabled()) - return; - - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); - - // Check if there is no Translate infobar. - translate::TranslateInfoBarDelegate* translate = - GetExistingTranslateInfoBarDelegate(); - EXPECT_FALSE(translate); - - // Setup page title observer. - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - ASSERT_TRUE(web_contents); - content::TitleWatcher watcher(web_contents, base::ASCIIToUTF16("PASS")); - watcher.AlsoWaitForTitle(base::ASCIIToUTF16("FAIL")); - - // Visit a test page. - ui_test_utils::NavigateToURL( - browser(), - GetNonSecureURL(kRefreshMetaTagAtOnloadTestPath)); - - // Wait for the page title is changed after the test finished. - const base::string16 result = watcher.WaitAndGetTitle(); - EXPECT_EQ("PASS", base::UTF16ToASCII(result)); - - // Check if there is no Translate infobar. - translate = GetExistingTranslateInfoBarDelegate(); - EXPECT_FALSE(translate); + ASSERT_NO_FATAL_FAILURE(CheckForTranslateUI( + kRefreshMetaTagAtOnloadTestPath, false)); } IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, UpdateLocation) { - // TODO(port): Test corresponding bubble translate UX: http://crbug.com/383235 - if (TranslateService::IsTranslateBubbleEnabled()) - return; - - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); - - // Check if there is no Translate infobar. - translate::TranslateInfoBarDelegate* translate = - GetExistingTranslateInfoBarDelegate(); - EXPECT_FALSE(translate); - - // Setup page title observer. - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - ASSERT_TRUE(web_contents); - content::TitleWatcher watcher(web_contents, base::ASCIIToUTF16("PASS")); - watcher.AlsoWaitForTitle(base::ASCIIToUTF16("FAIL")); - - // Visit a test page. - ui_test_utils::NavigateToURL( - browser(), - GetNonSecureURL(kUpdateLocationTestPath)); - - // Wait for the page title is changed after the test finished. - const base::string16 result = watcher.WaitAndGetTitle(); - EXPECT_EQ("PASS", base::UTF16ToASCII(result)); - - // Check if there is no Translate infobar. - translate = GetExistingTranslateInfoBarDelegate(); - EXPECT_FALSE(translate); + ASSERT_NO_FATAL_FAILURE(CheckForTranslateUI( + kUpdateLocationTestPath, false)); } IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, UpdateLocationAtOnload) { - // TODO(port): Test corresponding bubble translate UX: http://crbug.com/383235 - if (TranslateService::IsTranslateBubbleEnabled()) - return; - - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); - - // Check if there is no Translate infobar. - translate::TranslateInfoBarDelegate* translate = - GetExistingTranslateInfoBarDelegate(); - EXPECT_FALSE(translate); - - // Setup page title observer. - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - ASSERT_TRUE(web_contents); - content::TitleWatcher watcher(web_contents, base::ASCIIToUTF16("PASS")); - watcher.AlsoWaitForTitle(base::ASCIIToUTF16("FAIL")); - - // Visit a test page. - ui_test_utils::NavigateToURL( - browser(), - GetNonSecureURL(kUpdateLocationAtOnloadTestPath)); - - // Wait for the page title is changed after the test finished. - const base::string16 result = watcher.WaitAndGetTitle(); - EXPECT_EQ("PASS", base::UTF16ToASCII(result)); - - // Check if there is no Translate infobar. - translate = GetExistingTranslateInfoBarDelegate(); - EXPECT_FALSE(translate); + ASSERT_NO_FATAL_FAILURE(CheckForTranslateUI( + kUpdateLocationAtOnloadTestPath, false)); } #endif // !defined(USE_AURA)
diff --git a/chrome/browser/ui/android/infobars/auto_signin_first_run_infobar.cc b/chrome/browser/ui/android/infobars/auto_signin_first_run_infobar.cc new file mode 100644 index 0000000..4e57af4 --- /dev/null +++ b/chrome/browser/ui/android/infobars/auto_signin_first_run_infobar.cc
@@ -0,0 +1,51 @@ +// Copyright 2015 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/android/infobars/auto_signin_first_run_infobar.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "components/password_manager/core/common/credential_manager_types.h" +#include "jni/AutoSigninFirstRunInfoBar_jni.h" + +AutoSigninFirstRunInfoBar::AutoSigninFirstRunInfoBar( + scoped_ptr<AutoSigninFirstRunInfoBarDelegate> delegate) + : ConfirmInfoBar(delegate.Pass()) {} + +AutoSigninFirstRunInfoBar::~AutoSigninFirstRunInfoBar() {} + +base::android::ScopedJavaLocalRef<jobject> +AutoSigninFirstRunInfoBar::CreateRenderInfoBar(JNIEnv* env) { + using base::android::ConvertUTF16ToJavaString; + using base::android::ScopedJavaLocalRef; + AutoSigninFirstRunInfoBarDelegate* auto_signin_infobar_delegate = + static_cast<AutoSigninFirstRunInfoBarDelegate*>(delegate()); + ScopedJavaLocalRef<jstring> ok_button_text = ConvertUTF16ToJavaString( + env, GetTextFor(ConfirmInfoBarDelegate::BUTTON_OK)); + ScopedJavaLocalRef<jstring> cancel_button_text = ConvertUTF16ToJavaString( + env, GetTextFor(ConfirmInfoBarDelegate::BUTTON_CANCEL)); + ScopedJavaLocalRef<jstring> explanation_text = ConvertUTF16ToJavaString( + env, auto_signin_infobar_delegate->GetExplanation()); + ScopedJavaLocalRef<jstring> message_text = ConvertUTF16ToJavaString( + env, auto_signin_infobar_delegate->GetMessageText()); + + return Java_AutoSigninFirstRunInfoBar_show( + env, message_text.obj(), ok_button_text.obj(), explanation_text.obj(), + auto_signin_infobar_delegate->message_link_range().start(), + auto_signin_infobar_delegate->message_link_range().end()); +} + +void AutoSigninFirstRunInfoBar::OnLinkClicked(JNIEnv* env, jobject obj) { + GetDelegate()->LinkClicked(NEW_FOREGROUND_TAB); +} + +bool AutoSigninFirstRunInfoBar::Register(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +scoped_ptr<infobars::InfoBar> CreateAutoSigninFirstRunInfoBar( + scoped_ptr<AutoSigninFirstRunInfoBarDelegate> delegate) { + return make_scoped_ptr(new AutoSigninFirstRunInfoBar(delegate.Pass())); +}
diff --git a/chrome/browser/ui/android/infobars/auto_signin_first_run_infobar.h b/chrome/browser/ui/android/infobars/auto_signin_first_run_infobar.h new file mode 100644 index 0000000..edddece0 --- /dev/null +++ b/chrome/browser/ui/android/infobars/auto_signin_first_run_infobar.h
@@ -0,0 +1,32 @@ +// Copyright 2015 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_ANDROID_INFOBARS_AUTO_SIGNIN_FIRST_RUN_INFOBAR_H_ +#define CHROME_BROWSER_UI_ANDROID_INFOBARS_AUTO_SIGNIN_FIRST_RUN_INFOBAR_H_ + +#include "base/macros.h" +#include "chrome/browser/password_manager/auto_signin_first_run_infobar_delegate.h" +#include "chrome/browser/ui/android/infobars/confirm_infobar.h" + +// The Android infobar that offers the user the ability to save a password +// for the site. +class AutoSigninFirstRunInfoBar : public ConfirmInfoBar { + public: + explicit AutoSigninFirstRunInfoBar( + scoped_ptr<AutoSigninFirstRunInfoBarDelegate> delegate); + + ~AutoSigninFirstRunInfoBar() override; + + static bool Register(JNIEnv* env); + + private: + // ConfirmInfoBar: + base::android::ScopedJavaLocalRef<jobject> CreateRenderInfoBar( + JNIEnv* env) override; + void OnLinkClicked(JNIEnv* env, jobject obj) override; + + DISALLOW_COPY_AND_ASSIGN(AutoSigninFirstRunInfoBar); +}; + +#endif // CHROME_BROWSER_UI_ANDROID_INFOBARS_AUTO_SIGNIN_FIRST_RUN_INFOBAR_H_
diff --git a/chrome/browser/ui/android/snackbars/auto_signin_prompt_controller.cc b/chrome/browser/ui/android/snackbars/auto_signin_prompt_controller.cc new file mode 100644 index 0000000..2edc8a5 --- /dev/null +++ b/chrome/browser/ui/android/snackbars/auto_signin_prompt_controller.cc
@@ -0,0 +1,40 @@ +// Copyright 2015 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/android/snackbars/auto_signin_prompt_controller.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" +#include "chrome/browser/android/tab_android.h" +#include "chrome/browser/password_manager/auto_signin_first_run_infobar_delegate.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/grit/generated_resources.h" +#include "components/password_manager/core/browser/password_bubble_experiment.h" +#include "content/public/browser/web_contents.h" +#include "jni/AutoSigninSnackbarController_jni.h" +#include "ui/base/l10n/l10n_util.h" + +void ShowAutoSigninPrompt(content::WebContents* web_contents, + const base::string16& username) { + Profile* profile = + Profile::FromBrowserContext(web_contents->GetBrowserContext()); + base::string16 message = l10n_util::GetStringFUTF16( + IDS_MANAGE_PASSWORDS_AUTO_SIGNIN_TITLE, username); + + if (password_bubble_experiment::ShouldShowAutoSignInPromptFirstRunExperience( + profile->GetPrefs())) { + AutoSigninFirstRunInfoBarDelegate::Create(web_contents, message); + } else { + JNIEnv* env = base::android::AttachCurrentThread(); + TabAndroid* tab = TabAndroid::FromWebContents(web_contents); + ScopedJavaLocalRef<jstring> java_message = + base::android::ConvertUTF16ToJavaString(env, message); + Java_AutoSigninSnackbarController_showSnackbar( + env, tab->GetJavaObject().obj(), java_message.obj()); + } +} + +bool RegisterAutoSigninSnackbarController(JNIEnv* env) { + return RegisterNativesImpl(env); +}
diff --git a/chrome/browser/ui/android/snackbars/auto_signin_prompt_controller.h b/chrome/browser/ui/android/snackbars/auto_signin_prompt_controller.h new file mode 100644 index 0000000..f59a7434 --- /dev/null +++ b/chrome/browser/ui/android/snackbars/auto_signin_prompt_controller.h
@@ -0,0 +1,26 @@ +// Copyright 2015 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_ANDROID_SNACKBARS_AUTO_SIGNIN_PROMPT_CONTROLLER_H_ +#define CHROME_BROWSER_UI_ANDROID_SNACKBARS_AUTO_SIGNIN_PROMPT_CONTROLLER_H_ + +#include <jni.h> + +#include "base/strings/string16.h" + +namespace content { +class WebContents; +} + +// Shows an auto sign-in prompt in order to inform the users that they were +// automatically signed in to the website. |username| is the username used by +// the user in order to login to the web site, it can be email, telephone number +// or any string. +void ShowAutoSigninPrompt(content::WebContents* web_contents, + const base::string16& username); + +// Register native method. +bool RegisterAutoSigninSnackbarController(JNIEnv* env); + +#endif // CHROME_BROWSER_UI_ANDROID_SNACKBARS_AUTO_SIGNIN_PROMPT_CONTROLLER_H_
diff --git a/chrome/browser/ui/android/snackbars/auto_signin_snackbar_controller.cc b/chrome/browser/ui/android/snackbars/auto_signin_snackbar_controller.cc deleted file mode 100644 index ff5e160..0000000 --- a/chrome/browser/ui/android/snackbars/auto_signin_snackbar_controller.cc +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2015 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/android/snackbars/auto_signin_snackbar_controller.h" - -#include "base/android/jni_android.h" -#include "base/android/jni_string.h" -#include "chrome/browser/android/tab_android.h" -#include "chrome/grit/generated_resources.h" -#include "jni/AutoSigninSnackbarController_jni.h" -#include "ui/base/l10n/l10n_util.h" - -void ShowAutoSigninSnackbar(TabAndroid *tab, const base::string16& username) { - JNIEnv *env = base::android::AttachCurrentThread(); - ScopedJavaLocalRef<jstring> message = base::android::ConvertUTF16ToJavaString( - env, l10n_util::GetStringFUTF16(IDS_MANAGE_PASSWORDS_AUTO_SIGNIN_TITLE, - username)); - Java_AutoSigninSnackbarController_showSnackbar( - env, tab->GetJavaObject().obj(), message.obj()); -} - -bool RegisterAutoSigninSnackbarController(JNIEnv *env) { - return RegisterNativesImpl(env); -}
diff --git a/chrome/browser/ui/android/snackbars/auto_signin_snackbar_controller.h b/chrome/browser/ui/android/snackbars/auto_signin_snackbar_controller.h deleted file mode 100644 index 1e97ac1..0000000 --- a/chrome/browser/ui/android/snackbars/auto_signin_snackbar_controller.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2015 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_ANDROID_SNACKBARS_AUTO_SIGNIN_SNACKBAR_CONTROLLER_H_ -#define CHROME_BROWSER_UI_ANDROID_SNACKBARS_AUTO_SIGNIN_SNACKBAR_CONTROLLER_H_ - -#include <jni.h> - -#include "base/strings/string16.h" - -class TabAndroid; - -// Shows an auto sign-in snackbar in order to inform the users that they were -// automatically signed in to the website. |username| is the username used by -// the user in order to login to the web site, it can be email, telephone number -// or any string. -void ShowAutoSigninSnackbar(TabAndroid *tab, const base::string16& username); - -// Register native method. -bool RegisterAutoSigninSnackbarController(JNIEnv* env); - -#endif // CHROME_BROWSER_UI_ANDROID_SNACKBARS_AUTO_SIGNIN_SNACKBAR_CONTROLLER_H_
diff --git a/chrome/browser/ui/android/tab_model/tab_model.cc b/chrome/browser/ui/android/tab_model/tab_model.cc index 1c07f77..aab2a95 100644 --- a/chrome/browser/ui/android/tab_model/tab_model.cc +++ b/chrome/browser/ui/android/tab_model/tab_model.cc
@@ -9,6 +9,8 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/glue/synced_window_delegate_android.h" +#include "chrome/browser/sync/profile_sync_service.h" +#include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/ui/toolbar/toolbar_model_impl.h" #include "content/public/browser/notification_service.h" @@ -71,10 +73,10 @@ void TabModel::BroadcastSessionRestoreComplete() { if (profile_) { - NotificationService::current()->Notify( - chrome::NOTIFICATION_SESSION_RESTORE_COMPLETE, - content::Source<Profile>(profile_), - NotificationService::NoDetails()); + ProfileSyncService* sync_service = + ProfileSyncServiceFactory::GetForProfile(profile_); + if (sync_service) + sync_service->OnSessionRestoreComplete(); } else { // TODO(nyquist): Uncomment this once downstream Android uses new // constructor that takes a Profile* argument. See crbug.com/159704.
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc index 16e4113c..85837176 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc +++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
@@ -23,6 +23,7 @@ #include "chrome/browser/chromeos/login/session/user_session_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos.h" #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" #include "chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.h" @@ -30,6 +31,8 @@ #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_window.h" +#include "components/keyed_service/content/browser_context_keyed_service_shutdown_notifier_factory.h" +#include "components/keyed_service/core/keyed_service_shutdown_notifier.h" #include "content/public/browser/notification_service.h" #include "extensions/browser/app_window/app_window.h" #include "extensions/browser/app_window/app_window_registry.h" @@ -143,6 +146,29 @@ ash::MultiProfileUMA::RecordTeleportWindowType(window_type); } +// This is used to monitor profile destruction. +class MultiUserWindowManagerCrOSShutdownNotifierFactory + : public BrowserContextKeyedServiceShutdownNotifierFactory { + public: + static MultiUserWindowManagerCrOSShutdownNotifierFactory* GetInstance() { + return base::Singleton< + MultiUserWindowManagerCrOSShutdownNotifierFactory>::get(); + } + + private: + friend struct base::DefaultSingletonTraits< + MultiUserWindowManagerCrOSShutdownNotifierFactory>; + + MultiUserWindowManagerCrOSShutdownNotifierFactory() + : BrowserContextKeyedServiceShutdownNotifierFactory( + "MultiUserWindowManagerChromeOS") { + DependsOn(SigninManagerFactory::GetInstance()); + } + ~MultiUserWindowManagerCrOSShutdownNotifierFactory() override {} + + DISALLOW_COPY_AND_ASSIGN(MultiUserWindowManagerCrOSShutdownNotifierFactory); +}; + } // namespace namespace chrome { @@ -191,7 +217,11 @@ // window observer will take care of that. class AppObserver : public extensions::AppWindowRegistry::Observer { public: - explicit AppObserver(const std::string& user_id) : user_id_(user_id) {} + explicit AppObserver( + const std::string& user_id, + KeyedServiceShutdownNotifier::Subscription* shutdown_notification) + : user_id_(user_id), + profile_shutdown_notification_(shutdown_notification) {} ~AppObserver() override {} // AppWindowRegistry::Observer overrides: @@ -205,6 +235,12 @@ private: std::string user_id_; + // This notification is triggered when the profile gets destroyed (during + // shutdown process). + // The callback (stored in notification) destroyes AppObserver object. + scoped_ptr<KeyedServiceShutdownNotifier::Subscription> + profile_shutdown_notification_; + DISALLOW_COPY_AND_ASSIGN(AppObserver); }; @@ -238,10 +274,7 @@ Profile* profile = multi_user_util::GetProfileFromUserID( app_observer_iterator->first); CHECK(profile) << "profile not found for:" << app_observer_iterator->first; - extensions::AppWindowRegistry::Get(profile) - ->RemoveObserver(app_observer_iterator->second); - delete app_observer_iterator->second; - user_id_to_app_observer_.erase(app_observer_iterator); + RemoveUser(app_observer_iterator->first, profile); app_observer_iterator = user_id_to_app_observer_.begin(); } @@ -373,7 +406,15 @@ if (user_id_to_app_observer_.find(user_id) != user_id_to_app_observer_.end()) return; - user_id_to_app_observer_[user_id] = new AppObserver(user_id); + scoped_ptr<KeyedServiceShutdownNotifier::Subscription> notification = + MultiUserWindowManagerCrOSShutdownNotifierFactory::GetInstance() + ->Get(profile) + ->Subscribe(base::Bind(&MultiUserWindowManagerChromeOS::RemoveUser, + base::Unretained(this), user_id, + base::Unretained(profile))); + + user_id_to_app_observer_[user_id] = + new AppObserver(user_id, notification.release()); extensions::AppWindowRegistry::Get(profile) ->AddObserver(user_id_to_app_observer_[user_id]); @@ -746,4 +787,20 @@ (animation_speed_ == ANIMATION_SPEED_FAST ? 10 : 0); } +void MultiUserWindowManagerChromeOS::RemoveUser(const std::string& user_id, + Profile* profile) { + UserIDToAppWindowObserver::iterator app_observer_iterator = + user_id_to_app_observer_.find(user_id); + DCHECK(app_observer_iterator != user_id_to_app_observer_.end()) + << "User id '" << user_id << "', profile=" << profile + << " was not found."; + if (app_observer_iterator == user_id_to_app_observer_.end()) + return; + + extensions::AppWindowRegistry::Get(profile) + ->RemoveObserver(app_observer_iterator->second); + delete app_observer_iterator->second; + user_id_to_app_observer_.erase(app_observer_iterator); +} + } // namespace chrome
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h index 3507d5e..90788f7 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h +++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h
@@ -21,6 +21,7 @@ class Browser; class MultiUserNotificationBlockerChromeOS; class MultiUserNotificationBlockerChromeOSTest; +class Profile; namespace content { class BrowserContext; @@ -226,6 +227,12 @@ // from the passed |default_time_in_ms|. int GetAdjustedAnimationTimeInMS(int default_time_in_ms) const; + // This is called when KeyedService (for |iser_id| and |profile|) is + // destroyed, or when MultiUserWindowManagerChromeOS is destroyed. + // This happens on shutdown, before profile prefs are stored to + // disk. + void RemoveUser(const std::string& user_id, Profile* profile); + // A lookup to see to which user the given window belongs to, where and if it // should get shown. WindowToEntryMap window_to_entry_;
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller.h b/chrome/browser/ui/autofill/save_card_bubble_controller.h index 4f09a8a..75ae33b 100644 --- a/chrome/browser/ui/autofill/save_card_bubble_controller.h +++ b/chrome/browser/ui/autofill/save_card_bubble_controller.h
@@ -16,6 +16,7 @@ public: virtual void OnSaveButton() = 0; virtual void OnCancelButton() = 0; + virtual void OnLearnMoreClicked() = 0; virtual void OnBubbleClosed() = 0; protected:
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc index 52ede1f..2e43699e 100644 --- a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc +++ b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc
@@ -9,6 +9,7 @@ #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/location_bar/location_bar.h" +#include "components/autofill/core/common/autofill_constants.h" #include "content/public/browser/navigation_details.h" DEFINE_WEB_CONTENTS_USER_DATA_KEY(autofill::SaveCardBubbleControllerImpl); @@ -82,6 +83,12 @@ save_card_callback_.Reset(); } +void SaveCardBubbleControllerImpl::OnLearnMoreClicked() { + web_contents()->OpenURL(content::OpenURLParams( + GURL(kHelpURL), content::Referrer(), NEW_FOREGROUND_TAB, + ui::PAGE_TRANSITION_LINK, false)); +} + void SaveCardBubbleControllerImpl::OnBubbleClosed() { save_card_bubble_view_ = nullptr; UpdateIcon();
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.h b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.h index 4df4b407..921b0a6 100644 --- a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.h +++ b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.h
@@ -43,6 +43,7 @@ // SaveCardBubbleController: void OnSaveButton() override; void OnCancelButton() override; + void OnLearnMoreClicked() override; void OnBubbleClosed() override; private:
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 4f6a754..d6a2493 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -164,7 +164,7 @@ #include "components/search/search.h" #include "components/sessions/core/session_types.h" #include "components/sessions/core/tab_restore_service.h" -#include "components/startup_metric_utils/startup_metric_utils.h" +#include "components/startup_metric_utils/browser/startup_metric_utils.h" #include "components/translate/core/browser/language_state.h" #include "components/ui/zoom/zoom_controller.h" #include "components/web_modal/web_contents_modal_dialog_manager.h"
diff --git a/chrome/browser/ui/cocoa/simple_message_box_mac.mm b/chrome/browser/ui/cocoa/simple_message_box_mac.mm index 508b84f..4193a64 100644 --- a/chrome/browser/ui/cocoa/simple_message_box_mac.mm +++ b/chrome/browser/ui/cocoa/simple_message_box_mac.mm
@@ -9,7 +9,7 @@ #include "base/strings/sys_string_conversions.h" #include "chrome/browser/ui/simple_message_box_internal.h" #include "chrome/grit/generated_resources.h" -#include "components/startup_metric_utils/startup_metric_utils.h" +#include "components/startup_metric_utils/browser/startup_metric_utils.h" #include "ui/base/l10n/l10n_util_mac.h" namespace chrome {
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm index 9a976e5a..0cd9275d 100644 --- a/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm
@@ -98,7 +98,14 @@ } void TearDown() override { - bar_.reset(); // browser() must outlive the ToolbarController. + // Releasing ToolbarController doesn't actually free it at this point, since + // the NSViewController retains a reference to it from the nib loading. + // As browser() is released in the superclass TearDown, call + // -[ToolbarController browserWillBeDestroyed] to prevent a use after free + // issue on the |browser_| pointer in LocationBarViewMac when + // ToolbarController is actually freed (some time after this method is run). + [bar_ browserWillBeDestroyed]; + bar_.reset(); CocoaProfileTest::TearDown(); } @@ -346,6 +353,7 @@ TEST_F(ToolbarControllerTest, HoverButtonForEvent) { base::scoped_nsobject<HitView> view( [[HitView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)]); + NSView* toolbarView = [bar_ view]; [bar_ setView:view]; NSEvent* event = [NSEvent mouseEventWithType:NSMouseMoved location:NSMakePoint(10,10) @@ -371,6 +379,10 @@ [[ImageButtonCell alloc] init]); [button setCell:cell.get()]; EXPECT_TRUE([bar_ hoverButtonForEvent:nil]); + + // Restore the original view so that + // -[ToolbarController browserWillBeDestroyed] will run correctly. + [bar_ setView:toolbarView]; } class BrowserRemovedObserver : public chrome::BrowserListObserver { @@ -386,18 +398,4 @@ DISALLOW_COPY_AND_ASSIGN(BrowserRemovedObserver); }; -// Test that ToolbarController can be destroyed after the Browser. -// This can happen because the ToolbarController is retained by both the -// BrowserWindowController and -[ToolbarController view], the latter of which is -// autoreleased. -TEST_F(ToolbarControllerTest, ToolbarDestroyedAfterBrowser) { - BrowserRemovedObserver observer; - // This is normally called by BrowserWindowController, but since |bar_| is not - // owned by one, call it here. - [bar_ browserWillBeDestroyed]; - CloseBrowserWindow(); - observer.WaitUntilBrowserRemoved(); - // |bar_| is released in TearDown(). -} - } // namespace
diff --git a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller_unittest.mm b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller_unittest.mm index aa9fdfc..58bdd6e2 100644 --- a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller_unittest.mm
@@ -10,7 +10,6 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/profile_sync_service_factory.h" -#include "chrome/browser/sync/sessions/sessions_sync_manager.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_list_observer.h" #include "chrome/browser/ui/cocoa/cocoa_profile_test.h" @@ -27,6 +26,9 @@ #include "chrome/test/base/testing_profile.h" #include "components/sync_driver/local_device_info_provider_mock.h" #include "components/sync_driver/sync_client.h" +#include "components/sync_driver/sync_prefs.h" +#include "components/sync_sessions/fake_sync_sessions_client.h" +#include "components/sync_sessions/sessions_sync_manager.h" #include "grit/theme_resources.h" #include "sync/api/fake_sync_change_processor.h" #include "sync/api/sync_error_factory_mock.h" @@ -74,12 +76,14 @@ controller_.reset([[WrenchMenuController alloc] initWithBrowser:browser()]); fake_model_.reset(new MockAppMenuModel); + sync_prefs_.reset(new sync_driver::SyncPrefs(profile()->GetPrefs())); manager_.reset(new browser_sync::SessionsSyncManager( ProfileSyncServiceFactory::GetForProfile(profile()) ->GetSyncClient() ->GetSyncSessionsClient(), - profile(), local_device_.get(), - scoped_ptr<browser_sync::LocalSessionEventRouter>(new DummyRouter()))); + sync_prefs_.get(), local_device_.get(), + scoped_ptr<browser_sync::LocalSessionEventRouter>(new DummyRouter()), + base::Closure(), base::Closure())); manager_->MergeDataAndStartSyncing( syncer::SESSIONS, syncer::SyncDataList(), @@ -113,6 +117,7 @@ scoped_ptr<MockAppMenuModel> fake_model_; private: + scoped_ptr<sync_driver::SyncPrefs> sync_prefs_; scoped_ptr<browser_sync::SessionsSyncManager> manager_; scoped_ptr<sync_driver::LocalDeviceInfoProviderMock> local_device_; };
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc index f5346b0..44af20e 100644 --- a/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc +++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/metrics/field_trial.h" #include "base/metrics/histogram_samples.h" #include "base/prefs/pref_service.h" #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/ui/passwords/manage_passwords_view_utils.cc b/chrome/browser/ui/passwords/manage_passwords_view_utils.cc index 833e5b2e..ce016fa 100644 --- a/chrome/browser/ui/passwords/manage_passwords_view_utils.cc +++ b/chrome/browser/ui/passwords/manage_passwords_view_utils.cc
@@ -119,3 +119,24 @@ l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_ACCOUNT_CHOOSER_TITLE); } } + +void GetAutoSigninPromptFirstRunExperienceExplanation( + bool is_smartlock_branding_enabled, + base::string16* explanation, + gfx::Range* explanation_link_range) { + *explanation_link_range = gfx::Range(); + if (is_smartlock_branding_enabled) { + size_t offset; + base::string16 explanation_link = + l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SMART_LOCK); + *explanation = l10n_util::GetStringFUTF16( + IDS_MANAGE_PASSWORDS_AUTO_SIGNIN_SMART_LOCK_WELCOME, explanation_link, + &offset); + *explanation_link_range = + gfx::Range(offset, offset + explanation_link.length()); + } else { + *explanation = l10n_util::GetStringFUTF16( + IDS_MANAGE_PASSWORDS_AUTO_SIGNIN_DEFAULT_WELCOME, + l10n_util::GetStringUTF16(IDS_SAVE_PASSWORD_TITLE_BRAND)); + } +}
diff --git a/chrome/browser/ui/passwords/manage_passwords_view_utils.h b/chrome/browser/ui/passwords/manage_passwords_view_utils.h index f52f980e..21b6af4 100644 --- a/chrome/browser/ui/passwords/manage_passwords_view_utils.h +++ b/chrome/browser/ui/passwords/manage_passwords_view_utils.h
@@ -60,4 +60,14 @@ base::string16* title, gfx::Range* title_link_range); +// Sets the formatted |explanation| in the Auto sign-in prompt. +// If |is_smartlock_branding_enabled| is true, sets the +// |explanation_link_range| for the "Google Smart Lock" text range to be set +// visibly as a hyperlink in the prompt, otherwise chooses the title which +// doesn't contain Smart Lock branding. +void GetAutoSigninPromptFirstRunExperienceExplanation( + bool is_smartlock_branding_enabled, + base::string16* explanation, + gfx::Range* explanation_link_range); + #endif // CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_VIEW_UTILS_H_
diff --git a/chrome/browser/ui/startup/bad_flags_prompt.cc b/chrome/browser/ui/startup/bad_flags_prompt.cc index 88b827a..553b5db8 100644 --- a/chrome/browser/ui/startup/bad_flags_prompt.cc +++ b/chrome/browser/ui/startup/bad_flags_prompt.cc
@@ -20,7 +20,7 @@ #include "components/infobars/core/simple_alert_infobar_delegate.h" #include "components/invalidation/impl/invalidation_switches.h" #include "components/nacl/common/nacl_switches.h" -#include "components/startup_metric_utils/startup_metric_utils.h" +#include "components/startup_metric_utils/browser/startup_metric_utils.h" #include "components/translate/core/common/translate_switches.h" #include "content/public/common/content_switches.h" #include "extensions/common/switches.h"
diff --git a/chrome/browser/ui/startup/default_browser_prompt_win.cc b/chrome/browser/ui/startup/default_browser_prompt_win.cc index d2d01ce1..8ba18a2 100644 --- a/chrome/browser/ui/startup/default_browser_prompt_win.cc +++ b/chrome/browser/ui/startup/default_browser_prompt_win.cc
@@ -11,7 +11,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/webui/set_as_default_browser_ui.h" -#include "components/startup_metric_utils/startup_metric_utils.h" +#include "components/startup_metric_utils/browser/startup_metric_utils.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h"
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index 119518b..f61cc10 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc
@@ -239,7 +239,9 @@ #endif // defined(ENABLE_PRINTING) && !defined(OS_ANDROID) if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableDomDistiller)) { + switches::kEnableDomDistiller) || + !base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisablePrintPreviewSimplify)) { dom_distiller::WebContentsMainFrameObserver::CreateForWebContents( web_contents); }
diff --git a/chrome/browser/ui/toolbar/recent_tabs_builder_test_helper.cc b/chrome/browser/ui/toolbar/recent_tabs_builder_test_helper.cc index a9024a40..03f35db0 100644 --- a/chrome/browser/ui/toolbar/recent_tabs_builder_test_helper.cc +++ b/chrome/browser/ui/toolbar/recent_tabs_builder_test_helper.cc
@@ -8,8 +8,8 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "chrome/browser/sync/sessions/sessions_sync_manager.h" #include "components/sync_driver/open_tabs_ui_delegate.h" +#include "components/sync_sessions/sessions_sync_manager.h" #include "sync/api/attachments/attachment_id.h" #include "sync/internal_api/public/attachments/attachment_service_proxy_for_test.h" #include "sync/protocol/session_specifics.pb.h"
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc index c305041..1a5ba65 100644 --- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc +++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc
@@ -16,7 +16,6 @@ #include "chrome/browser/sessions/session_service_factory.h" #include "chrome/browser/sessions/tab_restore_service_factory.h" #include "chrome/browser/sync/profile_sync_service_mock.h" -#include "chrome/browser/sync/sessions/sessions_sync_manager.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/sync/browser_synced_window_delegates_getter.h" @@ -32,6 +31,8 @@ #include "components/sync_driver/glue/synced_session.h" #include "components/sync_driver/local_device_info_provider_mock.h" #include "components/sync_driver/sync_client.h" +#include "components/sync_driver/sync_prefs.h" +#include "components/sync_sessions/sessions_sync_manager.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_utils.h" #include "grit/generated_resources.h" @@ -125,10 +126,12 @@ "Chrome 10k", sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id")) { + sync_prefs_.reset(new sync_driver::SyncPrefs(testing_profile_.GetPrefs())); manager_.reset(new browser_sync::SessionsSyncManager( sync_service_.GetSyncClient()->GetSyncSessionsClient(), - &testing_profile_, local_device_.get(), - scoped_ptr<browser_sync::LocalSessionEventRouter>(new DummyRouter()))); + sync_prefs_.get(), local_device_.get(), + scoped_ptr<browser_sync::LocalSessionEventRouter>(new DummyRouter()), + base::Closure(), base::Closure())); manager_->MergeDataAndStartSyncing( syncer::SESSIONS, syncer::SyncDataList(), @@ -161,7 +164,7 @@ private: TestingProfile testing_profile_; testing::NiceMock<ProfileSyncServiceMock> sync_service_; - + scoped_ptr<sync_driver::SyncPrefs> sync_prefs_; scoped_ptr<browser_sync::SessionsSyncManager> manager_; scoped_ptr<sync_driver::LocalDeviceInfoProviderMock> local_device_; };
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc index d04a6c0..214f508e 100644 --- a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
@@ -11,6 +11,7 @@ #include "ui/views/bubble/bubble_frame_view.h" #include "ui/views/controls/button/blue_button.h" #include "ui/views/controls/button/label_button.h" +#include "ui/views/controls/link.h" #include "ui/views/layout/grid_layout.h" #include "ui/views/layout/layout_constants.h" @@ -21,6 +22,15 @@ // Fixed width of the column holding the message text. const int kWidthOfMessageText = 375; +// TODO(bondd): BubbleManager will eventually move this logic somewhere else, +// and then kIsOkButtonOnLeftSide can be removed from here and +// dialog_client_view.cc. +#if defined(OS_WIN) || defined(OS_CHROMEOS) +const bool kIsOkButtonOnLeftSide = true; +#else +const bool kIsOkButtonOnLeftSide = false; +#endif + } // namespace namespace autofill { @@ -31,7 +41,8 @@ : LocationBarBubbleDelegateView(anchor_view, web_contents), controller_(controller), save_button_(nullptr), - cancel_button_(nullptr) { + cancel_button_(nullptr), + learn_more_link_(nullptr) { DCHECK(controller); views::BubbleDelegateView::CreateBubble(this); } @@ -79,6 +90,11 @@ GetWidget()->Close(); } +void SaveCardBubbleViews::LinkClicked(views::Link* source, int event_flags) { + DCHECK_EQ(source, learn_more_link_); + controller_->OnLearnMoreClicked(); +} + void SaveCardBubbleViews::Init() { enum { COLUMN_SET_ID_MESSAGE, @@ -97,8 +113,11 @@ cs->AddPaddingColumn(1, kWidthOfMessageText); cs->AddPaddingColumn(0, horizontal_inset); - // Set up ColumnSet that will contain the buttons. + // Set up ColumnSet that will contain the buttons and "learn more" link. cs = layout->AddColumnSet(COLUMN_SET_ID_BUTTONS); + cs->AddPaddingColumn(0, horizontal_inset); + cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, + GridLayout::USE_PREF, 0, 0); cs->AddPaddingColumn(1, 0); cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, GridLayout::USE_PREF, 0, 0); @@ -107,18 +126,29 @@ GridLayout::USE_PREF, 0, 0); cs->AddPaddingColumn(0, horizontal_inset); - // Create accept button and add it to layout. + // Create "learn more" link and add it to layout. + learn_more_link_ = new views::Link(l10n_util::GetStringUTF16(IDS_LEARN_MORE)); + learn_more_link_->set_listener(this); + layout->StartRow(0, COLUMN_SET_ID_BUTTONS); + layout->AddView(learn_more_link_); + + // Create accept button. save_button_ = new views::BlueButton( this, l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_CARD_BUBBLE_ACCEPT)); save_button_->SetIsDefault(true); - layout->StartRow(0, COLUMN_SET_ID_BUTTONS); - layout->AddView(save_button_); - // Create cancel button and add it to layout. + // Create cancel button. cancel_button_ = new views::LabelButton( this, l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_CARD_BUBBLE_DENY)); cancel_button_->SetStyle(views::Button::STYLE_BUTTON); - layout->AddView(cancel_button_); + + if (kIsOkButtonOnLeftSide) { + layout->AddView(save_button_); + layout->AddView(cancel_button_); + } else { + layout->AddView(cancel_button_); + layout->AddView(save_button_); + } layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); set_margins(gfx::Insets(1, 0, 1, 0));
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views.h b/chrome/browser/ui/views/autofill/save_card_bubble_views.h index f82054d0..eba7e60 100644 --- a/chrome/browser/ui/views/autofill/save_card_bubble_views.h +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views.h
@@ -9,6 +9,7 @@ #include "chrome/browser/ui/autofill/save_card_bubble_view.h" #include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h" #include "ui/views/controls/button/button.h" +#include "ui/views/controls/link_listener.h" namespace content { class WebContents; @@ -16,6 +17,7 @@ namespace views { class LabelButton; +class Link; } namespace autofill { @@ -27,7 +29,8 @@ // previously saved. class SaveCardBubbleViews : public SaveCardBubbleView, public LocationBarBubbleDelegateView, - public views::ButtonListener { + public views::ButtonListener, + public views::LinkListener { public: // Bubble will be anchored to |anchor_view|. SaveCardBubbleViews(views::View* anchor_view, @@ -48,19 +51,24 @@ // views::ButtonListener void ButtonPressed(views::Button* sender, const ui::Event& event) override; + // views::LinkListener + void LinkClicked(views::Link* source, int event_flags) override; + private: ~SaveCardBubbleViews() override; // views::BubbleDelegateView void Init() override; - SaveCardBubbleController* controller_; + SaveCardBubbleController* controller_; // Weak reference. // Button for the user to confirm saving the credit card info. views::LabelButton* save_button_; views::LabelButton* cancel_button_; + views::Link* learn_more_link_; + DISALLOW_COPY_AND_ASSIGN(SaveCardBubbleViews); };
diff --git a/chrome/browser/ui/views/bar_control_button.cc b/chrome/browser/ui/views/bar_control_button.cc new file mode 100644 index 0000000..0e4336d5 --- /dev/null +++ b/chrome/browser/ui/views/bar_control_button.cc
@@ -0,0 +1,137 @@ +// Copyright 2015 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/views/bar_control_button.h" + +#include "ui/gfx/color_utils.h" +#include "ui/gfx/paint_vector_icon.h" +#include "ui/gfx/vector_icons_public.h" +#include "ui/views/animation/ink_drop_animation_controller.h" +#include "ui/views/animation/ink_drop_animation_controller_factory.h" +#include "ui/views/border.h" + +namespace { + +// Extra space around the buttons to increase their event target size. +const int kButtonExtraTouchSize = 4; + +} // namespace + +BarControlButton::BarControlButton(views::ButtonListener* listener) + : views::ImageButton(listener), + id_(gfx::VectorIconId::VECTOR_ICON_NONE), + ink_drop_animation_controller_( + views::InkDropAnimationControllerFactory:: + CreateInkDropAnimationController(this)) { + const int kInkDropLargeSize = 32; + const int kInkDropLargeCornerRadius = 4; + const int kInkDropSmallSize = 24; + const int kInkDropSmallCornerRadius = 2; + ink_drop_animation_controller_->SetInkDropSize( + gfx::Size(kInkDropLargeSize, kInkDropLargeSize), + kInkDropLargeCornerRadius, + gfx::Size(kInkDropSmallSize, kInkDropSmallSize), + kInkDropSmallCornerRadius); +} + +BarControlButton::~BarControlButton() {} + +void BarControlButton::SetIcon( + gfx::VectorIconId id, + const base::Callback<SkColor(void)>& get_text_color_callback) { + id_ = id; + get_text_color_callback_ = get_text_color_callback; + + SetBorder(views::Border::CreateEmptyBorder( + kButtonExtraTouchSize, kButtonExtraTouchSize, kButtonExtraTouchSize, + kButtonExtraTouchSize)); + SetImageAlignment(views::ImageButton::ALIGN_CENTER, + views::ImageButton::ALIGN_MIDDLE); +} + +void BarControlButton::OnThemeChanged() { + SkColor icon_color = + color_utils::DeriveDefaultIconColor(get_text_color_callback_.Run()); + gfx::ImageSkia image = gfx::CreateVectorIcon(id_, 16, icon_color); + SetImage(views::CustomButton::STATE_NORMAL, &image); + image = gfx::CreateVectorIcon(id_, 16, SkColorSetA(icon_color, 0xff / 2)); + SetImage(views::CustomButton::STATE_DISABLED, &image); +} + +void BarControlButton::OnNativeThemeChanged(const ui::NativeTheme* theme) { + OnThemeChanged(); +} + +void BarControlButton::Layout() { + ImageButton::Layout(); + + ink_drop_animation_controller_->SetInkDropCenter( + GetLocalBounds().CenterPoint()); +} + +void BarControlButton::AddInkDropLayer(ui::Layer* ink_drop_layer) { + SetPaintToLayer(true); + SetFillsBoundsOpaquely(false); + layer()->Add(ink_drop_layer); + layer()->StackAtBottom(ink_drop_layer); +} + +void BarControlButton::RemoveInkDropLayer(ui::Layer* ink_drop_layer) { + layer()->Remove(ink_drop_layer); + SetFillsBoundsOpaquely(true); + SetPaintToLayer(false); +} + +bool BarControlButton::OnMousePressed(const ui::MouseEvent& event) { + if (IsTriggerableEvent(event)) { + ink_drop_animation_controller_->AnimateToState( + views::InkDropState::ACTION_PENDING); + } + + return ImageButton::OnMousePressed(event); +} + +void BarControlButton::OnGestureEvent(ui::GestureEvent* event) { + views::InkDropState ink_drop_state = views::InkDropState::HIDDEN; + switch (event->type()) { + case ui::ET_GESTURE_TAP_DOWN: + ink_drop_state = views::InkDropState::ACTION_PENDING; + // The ui::ET_GESTURE_TAP_DOWN event needs to be marked as handled so + // that subsequent events for the gesture are sent to |this|. + event->SetHandled(); + break; + case ui::ET_GESTURE_LONG_PRESS: + ink_drop_state = views::InkDropState::SLOW_ACTION_PENDING; + break; + case ui::ET_GESTURE_TAP: + ink_drop_state = views::InkDropState::QUICK_ACTION; + break; + case ui::ET_GESTURE_LONG_TAP: + ink_drop_state = views::InkDropState::SLOW_ACTION; + break; + case ui::ET_GESTURE_END: + case ui::ET_GESTURE_TAP_CANCEL: + ink_drop_state = views::InkDropState::HIDDEN; + break; + default: + return; + } + ink_drop_animation_controller_->AnimateToState(ink_drop_state); + + ImageButton::OnGestureEvent(event); +} + +void BarControlButton::OnMouseReleased(const ui::MouseEvent& event) { + if (!HitTestPoint(event.location())) + ink_drop_animation_controller_->AnimateToState(views::InkDropState::HIDDEN); + + ImageButton::OnMouseReleased(event); +} + +void BarControlButton::NotifyClick(const ui::Event& event) { + ink_drop_animation_controller_->AnimateToState( + views::InkDropState::QUICK_ACTION); + + ImageButton::NotifyClick(event); +}
diff --git a/chrome/browser/ui/views/bar_control_button.h b/chrome/browser/ui/views/bar_control_button.h new file mode 100644 index 0000000..7a997cc --- /dev/null +++ b/chrome/browser/ui/views/bar_control_button.h
@@ -0,0 +1,56 @@ +// Copyright 2015 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_VIEWS_BAR_CONTROL_BUTTON_H_ +#define CHROME_BROWSER_UI_VIEWS_BAR_CONTROL_BUTTON_H_ + +#include "base/callback.h" +#include "base/macros.h" +#include "ui/views/animation/ink_drop_host.h" +#include "ui/views/controls/button/image_button.h" + +namespace gfx { +enum class VectorIconId; +} + +namespace views { +class InkDropAnimationController; +} + +// A class for buttons that control bars (find bar, download shelf, etc.). The +// button has an image and no text. +class BarControlButton : public views::ImageButton, public views::InkDropHost { + public: + explicit BarControlButton(views::ButtonListener* listener); + ~BarControlButton() override; + + // Sets the icon to display and provides a callback which should return the + // text color from which to derive this icon's color. + void SetIcon(gfx::VectorIconId id, + const base::Callback<SkColor(void)>& get_text_color_callback); + + // views::ImageButton: + void OnThemeChanged() override; + void OnNativeThemeChanged(const ui::NativeTheme* theme) override; + void Layout() override; + bool OnMousePressed(const ui::MouseEvent& event) override; + void OnGestureEvent(ui::GestureEvent* event) override; + void OnMouseReleased(const ui::MouseEvent& event) override; + void NotifyClick(const ui::Event& event) override; + + private: + // views::InkDropHost: + void AddInkDropLayer(ui::Layer* ink_drop_layer) override; + void RemoveInkDropLayer(ui::Layer* ink_drop_layer) override; + + gfx::VectorIconId id_; + base::Callback<SkColor(void)> get_text_color_callback_; + + // Animation controller for the ink drop ripple effect. + scoped_ptr<views::InkDropAnimationController> ink_drop_animation_controller_; + + DISALLOW_COPY_AND_ASSIGN(BarControlButton); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_BAR_CONTROL_BUTTON_H_
diff --git a/chrome/browser/ui/views/download/download_item_view_md.cc b/chrome/browser/ui/views/download/download_item_view_md.cc index 03c8aab3..81281d90 100644 --- a/chrome/browser/ui/views/download/download_item_view_md.cc +++ b/chrome/browser/ui/views/download/download_item_view_md.cc
@@ -30,6 +30,7 @@ #include "chrome/browser/safe_browsing/download_protection_service.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/themes/theme_properties.h" +#include "chrome/browser/ui/views/bar_control_button.h" #include "chrome/browser/ui/views/download/download_feedback_dialog_view.h" #include "chrome/browser/ui/views/download/download_shelf_context_menu_view.h" #include "chrome/browser/ui/views/download/download_shelf_view.h" @@ -103,8 +104,6 @@ // Height/width of the warning icon, also in dp. const int kWarningIconSize = 24; -const SkColor kFileNameDisabledColor = SkColorSetRGB(171, 192, 212); - // How long the 'download complete' animation should last for. const int kCompleteAnimationDurationMs = 2500; @@ -180,12 +179,7 @@ OnDownloadUpdated(download()); - // TODO(estade): share this button init code with the find in page bar; - // also fix theming. - dropdown_button_ = new views::ImageButton(this); - dropdown_button_->SetBorder(views::Border::CreateEmptyBorder(4, 4, 4, 4)); - dropdown_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, - views::ImageButton::ALIGN_MIDDLE); + dropdown_button_ = new BarControlButton(this); AddChildView(dropdown_button_); SetDropdownState(NORMAL); UpdateColorsFromTheme(); @@ -222,6 +216,13 @@ progress_timer_.Stop(); } +// static +SkColor DownloadItemViewMd::GetTextColorForThemeProvider( + ui::ThemeProvider* theme) { + return theme ? theme->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT) + : SK_ColorRED; +} + void DownloadItemViewMd::OnExtractIconComplete(gfx::Image* icon_bitmap) { if (icon_bitmap) shelf_->SchedulePaint(); @@ -588,10 +589,8 @@ kTextWidth); int y = GetYForFilenameText() + font_list_.GetBaseline() + kVerticalTextPadding; - SkColor file_name_color = SkColorSetA( - GetThemeProvider()->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT), 0xC7); canvas->DrawStringRect( - status_text_, status_font_list_, file_name_color, + status_text_, status_font_list_, GetDimmedTextColor(), gfx::Rect(mirrored_x, y, kTextWidth, status_font_list_.GetHeight())); } @@ -624,11 +623,8 @@ kStartPadding + DownloadShelf::kProgressIndicatorSize + kProgressTextPadding, kTextWidth); - SkColor file_name_color = - GetThemeProvider()->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT); - canvas->DrawStringRect(filename, font_list_, - enabled() ? file_name_color : kFileNameDisabledColor, + enabled() ? GetTextColor() : GetDimmedTextColor(), gfx::Rect(mirrored_x, GetYForFilenameText(), kTextWidth, font_list_.GetHeight())); } @@ -760,10 +756,8 @@ if (!GetThemeProvider()) return; - if (dangerous_download_label_) { - dangerous_download_label_->SetEnabledColor( - GetThemeProvider()->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT)); - } + if (dangerous_download_label_) + dangerous_download_label_->SetEnabledColor(GetTextColor()); SetBorder(make_scoped_ptr(new SeparatorBorder( GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR_SEPARATOR)))); } @@ -825,12 +819,11 @@ !dropdown_button_->GetImage(views::CustomButton::STATE_NORMAL).isNull()) return; - // TODO(estade): theme this color instead of using a constant. - gfx::ImageSkia image = - gfx::CreateVectorIcon(new_state == PUSHED ? gfx::VectorIconId::FIND_NEXT - : gfx::VectorIconId::FIND_PREV, - 16, gfx::kChromeIconGrey); - dropdown_button_->SetImage(views::CustomButton::STATE_NORMAL, &image); + dropdown_button_->SetIcon( + new_state == PUSHED ? gfx::VectorIconId::FIND_NEXT + : gfx::VectorIconId::FIND_PREV, + base::Bind(&DownloadItemViewMd::GetTextColor, base::Unretained(this))); + dropdown_button_->OnThemeChanged(); dropdown_state_ = new_state; SchedulePaint(); } @@ -1077,3 +1070,11 @@ animation->Reset((to == HOT) ? 1.0 : 0.0); } } + +SkColor DownloadItemViewMd::GetTextColor() { + return GetTextColorForThemeProvider(GetThemeProvider()); +} + +SkColor DownloadItemViewMd::GetDimmedTextColor() { + return SkColorSetA(GetTextColor(), 0xC7); +}
diff --git a/chrome/browser/ui/views/download/download_item_view_md.h b/chrome/browser/ui/views/download/download_item_view_md.h index 2d69906..2d646db 100644 --- a/chrome/browser/ui/views/download/download_item_view_md.h +++ b/chrome/browser/ui/views/download/download_item_view_md.h
@@ -35,6 +35,7 @@ #include "ui/views/controls/button/button.h" #include "ui/views/view.h" +class BarControlButton; class DownloadShelfView; class DownloadShelfContextMenuView; @@ -48,6 +49,10 @@ class SlideAnimation; } +namespace ui { +class ThemeProvider; +} + namespace views { class ImageButton; class Label; @@ -71,6 +76,9 @@ void StartDownloadProgress(); void StopDownloadProgress(); + // Returns the base color for text on this download item, based on |theme|. + static SkColor GetTextColorForThemeProvider(ui::ThemeProvider* theme); + // IconManager::Client interface. void OnExtractIconComplete(gfx::Image* icon); @@ -205,6 +213,12 @@ State to, gfx::SlideAnimation* animation); + // Returns the base text color. + SkColor GetTextColor(); + + // Returns a slightly dimmed version of the base text color. + SkColor GetDimmedTextColor(); + // The download shelf that owns us. DownloadShelfView* shelf_; @@ -264,7 +278,7 @@ views::LabelButton* discard_button_; // The drop down button. - views::ImageButton* dropdown_button_; + BarControlButton* dropdown_button_; // Dangerous mode label. views::Label* dangerous_download_label_;
diff --git a/chrome/browser/ui/views/download/download_shelf_view.cc b/chrome/browser/ui/views/download/download_shelf_view.cc index 59ae5ce7..94c139f 100644 --- a/chrome/browser/ui/views/download/download_shelf_view.cc +++ b/chrome/browser/ui/views/download/download_shelf_view.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/view_ids.h" +#include "chrome/browser/ui/views/bar_control_button.h" #include "chrome/browser/ui/views/download/download_item_view.h" #include "chrome/browser/ui/views/download/download_item_view_md.h" #include "chrome/browser/ui/views/frame/browser_view.h" @@ -29,8 +30,6 @@ #include "ui/base/theme_provider.h" #include "ui/gfx/animation/slide_animation.h" #include "ui/gfx/canvas.h" -#include "ui/gfx/color_palette.h" -#include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/vector_icons_public.h" #include "ui/resources/grit/ui_resources.h" #include "ui/views/background.h" @@ -143,9 +142,6 @@ arrow_image_ = new views::ImageView(); AddChildView(arrow_image_); - close_button_ = new views::ImageButton(this); - close_button_->SetAccessibleName( - l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); if (!ui::MaterialDesignController::IsModeMaterial()) { arrow_image_->SetImage(rb.GetImageSkiaNamed(IDR_DOWNLOADS_FAVICON)); @@ -154,6 +150,7 @@ show_all_view->set_listener(this); show_all_view_ = show_all_view; + close_button_ = new views::ImageButton(this); close_button_->SetImage(views::CustomButton::STATE_NORMAL, rb.GetImageSkiaNamed(IDR_CLOSE_1)); close_button_->SetImage(views::CustomButton::STATE_HOVERED, @@ -167,15 +164,14 @@ show_all_view->SetStyle(views::Button::STYLE_BUTTON); show_all_view_ = show_all_view; - // TODO(estade): share this button init code with the find in page bar; - // also fix theming. - close_button_->SetBorder(views::Border::CreateEmptyBorder(4, 4, 4, 4)); - close_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, - views::ImageButton::ALIGN_MIDDLE); - gfx::ImageSkia image = gfx::CreateVectorIcon(gfx::VectorIconId::BAR_CLOSE, - 16, gfx::kChromeIconGrey); - close_button_->SetImage(views::CustomButton::STATE_NORMAL, &image); + BarControlButton* close_button = new BarControlButton(this); + close_button->SetIcon(gfx::VectorIconId::BAR_CLOSE, + base::Bind(&DownloadShelfView::GetTextColorForIconMd, + base::Unretained(this))); + close_button_ = close_button; } + close_button_->SetAccessibleName( + l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); AddChildView(show_all_view_); AddChildView(close_button_); @@ -397,15 +393,13 @@ show_all_view->SetBackgroundColor(background()->get_color()); show_all_view->SetEnabledColor( GetThemeProvider()->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT)); - } - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - set_background(views::Background::CreateSolidBackground( - GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR))); - close_button_->SetBackground( - GetThemeProvider()->GetColor(ThemeProperties::COLOR_TAB_TEXT), - rb.GetImageSkiaNamed(IDR_CLOSE_1), - rb.GetImageSkiaNamed(IDR_CLOSE_1_MASK)); + ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); + close_button_->SetBackground( + GetThemeProvider()->GetColor(ThemeProperties::COLOR_TAB_TEXT), + rb.GetImageSkiaNamed(IDR_CLOSE_1), + rb.GetImageSkiaNamed(IDR_CLOSE_1_MASK)); + } } } @@ -494,3 +488,7 @@ return static_cast<DownloadItemViewMd*>(download_views_[i])->download(); return static_cast<DownloadItemView*>(download_views_[i])->download(); } + +SkColor DownloadShelfView::GetTextColorForIconMd() { + return DownloadItemViewMd::GetTextColorForThemeProvider(GetThemeProvider()); +}
diff --git a/chrome/browser/ui/views/download/download_shelf_view.h b/chrome/browser/ui/views/download/download_shelf_view.h index 083f76a..0be189c 100644 --- a/chrome/browser/ui/views/download/download_shelf_view.h +++ b/chrome/browser/ui/views/download/download_shelf_view.h
@@ -124,6 +124,9 @@ // shouldn't be necessary after we only have one type of DownloadItemView. content::DownloadItem* GetDownloadItemForView(size_t i); + // Returns the color of text for the shelf (used for deriving icon color). + SkColor GetTextColorForIconMd(); + // The browser for this shelf. Browser* browser_;
diff --git a/chrome/browser/ui/views/find_bar_view.cc b/chrome/browser/ui/views/find_bar_view.cc index 2ae8912..1fd5b592 100644 --- a/chrome/browser/ui/views/find_bar_view.cc +++ b/chrome/browser/ui/views/find_bar_view.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/ui/find_bar/find_notification_details.h" #include "chrome/browser/ui/find_bar/find_tab_helper.h" #include "chrome/browser/ui/view_ids.h" +#include "chrome/browser/ui/views/bar_control_button.h" #include "chrome/browser/ui/views/find_bar_host.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/grit/generated_resources.h" @@ -36,9 +37,6 @@ #include "ui/native_theme/common_theme.h" #include "ui/native_theme/native_theme.h" #include "ui/resources/grit/ui_resources.h" -#include "ui/views/animation/ink_drop_animation_controller.h" -#include "ui/views/animation/ink_drop_animation_controller_factory.h" -#include "ui/views/animation/ink_drop_host.h" #include "ui/views/background.h" #include "ui/views/border.h" #include "ui/views/bubble/bubble_border.h" @@ -68,8 +66,6 @@ // Additional spacing around the separator. const int kSeparatorLeftSpacing = 12 - kInterChildSpacing; const int kSeparatorRightSpacing = 8 - kInterChildSpacing; -// Extra space around the buttons to increase their event target size. -const int kButtonExtraTouchSize = 4; // The margins around the match count label (We add extra space so that the // background highlight extends beyond just the text). @@ -90,36 +86,10 @@ // The background color of the match count label when no results are found. const SkColor kBackgroundColorNoMatch = SkColorSetRGB(255, 102, 102); -// The color of the match count label for Material Design. -const SkColor kMatchTextColorMD = SkColorSetRGB(0x96, 0x96, 0x96); - -// Color of the vertical separator between match count and buttons. (MD only.) -const SkColor kSeparatorColor = SkColorSetARGB(0x26, 0, 0, 0); - // The default number of average characters that the text box will be. This // number brings the width on a "regular fonts" system to about 300px. const int kDefaultCharWidth = 43; -class FindBarButton : public views::ImageButton, public views::InkDropHost { - public: - explicit FindBarButton(views::ButtonListener* listener); - ~FindBarButton() override; - - private: - void Layout() override; - void AddInkDropLayer(ui::Layer* ink_drop_layer) override; - void RemoveInkDropLayer(ui::Layer* ink_drop_layer) override; - bool OnMousePressed(const ui::MouseEvent& event) override; - void OnGestureEvent(ui::GestureEvent* event) override; - void OnMouseReleased(const ui::MouseEvent& event) override; - void NotifyClick(const ui::Event& event) override; - - // Animation controller for the ink drop ripple effect. - scoped_ptr<views::InkDropAnimationController> ink_drop_animation_controller_; - - DISALLOW_COPY_AND_ASSIGN(FindBarButton); -}; - // The match count label is like a normal label, but can process events (which // makes it easier to forward events to the text input --- see // FindBarView::TargetForRect). @@ -138,114 +108,17 @@ } // namespace //////////////////////////////////////////////////////////////////////////////// -// FindBarButton, public: - -FindBarButton::FindBarButton(views::ButtonListener* listener) - : views::ImageButton(listener), - ink_drop_animation_controller_( - views::InkDropAnimationControllerFactory:: - CreateInkDropAnimationController(this)) { - const int kInkDropLargeSize = 32; - const int kInkDropLargeCornerRadius = 4; - const int kInkDropSmallSize = 24; - const int kInkDropSmallCornerRadius = 2; - - ink_drop_animation_controller_->SetInkDropSize( - gfx::Size(kInkDropLargeSize, kInkDropLargeSize), - kInkDropLargeCornerRadius, - gfx::Size(kInkDropSmallSize, kInkDropSmallSize), - kInkDropSmallCornerRadius); -} - -FindBarButton::~FindBarButton() {} - -//////////////////////////////////////////////////////////////////////////////// -// FindBarButton, private: - -void FindBarButton::Layout() { - ImageButton::Layout(); - - ink_drop_animation_controller_->SetInkDropCenter( - GetLocalBounds().CenterPoint()); -} - -void FindBarButton::AddInkDropLayer(ui::Layer* ink_drop_layer) { - SetPaintToLayer(true); - SetFillsBoundsOpaquely(false); - layer()->Add(ink_drop_layer); - layer()->StackAtBottom(ink_drop_layer); -} - -void FindBarButton::RemoveInkDropLayer(ui::Layer* ink_drop_layer) { - layer()->Remove(ink_drop_layer); - SetFillsBoundsOpaquely(true); - SetPaintToLayer(false); -} - -bool FindBarButton::OnMousePressed(const ui::MouseEvent& event) { - if (IsTriggerableEvent(event)) { - ink_drop_animation_controller_->AnimateToState( - views::InkDropState::ACTION_PENDING); - } - - return ImageButton::OnMousePressed(event); -} - -void FindBarButton::OnGestureEvent(ui::GestureEvent* event) { - views::InkDropState ink_drop_state = views::InkDropState::HIDDEN; - switch (event->type()) { - case ui::ET_GESTURE_TAP_DOWN: - ink_drop_state = views::InkDropState::ACTION_PENDING; - // The ui::ET_GESTURE_TAP_DOWN event needs to be marked as handled so - // that subsequent events for the gesture are sent to |this|. - event->SetHandled(); - break; - case ui::ET_GESTURE_LONG_PRESS: - ink_drop_state = views::InkDropState::SLOW_ACTION_PENDING; - break; - case ui::ET_GESTURE_TAP: - ink_drop_state = views::InkDropState::QUICK_ACTION; - break; - case ui::ET_GESTURE_LONG_TAP: - ink_drop_state = views::InkDropState::SLOW_ACTION; - break; - case ui::ET_GESTURE_END: - case ui::ET_GESTURE_TAP_CANCEL: - ink_drop_state = views::InkDropState::HIDDEN; - break; - default: - return; - } - ink_drop_animation_controller_->AnimateToState(ink_drop_state); - - ImageButton::OnGestureEvent(event); -} - -void FindBarButton::OnMouseReleased(const ui::MouseEvent& event) { - if (!HitTestPoint(event.location())) - ink_drop_animation_controller_->AnimateToState(views::InkDropState::HIDDEN); - - ImageButton::OnMouseReleased(event); -} - -void FindBarButton::NotifyClick(const ui::Event& event) { - ink_drop_animation_controller_->AnimateToState( - views::InkDropState::QUICK_ACTION); - - ImageButton::NotifyClick(event); -} - -//////////////////////////////////////////////////////////////////////////////// // FindBarView, public: FindBarView::FindBarView(FindBarHost* host) : DropdownBarView(host), - find_text_(NULL), - match_count_text_(NULL), - focus_forwarder_view_(NULL), - find_previous_button_(NULL), - find_next_button_(NULL), - close_button_(NULL) { + find_text_(nullptr), + match_count_text_(nullptr), + focus_forwarder_view_(nullptr), + separator_(nullptr), + find_previous_button_(nullptr), + find_next_button_(nullptr), + close_button_(nullptr) { find_text_ = new views::Textfield; find_text_->set_id(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD); find_text_->set_default_width_in_chars(kDefaultCharWidth); @@ -254,7 +127,29 @@ find_text_->SetTextInputFlags(ui::TEXT_INPUT_FLAG_AUTOCORRECT_OFF); AddChildView(find_text_); - find_previous_button_ = new FindBarButton(this); + if (ui::MaterialDesignController::IsModeMaterial()) { + BarControlButton* find_previous = new BarControlButton(this); + find_previous->SetIcon( + gfx::VectorIconId::FIND_PREV, + base::Bind(&FindBarView::GetTextColorForIcon, base::Unretained(this))); + BarControlButton* find_next = new BarControlButton(this); + find_next->SetIcon( + gfx::VectorIconId::FIND_NEXT, + base::Bind(&FindBarView::GetTextColorForIcon, base::Unretained(this))); + BarControlButton* close = new BarControlButton(this); + close->SetIcon( + gfx::VectorIconId::BAR_CLOSE, + base::Bind(&FindBarView::GetTextColorForIcon, base::Unretained(this))); + + find_previous_button_ = find_previous; + find_next_button_ = find_next; + close_button_ = close; + } else { + find_previous_button_ = new views::ImageButton(this); + find_next_button_ = new views::ImageButton(this); + close_button_ = new views::ImageButton(this); + } + find_previous_button_->set_tag(FIND_PREVIOUS_TAG); find_previous_button_->SetFocusable(true); find_previous_button_->set_request_focus_on_press(false); @@ -264,7 +159,6 @@ l10n_util::GetStringUTF16(IDS_ACCNAME_PREVIOUS)); AddChildView(find_previous_button_); - find_next_button_ = new FindBarButton(this); find_next_button_->set_tag(FIND_NEXT_TAG); find_next_button_->SetFocusable(true); find_next_button_->set_request_focus_on_press(false); @@ -274,7 +168,6 @@ l10n_util::GetStringUTF16(IDS_ACCNAME_NEXT)); AddChildView(find_next_button_); - close_button_ = new FindBarButton(this); close_button_->set_tag(CLOSE_TAG); close_button_->SetFocusable(true); close_button_->set_request_focus_on_press(false); @@ -655,40 +548,13 @@ make_scoped_ptr(new views::ViewTargeter(this))); AddChildViewAt(match_count_text_, 1); - views::Separator* separator = - new views::Separator(views::Separator::VERTICAL); - separator->SetColor(kSeparatorColor); - separator->SetBorder(views::Border::CreateEmptyBorder( + separator_ = new views::Separator(views::Separator::VERTICAL); + separator_->SetBorder(views::Border::CreateEmptyBorder( 0, kSeparatorLeftSpacing, 0, kSeparatorRightSpacing)); - AddChildViewAt(separator, 2); + AddChildViewAt(separator_, 2); find_text_->SetBorder(views::Border::NullBorder()); - struct { - views::ImageButton* button; - gfx::VectorIconId id; - } button_images[] = { - {find_previous_button_, gfx::VectorIconId::FIND_PREV}, - {find_next_button_, gfx::VectorIconId::FIND_NEXT}, - {close_button_, gfx::VectorIconId::BAR_CLOSE}, - }; - - for (size_t i = 0; i < arraysize(button_images); ++i) { - views::ImageButton* button = button_images[i].button; - button->SetBorder(views::Border::CreateEmptyBorder( - kButtonExtraTouchSize, kButtonExtraTouchSize, kButtonExtraTouchSize, - kButtonExtraTouchSize)); - button->SetImageAlignment(views::ImageButton::ALIGN_CENTER, - views::ImageButton::ALIGN_MIDDLE); - - gfx::ImageSkia image = - gfx::CreateVectorIcon(button_images[i].id, 16, gfx::kChromeIconGrey); - button->SetImage(views::CustomButton::STATE_NORMAL, &image); - image = gfx::CreateVectorIcon(button_images[i].id, 16, - SkColorSetA(gfx::kChromeIconGrey, 0xff / 2)); - button->SetImage(views::CustomButton::STATE_DISABLED, &image); - } - views::BoxLayout* manager = new views::BoxLayout(views::BoxLayout::kHorizontal, kInteriorPadding, kInteriorPadding, kInterChildSpacing); @@ -781,9 +647,18 @@ if (!ui::MaterialDesignController::IsModeMaterial()) return; - SkColor color = - theme->GetSystemColor(ui::NativeTheme::kColorId_DialogBackground); - set_background(views::Background::CreateSolidBackground(color)); - match_count_text_->SetBackgroundColor(color); - match_count_text_->SetEnabledColor(kMatchTextColorMD); + SkColor bg_color = theme->GetSystemColor( + ui::NativeTheme::kColorId_TextfieldDefaultBackground); + set_background(views::Background::CreateSolidBackground(bg_color)); + match_count_text_->SetBackgroundColor(bg_color); + + SkColor text_color = + theme->GetSystemColor(ui::NativeTheme::kColorId_TextfieldDefaultColor); + match_count_text_->SetEnabledColor(SkColorSetA(text_color, 0x69)); + separator_->SetColor(SkColorSetA(text_color, 0x26)); +} + +SkColor FindBarView::GetTextColorForIcon() { + return GetNativeTheme()->GetSystemColor( + ui::NativeTheme::kColorId_TextfieldDefaultColor); }
diff --git a/chrome/browser/ui/views/find_bar_view.h b/chrome/browser/ui/views/find_bar_view.h index 5fac1d19..b26c753 100644 --- a/chrome/browser/ui/views/find_bar_view.h +++ b/chrome/browser/ui/views/find_bar_view.h
@@ -22,6 +22,7 @@ class Label; class MouseEvent; class Painter; +class Separator; } //////////////////////////////////////////////////////////////////////////////// @@ -104,6 +105,9 @@ void OnThemeChanged() override; void OnNativeThemeChanged(const ui::NativeTheme* theme) override; + // Returns the color for the icons on the buttons per the current NativeTheme. + SkColor GetTextColorForIcon(); + // We use a hidden view to grab mouse clicks and bring focus to the find // text box. This is because although the find text box may look like it // extends all the way to the find button, it only goes as far as to the @@ -137,6 +141,7 @@ scoped_ptr<views::Painter> find_text_border_; views::Label* match_count_text_; views::View* focus_forwarder_view_; + views::Separator* separator_; views::ImageButton* find_previous_button_; views::ImageButton* find_next_button_; views::ImageButton* close_button_;
diff --git a/chrome/browser/ui/views/frame/browser_frame_android.cc b/chrome/browser/ui/views/frame/browser_frame_android.cc new file mode 100644 index 0000000..883ee67 --- /dev/null +++ b/chrome/browser/ui/views/frame/browser_frame_android.cc
@@ -0,0 +1,80 @@ +// Copyright 2015 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/views/frame/browser_frame_android.h" + +#include "chrome/browser/ui/views/frame/browser_shutdown.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "ui/aura/window.h" +#include "ui/aura/window_tree_host_platform.h" + +/////////////////////////////////////////////////////////////////////////////// +// BrowserFrameAndroid, public: + +// static +const char BrowserFrameAndroid::kWindowName[] = "BrowserFrameAndroid"; + +namespace { +// |g_host| should be set before browser frame instantiation. It is used to get +// the window which is needed for creating the widget for the browser frame. +// TODO(moshayedi): crbug.com/551055. This is temporary until we have +// multi-window support. +aura::WindowTreeHostPlatform* g_host = nullptr; +} + +BrowserFrameAndroid::BrowserFrameAndroid(BrowserFrame* browser_frame, + BrowserView* browser_view) + : views::NativeWidgetAura(browser_frame), browser_view_(browser_view) { + GetNativeWindow()->SetName(kWindowName); +} + +// static +void BrowserFrameAndroid::SetHost(aura::WindowTreeHostPlatform* host) { + g_host = host; +} + +/////////////////////////////////////////////////////////////////////////////// +// BrowserFrameAndroid, views::NativeWidgetAura overrides: + +void BrowserFrameAndroid::OnWindowDestroying(aura::Window* window) { + // Destroy any remaining WebContents early on. Doing so may result in + // calling back to one of the Views/LayoutManagers or supporting classes of + // BrowserView. By destroying here we ensure all said classes are valid. + DestroyBrowserWebContents(browser_view_->browser()); + NativeWidgetAura::OnWindowDestroying(window); +} + +//////////////////////////////////////////////////////////////////////////////// +// BrowserFrameAndroid, NativeBrowserFrame implementation: + +views::Widget::InitParams BrowserFrameAndroid::GetWidgetParams() { + DCHECK(g_host); + + views::Widget::InitParams params; + params.native_widget = this; + params.context = g_host->window(); + return params; +} + +bool BrowserFrameAndroid::UseCustomFrame() const { + return true; +} + +bool BrowserFrameAndroid::UsesNativeSystemMenu() const { + return false; +} + +int BrowserFrameAndroid::GetMinimizeButtonOffset() const { + return 0; +} + +bool BrowserFrameAndroid::ShouldSaveWindowPlacement() const { + return false; +} + +void BrowserFrameAndroid::GetWindowPlacement( + gfx::Rect* bounds, + ui::WindowShowState* show_state) const {} + +BrowserFrameAndroid::~BrowserFrameAndroid() {}
diff --git a/chrome/browser/ui/views/frame/browser_frame_android.h b/chrome/browser/ui/views/frame/browser_frame_android.h new file mode 100644 index 0000000..f711d41 --- /dev/null +++ b/chrome/browser/ui/views/frame/browser_frame_android.h
@@ -0,0 +1,59 @@ +// Copyright 2015 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_VIEWS_FRAME_BROWSER_FRAME_ANDROID_H_ +#define CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_FRAME_ANDROID_H_ + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "chrome/browser/ui/views/frame/native_browser_frame.h" +#include "ui/aura/window_tree_host_platform.h" +#include "ui/views/widget/native_widget_aura.h" + +class BrowserFrame; +class BrowserView; + +//////////////////////////////////////////////////////////////////////////////// +// BrowserFrameAndroid +// +// BrowserFrameAndroid is a NativeWidgetAura subclass that provides the window +// frame for the Chrome browser window. +// +class BrowserFrameAndroid : public views::NativeWidgetAura, + public NativeBrowserFrame { + public: + static const char kWindowName[]; + + BrowserFrameAndroid(BrowserFrame* browser_frame, BrowserView* browser_view); + + BrowserView* browser_view() const { return browser_view_; } + + // Must be called before the browser frame is created. + static void SetHost(aura::WindowTreeHostPlatform* host); + + protected: + // Overridden from views::NativeWidgetAura: + void OnWindowDestroying(aura::Window* window) override; + + // Overridden from NativeBrowserFrame: + views::Widget::InitParams GetWidgetParams() override; + bool UseCustomFrame() const override; + bool UsesNativeSystemMenu() const override; + int GetMinimizeButtonOffset() const override; + bool ShouldSaveWindowPlacement() const override; + void GetWindowPlacement(gfx::Rect* bounds, + ui::WindowShowState* show_state) const override; + + ~BrowserFrameAndroid() override; + + private: + class WindowPropertyWatcher; + + // The BrowserView is our ClientView. This is a pointer to it. + BrowserView* browser_view_; + + DISALLOW_COPY_AND_ASSIGN(BrowserFrameAndroid); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_FRAME_ANDROID_H_
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc index 6fbb26b..444aad2 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -176,10 +176,8 @@ return 0; if (browser_view()->IsTabStripVisible()) { - if (frame()->IsMaximized() || frame()->IsFullscreen()) - return kTabstripTopSpacingShort; - else - return kTabstripTopSpacingTall; + return (frame()->IsMaximized() || frame()->IsFullscreen()) ? + kTabstripTopSpacingShort : kTabstripTopSpacingTall; } if (UsePackagedAppHeaderStyle() || UseWebAppHeaderStyle())
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc index 7168d7c..10c5958 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -347,65 +347,63 @@ int x = toolbar_bounds.x(); int w = toolbar_bounds.width(); - gfx::ImageSkia* theme_toolbar = tp->GetImageSkiaNamed(IDR_THEME_TOOLBAR); - gfx::ImageSkia* toolbar_center = tp->GetImageSkiaNamed( - IDR_CONTENT_TOP_CENTER); - + // Toolbar background. + int y = toolbar_bounds.y(); // Tile the toolbar image starting at the frame edge on the left and where // the tabstrip is on the top. - int y = toolbar_bounds.y(); - int dest_y = browser_view()->IsTabStripVisible() - ? y + (kFrameShadowThickness * 2) - : y; - canvas->TileImageInt(*theme_toolbar, - x + GetThemeBackgroundXInset(), - dest_y - GetTopInset(), x, - dest_y, w, theme_toolbar->height()); + gfx::ImageSkia* theme_toolbar = tp->GetImageSkiaNamed(IDR_THEME_TOOLBAR); + int dest_y = y; + // In the pre-MD world, the toolbar top edge is drawn using the + // IDR_CONTENT_TOP_XXX images, which overlay the toolbar. The top 2 px of + // these images is the actual top edge, and is partly transparent, so the + // toolbar background shouldn't be drawn over it. + const int kPreMDToolbarTopEdgeExclusion = 2; + if (browser_view()->IsTabStripVisible()) + dest_y += kPreMDToolbarTopEdgeExclusion; + canvas->TileImageInt(*theme_toolbar, x + GetThemeBackgroundXInset(), + dest_y - GetTopInset(), x, dest_y, w, + theme_toolbar->height()); + // Toolbar edges. if (browser_view()->IsTabStripVisible()) { + // Pre-Windows 10, we draw toolbar left and right edges and top corners, + // partly atop the window border. In Windows 10+, we don't draw our own + // window border but rather go right to the system border, so we need only + // draw the toolbar top edge. + int center_x = x; + int center_w = w; if (base::win::GetVersion() < base::win::VERSION_WIN10) { - int left_x = x - kContentEdgeShadowThickness; - // Draw rounded corners for the tab. - gfx::ImageSkia* toolbar_left_mask = - tp->GetImageSkiaNamed(IDR_CONTENT_TOP_LEFT_CORNER_MASK); - gfx::ImageSkia* toolbar_right_mask = - tp->GetImageSkiaNamed(IDR_CONTENT_TOP_RIGHT_CORNER_MASK); - - // We mask out the corners by using the DestinationIn transfer mode, - // which keeps the RGB pixels from the destination and the alpha from - // the source. + // Mask out the top left corner and draw left corner and edge. + const int left_x = center_x - kContentEdgeShadowThickness; SkPaint paint; paint.setXfermodeMode(SkXfermode::kDstIn_Mode); - - // Mask out the top left corner. - canvas->DrawImageInt(*toolbar_left_mask, left_x, y, paint); - - // Mask out the top right corner. - int right_x = - x + w + kContentEdgeShadowThickness - toolbar_right_mask->width(); - canvas->DrawImageInt(*toolbar_right_mask, right_x, y, paint); - - // Draw left edge. + canvas->DrawImageInt( + *tp->GetImageSkiaNamed(IDR_CONTENT_TOP_LEFT_CORNER_MASK), left_x, y, + paint); gfx::ImageSkia* toolbar_left = tp->GetImageSkiaNamed(IDR_CONTENT_TOP_LEFT_CORNER); canvas->DrawImageInt(*toolbar_left, left_x, y); + center_x = left_x + toolbar_left->width(); - // Draw center edge. - canvas->TileImageInt(*toolbar_center, left_x + toolbar_left->width(), y, - right_x - (left_x + toolbar_left->width()), - toolbar_center->height()); - - // Right edge. + // Mask out the top right corner and draw right corner and edge. + gfx::ImageSkia* toolbar_right_mask = + tp->GetImageSkiaNamed(IDR_CONTENT_TOP_RIGHT_CORNER_MASK); + const int right_x = toolbar_bounds.right() + + kContentEdgeShadowThickness - toolbar_right_mask->width(); + canvas->DrawImageInt(*toolbar_right_mask, right_x, y, paint); canvas->DrawImageInt(*tp->GetImageSkiaNamed(IDR_CONTENT_TOP_RIGHT_CORNER), right_x, y); - } else { - // On Windows 10, we don't draw our own window border but rather go right - // to the system border, so we don't need to draw the toolbar edges. - canvas->TileImageInt(*toolbar_center, x, y, w, toolbar_center->height()); + center_w = right_x - center_x; } + + // Top edge. + gfx::ImageSkia* toolbar_center = + tp->GetImageSkiaNamed(IDR_CONTENT_TOP_CENTER); + canvas->TileImageInt(*toolbar_center, center_x, y, center_w, + toolbar_center->height()); } - // Draw the content/toolbar separator. + // Toolbar/content separator. if (ui::MaterialDesignController::IsModeMaterial()) { toolbar_bounds.Inset(kClientEdgeThickness, 0); BrowserView::Paint1pxHorizontalLine( @@ -417,8 +415,7 @@ canvas->FillRect( gfx::Rect(x + kClientEdgeThickness, toolbar_bounds.bottom() - kClientEdgeThickness, - w - (2 * kClientEdgeThickness), - kClientEdgeThickness), + w - (2 * kClientEdgeThickness), kClientEdgeThickness), ThemeProperties::GetDefaultColor( ThemeProperties::COLOR_TOOLBAR_SEPARATOR)); }
diff --git a/chrome/browser/ui/views/frame/native_browser_frame_factory_android.cc b/chrome/browser/ui/views/frame/native_browser_frame_factory_android.cc new file mode 100644 index 0000000..d846db6 --- /dev/null +++ b/chrome/browser/ui/views/frame/native_browser_frame_factory_android.cc
@@ -0,0 +1,13 @@ +// Copyright 2015 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/views/frame/native_browser_frame_factory.h" + +#include "chrome/browser/ui/views/frame/browser_frame_android.h" + +NativeBrowserFrame* NativeBrowserFrameFactory::Create( + BrowserFrame* browser_frame, + BrowserView* browser_view) { + return new BrowserFrameAndroid(browser_frame, browser_view); +}
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc index 1dfb6238..7e056b43 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
@@ -200,16 +200,15 @@ } int OpaqueBrowserFrameViewLayout::FrameBorderThickness(bool restored) const { - return (!restored && (IsTitleBarCondensed() || - delegate_->IsFullscreen())) ? + return (!restored && (IsTitleBarCondensed() || delegate_->IsFullscreen())) ? 0 : kFrameBorderThickness; } int OpaqueBrowserFrameViewLayout::NonClientBorderThickness() const { + const int frame = FrameBorderThickness(false); // When we fill the screen, we don't show a client edge. - return FrameBorderThickness(false) + - ((IsTitleBarCondensed() || delegate_->IsFullscreen()) ? - 0 : views::NonClientFrameView::kClientEdgeThickness); + return (IsTitleBarCondensed() || delegate_->IsFullscreen()) ? + frame : (frame + views::NonClientFrameView::kClientEdgeThickness); } int OpaqueBrowserFrameViewLayout::NonClientTopBorderHeight( @@ -221,33 +220,31 @@ } int thickness = FrameBorderThickness(restored); - if (!restored && delegate_->IsTabStripVisible() && - (delegate_->IsMaximized() || IsTitleBarCondensed())) { + if (!restored && delegate_->IsTabStripVisible() && IsTitleBarCondensed()) thickness -= kTabstripTopShadowThickness; - } return thickness; } int OpaqueBrowserFrameViewLayout::GetTabStripInsetsTop(bool restored) const { - return NonClientTopBorderHeight(restored) + - ((!restored && - (delegate_->IsMaximized() || IsTitleBarCondensed() || - delegate_->IsFullscreen())) ? 0 : kNonClientRestoredExtraThickness); + const int top = NonClientTopBorderHeight(restored); + return (!restored && (IsTitleBarCondensed() || delegate_->IsFullscreen())) ? + top : (top + kNonClientRestoredExtraThickness); } int OpaqueBrowserFrameViewLayout::TitlebarBottomThickness(bool restored) const { - return kTitlebarTopAndBottomEdgeThickness + - ((!restored && IsTitleBarCondensed()) ? 0 : - views::NonClientFrameView::kClientEdgeThickness); + const int edge = kTitlebarTopAndBottomEdgeThickness; + return (!restored && IsTitleBarCondensed()) ? + edge : (edge + views::NonClientFrameView::kClientEdgeThickness); } int OpaqueBrowserFrameViewLayout::CaptionButtonY(bool restored) const { // Maximized buttons start at window top, since the window has no border. This // offset is for the image (the actual clickable bounds extend all the way to // the top to take Fitts' Law into account). - return ((!restored && IsTitleBarCondensed()) ? + const int frame = (!restored && IsTitleBarCondensed()) ? FrameBorderThickness(false) : - views::NonClientFrameView::kFrameShadowThickness) + extra_caption_y_; + views::NonClientFrameView::kFrameShadowThickness; + return frame + extra_caption_y_; } gfx::Rect OpaqueBrowserFrameViewLayout::IconBounds() const { @@ -281,10 +278,10 @@ } int OpaqueBrowserFrameViewLayout::NewTabCaptionSpacing() const { - return has_trailing_buttons_ - ? (IsTitleBarCondensed() ? kNewTabCaptionCondensedSpacing - : kNewTabCaptionNormalSpacing) - : kNewTabNoCaptionButtonsSpacing; + if (!has_trailing_buttons_) + return kNewTabNoCaptionButtonsSpacing; + return IsTitleBarCondensed() ? + kNewTabCaptionCondensedSpacing : kNewTabCaptionNormalSpacing; } void OpaqueBrowserFrameViewLayout::LayoutWindowControls(views::View* host) {
diff --git a/chrome/browser/ui/views/layout_constants.cc b/chrome/browser/ui/views/layout_constants.cc index 68dd76b..6392477 100644 --- a/chrome/browser/ui/views/layout_constants.cc +++ b/chrome/browser/ui/views/layout_constants.cc
@@ -11,8 +11,9 @@ const int kFindBarVerticalOffset[] = {1, 6, 6}; const int kIconLabelViewInternalPadding[] = {3, 2, 2}; const int kIconLabelViewTrailingPadding[] = {2, 8, 8}; - const int kLocationBarBubbleHorizontalPadding[] = {1, 5, 5}; - const int kLocationBarBubbleVerticalPadding[] = {1, 5, 5}; + const int kLocationBarBorderThickness[] = {2, 1, 1}; + const int kLocationBarBubbleHorizontalPadding[] = {1, 4, 4}; + const int kLocationBarBubbleVerticalPadding[] = {1, 4, 4}; const int kLocationBarHeight[] = {0, 28, 32}; const int kLocationBarHorizontalPadding[] = {3, 6, 6}; const int kLocationBarVerticalPadding[] = {2, 2, 2}; @@ -45,6 +46,8 @@ return kIconLabelViewInternalPadding[mode]; case ICON_LABEL_VIEW_TRAILING_PADDING: return kIconLabelViewTrailingPadding[mode]; + case LOCATION_BAR_BORDER_THICKNESS: + return kLocationBarBorderThickness[mode]; case LOCATION_BAR_BUBBLE_HORIZONTAL_PADDING: return kLocationBarBubbleHorizontalPadding[mode]; case LOCATION_BAR_BUBBLE_VERTICAL_PADDING:
diff --git a/chrome/browser/ui/views/layout_constants.h b/chrome/browser/ui/views/layout_constants.h index 73799a77..57ec8cb 100644 --- a/chrome/browser/ui/views/layout_constants.h +++ b/chrome/browser/ui/views/layout_constants.h
@@ -18,6 +18,9 @@ // views. ICON_LABEL_VIEW_TRAILING_PADDING, + // The thickness of the location bar's border. + LOCATION_BAR_BORDER_THICKNESS, + // The horizontal space between the edge and a bubble. LOCATION_BAR_BUBBLE_HORIZONTAL_PADDING,
diff --git a/chrome/browser/ui/views/location_bar/background_with_1_px_border.cc b/chrome/browser/ui/views/location_bar/background_with_1_px_border.cc new file mode 100644 index 0000000..999ab1b5 --- /dev/null +++ b/chrome/browser/ui/views/location_bar/background_with_1_px_border.cc
@@ -0,0 +1,66 @@ +// Copyright 2015 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/views/location_bar/background_with_1_px_border.h" + +#include "chrome/browser/ui/views/layout_constants.h" +#include "third_party/skia/include/core/SkPaint.h" +#include "third_party/skia/include/core/SkPath.h" +#include "third_party/skia/include/pathops/SkPathOps.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/scoped_canvas.h" +#include "ui/views/view.h" +#include "ui/views/widget/widget.h" + +BackgroundWith1PxBorder::BackgroundWith1PxBorder(SkColor background, + SkColor border, + bool is_popup_mode) + : border_color_(border), is_popup_mode_(is_popup_mode) { + SetNativeControlColor(background); +} + +void BackgroundWith1PxBorder::Paint(gfx::Canvas* canvas, + views::View* view) const { + gfx::ScopedCanvas scoped_canvas(canvas); + const float scale = canvas->UndoDeviceScaleFactor(); + const float kPreScaleOffset = + GetLayoutConstant(LOCATION_BAR_BORDER_THICKNESS); + const float kPostScaleOffset = -0.5f; + gfx::RectF border_rect_f(view->GetContentsBounds()); + SkPath path; + if (is_popup_mode_) { + // Maximized popup windows don't draw the horizontal edges. We implement + // this by not insetting the edge before scaling. The subsequent post + // scaling inset expands the paint area outside of the canvas. + border_rect_f.Inset(view->GetWidget()->IsMaximized() ? 0 : kPreScaleOffset, + kPreScaleOffset); + border_rect_f.Scale(scale); + border_rect_f.Inset(kPostScaleOffset, kPostScaleOffset); + path.addRect(gfx::RectFToSkRect(border_rect_f)); + } else { + border_rect_f.Inset(kPreScaleOffset, kPreScaleOffset); + border_rect_f.Scale(scale); + border_rect_f.Inset(kPostScaleOffset, kPostScaleOffset); + const SkScalar kCornerRadius = SkDoubleToScalar(2.5f * scale); + path.addRoundRect(gfx::RectFToSkRect(border_rect_f), kCornerRadius, + kCornerRadius); + } + + SkPaint paint; + paint.setStyle(SkPaint::kStroke_Style); + paint.setStrokeWidth(1); + paint.setAntiAlias(true); + + SkPath stroke_path; + paint.getFillPath(path, &stroke_path); + + SkPath fill_path; + Op(path, stroke_path, kDifference_SkPathOp, &fill_path); + paint.setStyle(SkPaint::kFill_Style); + paint.setColor(get_color()); + canvas->sk_canvas()->drawPath(fill_path, paint); + + paint.setColor(border_color_); + canvas->sk_canvas()->drawPath(stroke_path, paint); +}
diff --git a/chrome/browser/ui/views/location_bar/background_with_1_px_border.h b/chrome/browser/ui/views/location_bar/background_with_1_px_border.h new file mode 100644 index 0000000..588b3f5 --- /dev/null +++ b/chrome/browser/ui/views/location_bar/background_with_1_px_border.h
@@ -0,0 +1,47 @@ +// Copyright 2015 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_VIEWS_LOCATION_BAR_BACKGROUND_WITH_1_PX_BORDER_H_ +#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_BACKGROUND_WITH_1_PX_BORDER_H_ + +#include "base/macros.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/views/background.h" + +namespace gfx { +class Canvas; +} + +namespace views { +class View; +} + +// BackgroundWith1PxBorder renders a solid background color, with a one pixel +// border. This accounts for the scaling of the canvas, so that the border is +// one pixel regardless of display scaling. When created for popup mode, the +// border will be a rectangle, unless the window is maximized. A maximized popup +// will remove the horizontal edges of the border. +// +// When created for non popups, the border will have rounded corners. +class BackgroundWith1PxBorder : public views::Background { + public: + BackgroundWith1PxBorder(SkColor background, + SkColor border, + bool is_popup_mode); + + void Paint(gfx::Canvas* canvas, views::View* view) const override; + + private: + // Color for the one pixel border. + SkColor border_color_; + + // If true the border will be a rectangle, and will not render the horizontal + // edges when the window is maximized. If false the border will have rounded + // corners. + bool is_popup_mode_; + + DISALLOW_COPY_AND_ASSIGN(BackgroundWith1PxBorder); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_BACKGROUND_WITH_1_PX_BORDER_H_
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index 21d452b94..9d19ce3 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -38,6 +38,7 @@ #include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/browser_dialogs.h" #include "chrome/browser/ui/views/layout_constants.h" +#include "chrome/browser/ui/views/location_bar/background_with_1_px_border.h" #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h" #include "chrome/browser/ui/views/location_bar/ev_bubble_view.h" #include "chrome/browser/ui/views/location_bar/keyword_hint_view.h" @@ -116,11 +117,7 @@ // static -// TODO(jonross): Replace with lookup once Material Design asset has landed. -// (https://crbug.com/495654) -// Thickness of the edges of the omnibox background images, for normal and -// popup windows. -const int kNormalEdgeThickness = 2; +// Thickness of the edges of the omnibox background images, for popup windows. const int kPopupEdgeThickness = 1; const char LocationBarView::kViewClassName[] = "LocationBarView"; @@ -164,6 +161,12 @@ ui_zoom::ZoomEventManager::GetForBrowserContext(profile) ->AddZoomEventManagerObserver(this); + + if (ui::MaterialDesignController::IsModeMaterial()) { + set_background(new BackgroundWith1PxBorder( + GetColor(SecurityStateModel::NONE, BACKGROUND), + SkColorSetARGB(0x4D, 0x00, 0x00, 0x00), is_popup_mode_)); + } } LocationBarView::~LocationBarView() { @@ -513,7 +516,8 @@ *popup_width = parent()->width(); gfx::Rect location_bar_bounds(bounds()); - location_bar_bounds.Inset(kNormalEdgeThickness, 0); + location_bar_bounds.Inset(GetLayoutConstant(LOCATION_BAR_BORDER_THICKNESS), + 0); *left_margin = location_bar_bounds.x(); *right_margin = *popup_width - location_bar_bounds.right(); } @@ -885,10 +889,8 @@ } int LocationBarView::GetVerticalEdgeThickness() const { - // In Material Design vertical layout disregards the border. - if (ui::MaterialDesignController::IsModeMaterial()) - return 0; - return is_popup_mode_ ? kPopupEdgeThickness : kNormalEdgeThickness; + return is_popup_mode_ ? kPopupEdgeThickness + : GetLayoutConstant(LOCATION_BAR_BORDER_THICKNESS); } int LocationBarView::VerticalPadding() const { @@ -1289,6 +1291,9 @@ void LocationBarView::OnPaint(gfx::Canvas* canvas) { View::OnPaint(canvas); + if (ui::MaterialDesignController::IsModeMaterial()) + return; // The background and border are painted by our Background. + // Fill the location bar background color behind the border. Parts of the // border images are meant to rest atop the toolbar background and parts atop // the omnibox background, so we can't just blindly fill our entire bounds. @@ -1321,36 +1326,17 @@ if (show_focus_rect_ && HasFocus()) recorder.canvas()->DrawFocusRect(omnibox_view_->bounds()); + if (ui::MaterialDesignController::IsModeMaterial()) + return; // The background and border are painted by our Background. + // Maximized popup windows don't draw the horizontal edges. We implement this // by simply expanding the paint area outside the view by the edge thickness. gfx::Rect border_rect(GetContentsBounds()); if (is_popup_mode_ && (GetHorizontalEdgeThickness() == 0)) border_rect.Inset(-kPopupEdgeThickness, 0); - if (ui::MaterialDesignController::IsModeMaterial()) { - gfx::Canvas* canvas = recorder.canvas(); - gfx::ScopedCanvas scoped_canvas(canvas); - const float scale = canvas->UndoDeviceScaleFactor(); - - SkPaint paint; - paint.setStyle(SkPaint::Style::kStroke_Style); - paint.setColor(SkColorSetARGB(0x40, 0x00, 0x00, 0x00)); - paint.setStrokeWidth(1); - paint.setAntiAlias(true); - - const float kOffset = 0.5f; - gfx::RectF border_rect_f(border_rect); - border_rect_f.Scale(scale); - gfx::InsetsF insets(kOffset, kOffset, kOffset, kOffset); - border_rect_f.Inset(insets); - - const SkScalar kCornerRadius = SkDoubleToScalar(2.5f * scale); - canvas->sk_canvas()->drawRoundRect(gfx::RectFToSkRect(border_rect_f), - kCornerRadius, kCornerRadius, paint); - } else { - views::Painter::PaintPainterAt(recorder.canvas(), border_painter_.get(), - border_rect); - } + views::Painter::PaintPainterAt(recorder.canvas(), border_painter_.get(), + border_rect); } ////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/views/simple_message_box_views.cc b/chrome/browser/ui/views/simple_message_box_views.cc index 50433760..1732509b 100644 --- a/chrome/browser/ui/views/simple_message_box_views.cc +++ b/chrome/browser/ui/views/simple_message_box_views.cc
@@ -11,7 +11,7 @@ #include "chrome/browser/ui/simple_message_box_internal.h" #include "chrome/grit/generated_resources.h" #include "components/constrained_window/constrained_window_views.h" -#include "components/startup_metric_utils/startup_metric_utils.h" +#include "components/startup_metric_utils/browser/startup_metric_utils.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/native_widget_types.h"
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc index 47db562c..60ae27435 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -236,7 +236,8 @@ return IsTabPinned(tabstrip_->GetModelIndexOfTab(tab)); } -const ui::ListSelectionModel& BrowserTabStripController::GetSelectionModel() { +const ui::ListSelectionModel& +BrowserTabStripController::GetSelectionModel() const { return model_->selection_model(); }
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h index db2f32d..ad95104 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
@@ -45,7 +45,7 @@ bool IsTabPinned(Tab* tab) const; // TabStripController implementation: - const ui::ListSelectionModel& GetSelectionModel() override; + const ui::ListSelectionModel& GetSelectionModel() const override; int GetCount() const override; bool IsValidIndex(int model_index) const override; bool IsActiveTab(int model_index) const override;
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc index 22845aa..2ea2fb8 100644 --- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
@@ -30,7 +30,8 @@ active_index_ = -1; } -const ui::ListSelectionModel& FakeBaseTabStripController::GetSelectionModel() { +const ui::ListSelectionModel& +FakeBaseTabStripController::GetSelectionModel() const { return selection_model_; }
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h index 241c5cd..21312538 100644 --- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
@@ -22,7 +22,7 @@ void set_tab_strip(TabStrip* tab_strip) { tab_strip_ = tab_strip; } // TabStripController overrides: - const ui::ListSelectionModel& GetSelectionModel() override; + const ui::ListSelectionModel& GetSelectionModel() const override; int GetCount() const override; bool IsValidIndex(int index) const override; bool IsActiveTab(int index) const override;
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc index 809d656..c2d651c 100644 --- a/chrome/browser/ui/views/tabs/tab.cc +++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -100,14 +100,6 @@ // animation. const int kPinnedTitleChangeInitialXOffset = 6; -// Radius of the radial gradient used for pinned title change animation. -const int kPinnedTitleChangeGradientRadius = 20; - -// Colors of the gradient used during the pinned title change animation. -const SkColor kPinnedTitleChangeGradientColor1 = SK_ColorWHITE; -const SkColor kPinnedTitleChangeGradientColor2 = - SkColorSetARGB(0, 255, 255, 255); - // Max number of images to cache. This has to be at least two since rounding // errors may lead to tabs in the same tabstrip having different sizes. const size_t kMaxImageCacheSize = 4; @@ -148,6 +140,23 @@ animation->Stop(); } +void DrawHighlight(gfx::Canvas* canvas, + const SkPoint& p, + SkScalar radius, + SkAlpha alpha) { + const SkColor colors[2] = { SkColorSetA(SK_ColorWHITE, alpha), + SkColorSetA(SK_ColorWHITE, 0) }; + skia::RefPtr<SkShader> shader = skia::AdoptRef(SkGradientShader::CreateRadial( + p, radius, colors, nullptr, 2, SkShader::kClamp_TileMode)); + SkPaint paint; + paint.setStyle(SkPaint::kFill_Style); + paint.setAntiAlias(true); + paint.setShader(shader.get()); + canvas->sk_canvas()->drawRect( + SkRect::MakeXYWH(p.x() - radius, p.y() - radius, radius * 2, radius * 2), + paint); +} + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -356,9 +365,9 @@ // static const char Tab::kViewClassName[] = "Tab"; -Tab::TabImage Tab::tab_active_ = {0}; -Tab::TabImage Tab::tab_inactive_ = {0}; -Tab::TabImage Tab::tab_alpha_ = {0}; +Tab::TabImages Tab::active_images_ = {0}; +Tab::TabImages Tab::inactive_images_ = {0}; +Tab::TabImages Tab::mask_images_ = {0}; Tab::ImageCache* Tab::image_cache_ = NULL; //////////////////////////////////////////////////////////////////////////////// @@ -580,7 +589,7 @@ // Since we use images, the real minimum height of the image is // defined most accurately by the height of the end cap images. InitTabResources(); - int height = tab_active_.image_l->height(); + int height = active_images_.image_l->height(); return gfx::Size(GetLayoutInsets(TAB).width(), height); } @@ -1124,15 +1133,14 @@ PaintActiveTabBackground(canvas); } else { if (pinned_title_change_animation_ && - pinned_title_change_animation_->is_animating()) { + pinned_title_change_animation_->is_animating()) PaintInactiveTabBackgroundWithTitleChange(canvas); - } else { + else PaintInactiveTabBackground(canvas); - } - double throb_value = GetThrobValue(); + const double throb_value = GetThrobValue(); if (throb_value > 0) { - canvas->SaveLayerAlpha(static_cast<int>(throb_value * 0xff), + canvas->SaveLayerAlpha(gfx::ToRoundedInt(throb_value * 0xff), GetLocalBounds()); PaintActiveTabBackground(canvas); canvas->Restore(); @@ -1141,76 +1149,47 @@ } void Tab::PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas) { - // Render the inactive tab background. We'll use this for clipping. + const int kPinnedTitleChangeGradientRadius = 20; + const float radius = kPinnedTitleChangeGradientRadius; + double x = radius; + int alpha = 255; + if (pinned_title_change_animation_->current_part_index() == 0) { + x = pinned_title_change_animation_->CurrentValueBetween( + width() + radius - kPinnedTitleChangeInitialXOffset, radius); + } else if (pinned_title_change_animation_->current_part_index() == 2) { + x = pinned_title_change_animation_->CurrentValueBetween(radius, -radius); + alpha = pinned_title_change_animation_->CurrentValueBetween(255, 0); + } + SkPoint p; + p.set(SkDoubleToScalar(x), 0); gfx::Canvas background_canvas(size(), canvas->image_scale(), false); PaintInactiveTabBackground(&background_canvas); - gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); - - // Draw a radial gradient to hover_canvas. + canvas->DrawImageInt(background_image, 0, 0); gfx::Canvas hover_canvas(size(), canvas->image_scale(), false); - int radius = kPinnedTitleChangeGradientRadius; - int x0 = width() + radius - kPinnedTitleChangeInitialXOffset; - int x1 = radius; - int x2 = -radius; - int x; - if (pinned_title_change_animation_->current_part_index() == 0) { - x = pinned_title_change_animation_->CurrentValueBetween(x0, x1); - } else if (pinned_title_change_animation_->current_part_index() == 1) { - x = x1; - } else { - x = pinned_title_change_animation_->CurrentValueBetween(x1, x2); - } - SkPoint center_point; - center_point.iset(x, 0); - SkColor colors[2] = { kPinnedTitleChangeGradientColor1, - kPinnedTitleChangeGradientColor2 }; - skia::RefPtr<SkShader> shader = skia::AdoptRef( - SkGradientShader::CreateRadial( - center_point, SkIntToScalar(radius), colors, NULL, 2, - SkShader::kClamp_TileMode)); - SkPaint paint; - paint.setShader(shader.get()); - hover_canvas.DrawRect(gfx::Rect(x - radius, -radius, radius * 2, radius * 2), - paint); - - // Draw the radial gradient clipped to the background into hover_image. + DrawHighlight(&hover_canvas, p, SkFloatToScalar(radius), alpha); gfx::ImageSkia hover_image = gfx::ImageSkiaOperations::CreateMaskedImage( gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); - - // Draw the tab background to the canvas. - canvas->DrawImageInt(background_image, 0, 0); - - // And then the gradient on top of that. - if (pinned_title_change_animation_->current_part_index() == 2) { - uint8 alpha = pinned_title_change_animation_->CurrentValueBetween(255, 0); - canvas->DrawImageInt(hover_image, 0, 0, alpha); - } else { - canvas->DrawImageInt(hover_image, 0, 0); - } + canvas->DrawImageInt(hover_image, 0, 0); } void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas) { - int tab_id; - int frame_id; - views::Widget* widget = GetWidget(); - GetTabIdAndFrameId(widget, &tab_id, &frame_id); + int tab_id, frame_id; + GetTabIdAndFrameId(GetWidget(), &tab_id, &frame_id); + // HasCustomImage() is only true if the theme provides the image. However, + // even if the theme does not provide a tab background, the theme machinery + // will make one if given a frame image. + ui::ThemeProvider* theme_provider = GetThemeProvider(); + const bool has_custom_image = theme_provider->HasCustomImage(tab_id) || + (frame_id != 0 && theme_provider->HasCustomImage(frame_id)); // Explicitly map the id so we cache correctly. const chrome::HostDesktopType host_desktop_type = GetHostDesktopType(this); tab_id = chrome::MapThemeImage(host_desktop_type, tab_id); - // HasCustomImage() is only true if the theme provides the image. However, - // even if the theme does not provide a tab background, the theme machinery - // will make one if given a frame image. - ui::ThemeProvider* theme_provider = GetThemeProvider(); - const bool theme_provided_image = theme_provider->HasCustomImage(tab_id) || - (frame_id != 0 && theme_provider->HasCustomImage(frame_id)); - - const bool can_cache = !theme_provided_image && - !hover_controller_.ShouldDraw(); - - if (can_cache) { + // We only cache the image when it's the default image and we're not hovered, + // to avoid caching a background image that isn't the same for all tabs. + if (!has_custom_image && !hover_controller_.ShouldDraw()) { ui::ScaleFactor scale_factor = ui::GetSupportedScaleFactor(canvas->image_scale()); gfx::ImageSkia cached_image(GetCachedImage(tab_id, size(), scale_factor)); @@ -1228,120 +1207,114 @@ void Tab::PaintInactiveTabBackgroundUsingResourceId(gfx::Canvas* canvas, int tab_id) { - // WARNING: the inactive tab background may be cached. If you change what it - // is drawn from you may need to update whether it can be cached. - + gfx::ImageSkia* tab_background = + GetThemeProvider()->GetImageSkiaNamed(tab_id); // The tab image needs to be lined up with the background image // so that it feels partially transparent. These offsets represent the tab // position within the frame background image. - int offset = GetMirroredX() + background_offset_.x(); - - gfx::ImageSkia* tab_bg = GetThemeProvider()->GetImageSkiaNamed(tab_id); - - TabImage* tab_image = &tab_active_; - TabImage* tab_inactive_image = &tab_inactive_; - TabImage* alpha = &tab_alpha_; + const int x_offset = GetMirroredX() + background_offset_.x(); // If the theme is providing a custom background image, then its top edge // should be at the top of the tab. Otherwise, we assume that the background // image is a composited foreground + frame image. - int bg_offset_y = GetThemeProvider()->HasCustomImage(tab_id) ? + const int y_offset = GetThemeProvider()->HasCustomImage(tab_id) ? 0 : background_offset_.y(); - // We need a gfx::Canvas object to be able to extract the image from. - // We draw everything to this canvas and then output it to the canvas - // parameter in addition to using it to mask the hover glow if needed. + const gfx::Insets tab_insets(GetLayoutInsets(TAB)); + // Don't draw over the toolbar, but do include the 1 px divider stroke at the + // bottom. + const int toolbar_overlap = tab_insets.bottom() - 1; + + // Draw everything to a temporary canvas so we can extract an image for use in + // masking the hover glow. gfx::Canvas background_canvas(size(), canvas->image_scale(), false); - // Draw left edge. Don't draw over the toolbar, as we're not the foreground - // tab, but do include the 1 px divider stroke at the bottom. - const gfx::Insets tab_insets(GetLayoutInsets(TAB)); - const int toolbar_overlap = tab_insets.bottom() - 1; + // Draw left edge. gfx::ImageSkia tab_l = gfx::ImageSkiaOperations::CreateTiledImage( - *tab_bg, offset, bg_offset_y, tab_image->l_width, height()); + *tab_background, x_offset, y_offset, mask_images_.l_width, height()); gfx::ImageSkia theme_l = - gfx::ImageSkiaOperations::CreateMaskedImage(tab_l, *alpha->image_l); - background_canvas.DrawImageInt(theme_l, - 0, 0, theme_l.width(), theme_l.height() - toolbar_overlap, - 0, 0, theme_l.width(), theme_l.height() - toolbar_overlap, - false); + gfx::ImageSkiaOperations::CreateMaskedImage(tab_l, *mask_images_.image_l); + background_canvas.DrawImageInt( + theme_l, 0, 0, theme_l.width(), theme_l.height() - toolbar_overlap, 0, 0, + theme_l.width(), theme_l.height() - toolbar_overlap, false); - // Draw right edge. Again, don't draw over the toolbar. - gfx::ImageSkia tab_r = gfx::ImageSkiaOperations::CreateTiledImage(*tab_bg, - offset + width() - tab_image->r_width, bg_offset_y, - tab_image->r_width, height()); + // Draw right edge. + gfx::ImageSkia tab_r = gfx::ImageSkiaOperations::CreateTiledImage( + *tab_background, x_offset + width() - mask_images_.r_width, y_offset, + mask_images_.r_width, height()); gfx::ImageSkia theme_r = - gfx::ImageSkiaOperations::CreateMaskedImage(tab_r, *alpha->image_r); - background_canvas.DrawImageInt(theme_r, - 0, 0, theme_r.width(), theme_r.height() - toolbar_overlap, - width() - theme_r.width(), 0, theme_r.width(), - theme_r.height() - toolbar_overlap, false); + gfx::ImageSkiaOperations::CreateMaskedImage(tab_r, *mask_images_.image_r); + background_canvas.DrawImageInt(theme_r, 0, 0, theme_r.width(), + theme_r.height() - toolbar_overlap, + width() - theme_r.width(), 0, theme_r.width(), + theme_r.height() - toolbar_overlap, false); // Draw center. Instead of masking out the top portion we simply skip over - // it by incrementing by the top padding, since it's a simple rectangle. And - // again, don't draw over the toolbar. + // it by incrementing by the top padding, since it's a simple rectangle. background_canvas.TileImageInt( - *tab_bg, offset + tab_image->l_width, bg_offset_y + tab_insets.top(), - tab_image->l_width, tab_insets.top(), - width() - tab_image->l_width - tab_image->r_width, - height() - tab_insets.top() - toolbar_overlap); + *tab_background, x_offset + mask_images_.l_width, + y_offset + tab_insets.top(), mask_images_.l_width, tab_insets.top(), + width() - mask_images_.l_width - mask_images_.r_width, + height() - tab_insets.top() - toolbar_overlap); - canvas->DrawImageInt( - gfx::ImageSkia(background_canvas.ExtractImageRep()), 0, 0); + gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); + canvas->DrawImageInt(background_image, 0, 0); if (!GetThemeProvider()->HasCustomImage(tab_id) && - hover_controller_.ShouldDraw()) { - hover_controller_.Draw(canvas, gfx::ImageSkia( - background_canvas.ExtractImageRep())); - } + hover_controller_.ShouldDraw()) + hover_controller_.Draw(canvas, background_image); - // Now draw the highlights/shadows around the tab edge. - canvas->DrawImageInt(*tab_inactive_image->image_l, 0, 0); - canvas->TileImageInt(*tab_inactive_image->image_c, - tab_inactive_image->l_width, 0, - width() - tab_inactive_image->l_width - - tab_inactive_image->r_width, - height()); - canvas->DrawImageInt(*tab_inactive_image->image_r, - width() - tab_inactive_image->r_width, 0); + // Now draw the stroke, highlights, and shadows around the tab edge. + TabImages* stroke_images = &inactive_images_; + canvas->DrawImageInt(*stroke_images->image_l, 0, 0); + canvas->TileImageInt( + *stroke_images->image_c, stroke_images->l_width, 0, + width() - stroke_images->l_width - stroke_images->r_width, height()); + canvas->DrawImageInt(*stroke_images->image_r, + width() - stroke_images->r_width, 0); } void Tab::PaintActiveTabBackground(gfx::Canvas* canvas) { gfx::ImageSkia* tab_background = GetThemeProvider()->GetImageSkiaNamed(IDR_THEME_TOOLBAR); - int offset = GetMirroredX() + background_offset_.x(); + int x_offset = GetMirroredX() + background_offset_.x(); - TabImage* tab_image = &tab_active_; - TabImage* alpha = &tab_alpha_; + const gfx::Insets tab_insets(GetLayoutInsets(TAB)); // Draw left edge. gfx::ImageSkia tab_l = gfx::ImageSkiaOperations::CreateTiledImage( - *tab_background, offset, 0, tab_image->l_width, height()); + *tab_background, x_offset, 0, mask_images_.l_width, height()); gfx::ImageSkia theme_l = - gfx::ImageSkiaOperations::CreateMaskedImage(tab_l, *alpha->image_l); - canvas->DrawImageInt(theme_l, 0, 0); + gfx::ImageSkiaOperations::CreateMaskedImage(tab_l, *mask_images_.image_l); + canvas->DrawImageInt( + theme_l, 0, 0, theme_l.width(), theme_l.height(), 0, 0, theme_l.width(), + theme_l.height(), false); // Draw right edge. gfx::ImageSkia tab_r = gfx::ImageSkiaOperations::CreateTiledImage( - *tab_background, - offset + width() - tab_image->r_width, 0, tab_image->r_width, height()); + *tab_background, x_offset + width() - mask_images_.r_width, 0, + mask_images_.r_width, height()); gfx::ImageSkia theme_r = - gfx::ImageSkiaOperations::CreateMaskedImage(tab_r, *alpha->image_r); - canvas->DrawImageInt(theme_r, width() - tab_image->r_width, 0); + gfx::ImageSkiaOperations::CreateMaskedImage(tab_r, *mask_images_.image_r); + canvas->DrawImageInt(theme_r, 0, 0, theme_r.width(), theme_r.height(), + width() - theme_r.width(), 0, theme_r.width(), + theme_r.height(), false); // Draw center. Instead of masking out the top portion we simply skip over it // by incrementing by the top padding, since it's a simple rectangle. - const int top_padding = GetLayoutInsets(TAB).top(); - canvas->TileImageInt(*tab_background, offset + tab_image->l_width, - top_padding, tab_image->l_width, top_padding, - width() - tab_image->l_width - tab_image->r_width, - height() - top_padding); + canvas->TileImageInt(*tab_background, x_offset + mask_images_.l_width, + tab_insets.top(), mask_images_.l_width, tab_insets.top(), + width() - mask_images_.l_width - mask_images_.r_width, + height() - tab_insets.top()); - // Now draw the highlights/shadows around the tab edge. - canvas->DrawImageInt(*tab_image->image_l, 0, 0); - canvas->TileImageInt(*tab_image->image_c, tab_image->l_width, 0, - width() - tab_image->l_width - tab_image->r_width, height()); - canvas->DrawImageInt(*tab_image->image_r, width() - tab_image->r_width, 0); + // Now draw the stroke, highlights, and shadows around the tab edge. + TabImages* stroke_images = &active_images_; + canvas->DrawImageInt(*stroke_images->image_l, 0, 0); + canvas->TileImageInt( + *stroke_images->image_c, stroke_images->l_width, 0, + width() - stroke_images->l_width - stroke_images->r_width, height()); + canvas->DrawImageInt(*stroke_images->image_r, + width() - stroke_images->r_width, 0); } void Tab::PaintIcon(gfx::Canvas* canvas) { @@ -1528,8 +1501,8 @@ // This top line of the tab extends a few pixels left and right of the // center image due to pixels in the rounded corner images. const int kBarPadding = 1; - int main_bar_left = tab_active_.l_width - kBarPadding; - int main_bar_right = width() - tab_active_.r_width + kBarPadding; + int main_bar_left = active_images_.l_width - kBarPadding; + int main_bar_right = width() - active_images_.r_width + kBarPadding; return gfx::Rect( main_bar_left, 0, main_bar_right - main_bar_left, kImmersiveBarHeight); } @@ -1571,20 +1544,22 @@ // We're not letting people override tab images just yet. ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - tab_alpha_.image_l = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_LEFT); - tab_alpha_.image_r = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_RIGHT); + mask_images_.image_l = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_LEFT); + mask_images_.image_r = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_RIGHT); + mask_images_.l_width = mask_images_.image_l->width(); + mask_images_.r_width = mask_images_.image_r->width(); - tab_active_.image_l = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_LEFT); - tab_active_.image_c = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_CENTER); - tab_active_.image_r = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_RIGHT); - tab_active_.l_width = tab_active_.image_l->width(); - tab_active_.r_width = tab_active_.image_r->width(); + active_images_.image_l = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_LEFT); + active_images_.image_c = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_CENTER); + active_images_.image_r = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_RIGHT); + active_images_.l_width = active_images_.image_l->width(); + active_images_.r_width = active_images_.image_r->width(); - tab_inactive_.image_l = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_LEFT); - tab_inactive_.image_c = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_CENTER); - tab_inactive_.image_r = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_RIGHT); - tab_inactive_.l_width = tab_inactive_.image_l->width(); - tab_inactive_.r_width = tab_inactive_.image_r->width(); + inactive_images_.image_l = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_LEFT); + inactive_images_.image_c = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_CENTER); + inactive_images_.image_r = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_RIGHT); + inactive_images_.l_width = inactive_images_.image_l->width(); + inactive_images_.r_width = inactive_images_.image_r->width(); } // static
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h index 8ecd591..be601119 100644 --- a/chrome/browser/ui/views/tabs/tab.h +++ b/chrome/browser/ui/views/tabs/tab.h
@@ -369,16 +369,16 @@ // The offset used to paint the inactive background image. gfx::Point background_offset_; - struct TabImage { + struct TabImages { gfx::ImageSkia* image_l; gfx::ImageSkia* image_c; gfx::ImageSkia* image_r; int l_width; int r_width; }; - static TabImage tab_active_; - static TabImage tab_inactive_; - static TabImage tab_alpha_; + static TabImages active_images_; + static TabImages inactive_images_; + static TabImages mask_images_; // Whether we're showing the icon. It is cached so that we can detect when it // changes and layout appropriately.
diff --git a/chrome/browser/ui/views/tabs/tab_controller.h b/chrome/browser/ui/views/tabs/tab_controller.h index 3e8807be..23de038 100644 --- a/chrome/browser/ui/views/tabs/tab_controller.h +++ b/chrome/browser/ui/views/tabs/tab_controller.h
@@ -24,7 +24,7 @@ // Controller for tabs. class TabController { public: - virtual const ui::ListSelectionModel& GetSelectionModel() = 0; + virtual const ui::ListSelectionModel& GetSelectionModel() const = 0; // Returns true if multiple selection is supported. virtual bool SupportsMultipleSelection() = 0;
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 5269e99..da4e53b1 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -48,6 +48,7 @@ #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_operations.h" #include "ui/gfx/path.h" +#include "ui/gfx/scoped_canvas.h" #include "ui/gfx/screen.h" #include "ui/gfx/skia_util.h" #include "ui/views/controls/image_view.h" @@ -76,16 +77,6 @@ const int kTabStripAnimationVSlop = 40; -// Inactive tabs in a native frame are slightly transparent. -const uint8_t kGlassFrameInactiveTabAlpha = 200; -// If there are multiple tabs selected then make non-selected inactive tabs -// even more transparent. -const uint8_t kGlassFrameInactiveTabAlphaMultiSelection = 150; - -// Alpha applied to all elements save the selected tabs. -const uint8_t kInactiveTabAndNewTabButtonAlphaAsh = 230; -const uint8_t kInactiveTabAndNewTabButtonAlpha = 255; - // Inverse ratio of the width of a tab edge to the width of the tab. When // hovering over the left or right edge of a tab, the drop indicator will // point between tabs. @@ -122,6 +113,13 @@ const int kPinnedToNonPinnedOffset = 3; #endif +// Returns the size of the new tab button, not including any bounds extension to +// enlarge the clickable area. +gfx::Size GetNewTabButtonSize() { + return gfx::Size(GetLayoutConstant(NEW_TAB_BUTTON_WIDTH), + kNewTabButtonHeight); +} + // Returns the width needed for the new tab button (and padding). int GetNewTabButtonWidth() { return GetLayoutConstant(NEW_TAB_BUTTON_WIDTH) - @@ -258,26 +256,23 @@ background_offset_ = offset; } - protected: - // views::View: + private: + // views::ImageButton: #if defined(OS_WIN) void OnMouseReleased(const ui::MouseEvent& event) override; #endif + void OnGestureEvent(ui::GestureEvent* event) override; void OnPaint(gfx::Canvas* canvas) override; - // ui::EventHandler: - void OnGestureEvent(ui::GestureEvent* event) override; - - private: // views::MaskedTargeterDelegate: bool GetHitTestMask(gfx::Path* mask) const override; - bool ShouldWindowContentsBeTransparent() const; - gfx::ImageSkia GetBackgroundImage(views::CustomButton::ButtonState state, - float scale) const; - gfx::ImageSkia GetImageForState(views::CustomButton::ButtonState state, - float scale) const; - gfx::ImageSkia GetImageForScale(float scale) const; + // Paints the fill region of the button into |canvas|, according to the + // supplied values from GetImage(). + void PaintFill(bool pressed, + double hover_value, + float scale, + gfx::Canvas* canvas) const; // Tab strip that contains this button. TabStrip* tab_strip_; @@ -326,11 +321,6 @@ } #endif -void NewTabButton::OnPaint(gfx::Canvas* canvas) { - gfx::ImageSkia image = GetImageForScale(canvas->image_scale()); - canvas->DrawImageInt(image, 0, height() - image.height()); -} - void NewTabButton::OnGestureEvent(ui::GestureEvent* event) { // Consume all gesture events here so that the parent (Tab) does not // start consuming gestures. @@ -338,6 +328,40 @@ event->SetHandled(); } +void NewTabButton::OnPaint(gfx::Canvas* canvas) { + gfx::ScopedCanvas scoped_canvas(canvas); + canvas->Translate(gfx::Vector2d(0, height() - kNewTabButtonHeight)); + + const float scale = canvas->image_scale(); + + // Draw the fill. + const bool pressed = state() == views::CustomButton::STATE_PRESSED; + double hover_value = + (state() == views::CustomButton::STATE_HOVERED) ? 1 : 0; + if (hover_animation_->is_animating()) + hover_value = hover_animation_->GetCurrentValue(); + gfx::ImageSkia* mask = + GetThemeProvider()->GetImageSkiaNamed(IDR_NEWTAB_BUTTON_MASK); + // The canvas and mask have to use the same scale factor. + const float fill_canvas_scale = mask->HasRepresentation(scale) ? + scale : ui::GetScaleForScaleFactor(ui::SCALE_FACTOR_100P); + gfx::Canvas fill_canvas(GetNewTabButtonSize(), fill_canvas_scale, false); + PaintFill(pressed, hover_value, fill_canvas_scale, &fill_canvas); + gfx::ImageSkia image(fill_canvas.ExtractImageRep()); + canvas->DrawImageInt( + gfx::ImageSkiaOperations::CreateMaskedImage(image, *mask), 0, 0); + + // Draw the stroke. + // Draw the button border with a slight alpha. + static const SkAlpha kGlassFrameOverlayAlpha = 178; + static const SkAlpha kOpaqueFrameOverlayAlpha = 230; + const SkAlpha alpha = GetWidget()->ShouldWindowContentsBeTransparent() ? + kGlassFrameOverlayAlpha : kOpaqueFrameOverlayAlpha; + const int overlay_id = pressed ? IDR_NEWTAB_BUTTON_P : IDR_NEWTAB_BUTTON; + canvas->DrawImageInt(*GetThemeProvider()->GetImageSkiaNamed(overlay_id), 0, 0, + alpha); +} + bool NewTabButton::GetHitTestMask(gfx::Path* mask) const { DCHECK(mask); @@ -370,53 +394,23 @@ return true; } -bool NewTabButton::ShouldWindowContentsBeTransparent() const { - return GetWidget() && - GetWidget()->GetTopLevelWidget()->ShouldWindowContentsBeTransparent(); -} - -gfx::ImageSkia NewTabButton::GetBackgroundImage( - views::CustomButton::ButtonState state, - float scale) const { - int background_id = 0; - if (ShouldWindowContentsBeTransparent()) { - background_id = IDR_THEME_TAB_BACKGROUND_V; - } else if (tab_strip_->controller()->IsIncognito()) { - background_id = IDR_THEME_TAB_BACKGROUND_INCOGNITO; - } else { - background_id = IDR_THEME_TAB_BACKGROUND; +void NewTabButton::PaintFill(bool pressed, + double hover_value, + float scale, + gfx::Canvas* canvas) const { + int bg_id = IDR_THEME_TAB_BACKGROUND_V; + if (!GetWidget()->ShouldWindowContentsBeTransparent()) { + bg_id = tab_strip_->controller()->IsIncognito() ? + IDR_THEME_TAB_BACKGROUND_INCOGNITO : IDR_THEME_TAB_BACKGROUND; } - int alpha = 0; - switch (state) { - case views::CustomButton::STATE_NORMAL: - case views::CustomButton::STATE_HOVERED: - alpha = ShouldWindowContentsBeTransparent() ? kGlassFrameInactiveTabAlpha - : 255; - break; - case views::CustomButton::STATE_PRESSED: - alpha = 145; - break; - default: - NOTREACHED(); - break; - } - - gfx::ImageSkia* mask = - GetThemeProvider()->GetImageSkiaNamed(IDR_NEWTAB_BUTTON_MASK); - int height = mask->height(); - int width = mask->width(); - // The canvas and mask has to use the same scale factor. - if (!mask->HasRepresentation(scale)) - scale = ui::GetScaleForScaleFactor(ui::SCALE_FACTOR_100P); - - gfx::Canvas canvas(gfx::Size(width, height), scale, false); - - // For custom images the background starts at the top of the tab strip. - // Otherwise the background starts at the top of the frame. - gfx::ImageSkia* background = - GetThemeProvider()->GetImageSkiaNamed(background_id); - int offset_y = GetThemeProvider()->HasCustomImage(background_id) ? + // Draw the fill background image. + const gfx::Size size(GetNewTabButtonSize()); + ui::ThemeProvider* theme_provider = GetThemeProvider(); + gfx::ImageSkia* background = theme_provider->GetImageSkiaNamed(bg_id); + // For custom tab backgrounds the background starts at the top of the tab + // strip. Otherwise the background starts at the top of the frame. + const int offset_y = theme_provider->HasCustomImage(bg_id) ? 0 : background_offset_.y(); // The new tab background is mirrored in RTL mode, but the theme background @@ -425,61 +419,34 @@ int x = GetMirroredX() + background_offset_.x(); if (base::i18n::IsRTL()) { x_scale = -1.0f; - // Offset by |width| such that the same region is painted as if there was no - // flip. - x += width; + // Offset by |width| such that the same region is painted as if there was + // no flip. + x += size.width(); } - canvas.TileImageInt(*background, x, - TabStrip::kNewTabButtonVerticalOffset + offset_y, - x_scale, 1.0f, 0, 0, width, height); + canvas->TileImageInt(*background, x, + TabStrip::kNewTabButtonVerticalOffset + offset_y, + x_scale, 1.0f, 0, 0, size.width(), size.height()); + // Adjust the alpha of the fill to match that of inactive tabs (except for + // pressed buttons, which get a different value). + static const SkAlpha kPressedAlpha = 145; + const SkAlpha alpha = + pressed ? kPressedAlpha : tab_strip_->GetInactiveAlpha(true); if (alpha != 255) { SkPaint paint; - paint.setColor(SkColorSetARGB(alpha, 255, 255, 255)); + paint.setAlpha(alpha); paint.setXfermodeMode(SkXfermode::kDstIn_Mode); paint.setStyle(SkPaint::kFill_Style); - canvas.DrawRect(gfx::Rect(0, 0, width, height), paint); + canvas->DrawRect(gfx::Rect(size), paint); } // White highlight on hover. - if (state == views::CustomButton::STATE_HOVERED) - canvas.FillRect(GetLocalBounds(), SkColorSetARGB(64, 255, 255, 255)); - - return gfx::ImageSkiaOperations::CreateMaskedImage( - gfx::ImageSkia(canvas.ExtractImageRep()), *mask); -} - -gfx::ImageSkia NewTabButton::GetImageForState( - views::CustomButton::ButtonState state, - float scale) const { - const int overlay_id = state == views::CustomButton::STATE_PRESSED ? - IDR_NEWTAB_BUTTON_P : IDR_NEWTAB_BUTTON; - gfx::ImageSkia* overlay = GetThemeProvider()->GetImageSkiaNamed(overlay_id); - - gfx::Canvas canvas( - gfx::Size(overlay->width(), overlay->height()), - scale, - false); - canvas.DrawImageInt(GetBackgroundImage(state, scale), 0, 0); - - // Draw the button border with a slight alpha. - const uint8_t kGlassFrameOverlayAlpha = 178; - const uint8_t kOpaqueFrameOverlayAlpha = 230; - uint8_t alpha = ShouldWindowContentsBeTransparent() - ? kGlassFrameOverlayAlpha - : kOpaqueFrameOverlayAlpha; - canvas.DrawImageInt(*overlay, 0, 0, alpha); - - return gfx::ImageSkia(canvas.ExtractImageRep()); -} - -gfx::ImageSkia NewTabButton::GetImageForScale(float scale) const { - if (!hover_animation_->is_animating()) - return GetImageForState(state(), scale); - return gfx::ImageSkiaOperations::CreateBlendedImage( - GetImageForState(views::CustomButton::STATE_NORMAL, scale), - GetImageForState(views::CustomButton::STATE_HOVERED, scale), - hover_animation_->GetCurrentValue()); + if (hover_value) { + const int alpha = + gfx::Tween::LinearIntValueBetween(hover_value, 0x00, 0x40); + canvas->FillRect(GetLocalBounds(), + SkColorSetA(SK_ColorWHITE, static_cast<SkAlpha>(alpha))); + } } /////////////////////////////////////////////////////////////////////////////// @@ -960,6 +927,23 @@ immersive_style_ = enable; } +SkAlpha TabStrip::GetInactiveAlpha(bool for_new_tab_button) const { + static const SkAlpha kInactiveTabAlphaAsh = 230; + static const SkAlpha kInactiveTabAlphaGlass = 200; + static const SkAlpha kInactiveTabAlphaOpaque = 255; + static const float kMultiSelectionMultiplier = 0.75; + + const chrome::HostDesktopType host_desktop_type = + chrome::GetHostDesktopTypeForNativeView(GetWidget()->GetNativeView()); + if (host_desktop_type == chrome::HOST_DESKTOP_TYPE_ASH) + return kInactiveTabAlphaAsh; + if (!GetWidget()->ShouldWindowContentsBeTransparent()) + return kInactiveTabAlphaOpaque; + SkAlpha base_alpha = kInactiveTabAlphaGlass; + return (for_new_tab_button || (GetSelectionModel().size() <= 1)) ? + base_alpha : static_cast<SkAlpha>(kMultiSelectionMultiplier * base_alpha); +} + bool TabStrip::IsAnimating() const { return bounds_animator_.IsAnimating(); } @@ -979,7 +963,7 @@ drop_info_->file_supported = supported; } -const ui::ListSelectionModel& TabStrip::GetSelectionModel() { +const ui::ListSelectionModel& TabStrip::GetSelectionModel() const { return controller_->GetSelectionModel(); } @@ -1255,29 +1239,24 @@ // The view order doesn't match the paint order (tabs_ contains the tab // ordering). Additionally we need to paint the tabs that are closing in // |tabs_closing_map_|. + bool is_dragging = false; Tab* active_tab = NULL; Tabs tabs_dragging; Tabs selected_tabs; - int selected_tab_count = 0; - bool is_dragging = false; - int active_tab_index = -1; - - const chrome::HostDesktopType host_desktop_type = - chrome::GetHostDesktopTypeForNativeView(GetWidget()->GetNativeView()); - const uint8_t inactive_tab_alpha = - (host_desktop_type == chrome::HOST_DESKTOP_TYPE_ASH) - ? kInactiveTabAndNewTabButtonAlphaAsh - : kInactiveTabAndNewTabButtonAlpha; { + const chrome::HostDesktopType host_desktop_type = + chrome::GetHostDesktopTypeForNativeView(GetWidget()->GetNativeView()); + const uint8_t inactive_tab_alpha = + (host_desktop_type == chrome::HOST_DESKTOP_TYPE_ASH) ? + GetInactiveAlpha(false) : 255; ui::CompositingRecorder opacity_recorder(context, inactive_tab_alpha); PaintClosingTabs(tab_count(), context); + int active_tab_index = -1; for (int i = tab_count() - 1; i >= 0; --i) { Tab* tab = tab_at(i); - if (tab->IsSelected()) - selected_tab_count++; if (tab->dragging() && !stacked_layout_) { is_dragging = true; if (tab->IsActive()) { @@ -1320,10 +1299,8 @@ SkPaint paint; // If there are multiple tabs selected, fade non-selected tabs more to make // the selected tabs more noticable. - uint8_t alpha = selected_tab_count > 1 - ? kGlassFrameInactiveTabAlphaMultiSelection - : kGlassFrameInactiveTabAlpha; - paint.setColor(SkColorSetARGB(alpha, 255, 255, 255)); + uint8_t alpha = GetInactiveAlpha(false); + paint.setColor(SkColorSetA(SK_ColorWHITE, alpha)); paint.setXfermodeMode(SkXfermode::kDstIn_Mode); paint.setStyle(SkPaint::kFill_Style); @@ -1348,10 +1325,7 @@ active_tab->Paint(context); // Paint the New Tab button. - { - ui::CompositingRecorder opacity_recorder(context, inactive_tab_alpha); - newtab_button_->Paint(context); - } + newtab_button_->Paint(context); // And the dragged tabs. for (size_t i = 0; i < tabs_dragging.size(); ++i) @@ -1507,9 +1481,9 @@ set_id(VIEW_ID_TAB_STRIP); // So we get enter/exit on children to switch stacked layout on and off. set_notify_enter_exit_on_child(true); - newtab_button_bounds_.SetRect( - 0, 0, GetLayoutConstant(NEW_TAB_BUTTON_WIDTH), - kNewTabButtonHeight + kNewTabButtonVerticalOffset); + + newtab_button_bounds_.set_size(GetNewTabButtonSize()); + newtab_button_bounds_.Inset(0, 0, 0, -kNewTabButtonVerticalOffset); newtab_button_ = new NewTabButton(this, this); newtab_button_->SetTooltipText( l10n_util::GetStringUTF16(IDS_TOOLTIP_NEW_TAB));
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h index f682871..4f62593 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.h +++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -187,6 +187,12 @@ // Sets a painting style with miniature "tab indicator" rectangles at the top. void SetImmersiveStyle(bool enable); + // Returns the alpha that inactive tabs and the new tab button should use to + // blend against the frame background. Inactive tabs and the new tab button + // differ in whether they change alpha when tab multiselection is occurring; + // |for_new_tab_button| toggles between the two calculations. + SkAlpha GetInactiveAlpha(bool for_new_tab_button) const; + // Returns true if Tabs in this TabStrip are currently changing size or // position. bool IsAnimating() const; @@ -199,7 +205,7 @@ void FileSupported(const GURL& url, bool supported); // TabController overrides: - const ui::ListSelectionModel& GetSelectionModel() override; + const ui::ListSelectionModel& GetSelectionModel() const override; bool SupportsMultipleSelection() override; bool ShouldHideCloseButtonForInactiveTabs() override; void SelectTab(Tab* tab) override;
diff --git a/chrome/browser/ui/views/tabs/tab_strip_controller.h b/chrome/browser/ui/views/tabs/tab_strip_controller.h index f959bd7e..d945916 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/tab_strip_controller.h
@@ -28,7 +28,7 @@ virtual ~TabStripController() {} // Returns the selection model of the tabstrip. - virtual const ui::ListSelectionModel& GetSelectionModel() = 0; + virtual const ui::ListSelectionModel& GetSelectionModel() const = 0; // Returns the number of tabs in the model. virtual int GetCount() const = 0;
diff --git a/chrome/browser/ui/views/tabs/tab_unittest.cc b/chrome/browser/ui/views/tabs/tab_unittest.cc index 5c67ac25..621fbca 100644 --- a/chrome/browser/ui/views/tabs/tab_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_unittest.cc
@@ -27,7 +27,7 @@ void set_immersive_style(bool value) { immersive_style_ = value; } void set_active_tab(bool value) { active_tab_ = value; } - const ui::ListSelectionModel& GetSelectionModel() override { + const ui::ListSelectionModel& GetSelectionModel() const override { return selection_model_; } bool SupportsMultipleSelection() override { return false; }
diff --git a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc index 260b2f6..932d7a9 100644 --- a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc +++ b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc
@@ -10,12 +10,13 @@ #include "base/strings/string_number_conversions.h" #include "base/values.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_adapter_client.h" -#include "chromeos/dbus/fake_bluetooth_device_client.h" #include "chromeos/dbus/fake_cras_audio_client.h" #include "chromeos/dbus/fake_power_manager_client.h" #include "content/public/browser/web_ui.h" #include "device/bluetooth/bluetooth_device_chromeos.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_device_client.h" namespace { @@ -63,7 +64,7 @@ namespace chromeos { class DeviceEmulatorMessageHandler::BluetoothObserver - : public BluetoothDeviceClient::Observer { + : public bluez::BluetoothDeviceClient::Observer { public: explicit BluetoothObserver(DeviceEmulatorMessageHandler* owner) : owner_(owner) { @@ -179,8 +180,8 @@ DeviceEmulatorMessageHandler::DeviceEmulatorMessageHandler() : fake_bluetooth_device_client_( - static_cast<chromeos::FakeBluetoothDeviceClient*>( - chromeos::DBusThreadManager::Get() + static_cast<bluez::FakeBluetoothDeviceClient*>( + bluez::BluezDBusManager::Get() ->GetBluetoothDeviceClient())), fake_cras_audio_client_(static_cast<chromeos::FakeCrasAudioClient*>( chromeos::DBusThreadManager::Get() @@ -208,7 +209,7 @@ std::string path; CHECK(args->GetString(0, &path)); fake_bluetooth_device_client_->RemoveDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), dbus::ObjectPath(path)); } @@ -223,7 +224,7 @@ // the main adapter. std::vector<dbus::ObjectPath> paths = fake_bluetooth_device_client_->GetDevicesForAdapter( - dbus::ObjectPath(chromeos::FakeBluetoothAdapterClient::kAdapterPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath)); base::ListValue devices; // Get each device's properties. @@ -237,21 +238,21 @@ base::ListValue pairing_method_options; pairing_method_options.AppendString( - FakeBluetoothDeviceClient::kPairingMethodNone); + bluez::FakeBluetoothDeviceClient::kPairingMethodNone); pairing_method_options.AppendString( - FakeBluetoothDeviceClient::kPairingMethodPinCode); + bluez::FakeBluetoothDeviceClient::kPairingMethodPinCode); pairing_method_options.AppendString( - FakeBluetoothDeviceClient::kPairingMethodPassKey); + bluez::FakeBluetoothDeviceClient::kPairingMethodPassKey); base::ListValue pairing_action_options; pairing_action_options.AppendString( - FakeBluetoothDeviceClient::kPairingActionDisplay); + bluez::FakeBluetoothDeviceClient::kPairingActionDisplay); pairing_action_options.AppendString( - FakeBluetoothDeviceClient::kPairingActionRequest); + bluez::FakeBluetoothDeviceClient::kPairingActionRequest); pairing_action_options.AppendString( - FakeBluetoothDeviceClient::kPairingActionConfirmation); + bluez::FakeBluetoothDeviceClient::kPairingActionConfirmation); pairing_action_options.AppendString( - FakeBluetoothDeviceClient::kPairingActionFail); + bluez::FakeBluetoothDeviceClient::kPairingActionFail); // Send the list of devices to the view. web_ui()->CallJavascriptFunction(kUpdateBluetoothInfoJSCallback, @@ -263,7 +264,7 @@ const base::ListValue* args) { // Create the device if it does not already exist. std::string path = CreateBluetoothDeviceFromListValue(args); - chromeos::FakeBluetoothDeviceClient::Properties* props = + bluez::FakeBluetoothDeviceClient::Properties* props = fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(path)); // Try to pair the device with the main adapter. The device is identified @@ -442,7 +443,7 @@ std::string DeviceEmulatorMessageHandler::CreateBluetoothDeviceFromListValue( const base::ListValue* args) { const base::DictionaryValue* device_dict = nullptr; - FakeBluetoothDeviceClient::IncomingDeviceProperties props; + bluez::FakeBluetoothDeviceClient::IncomingDeviceProperties props; CHECK(args->GetDictionary(0, &device_dict)); CHECK(device_dict->GetString("path", &props.device_path)); @@ -459,8 +460,7 @@ // Create the device and store it in the FakeBluetoothDeviceClient's observed // list of devices. fake_bluetooth_device_client_->CreateDeviceWithProperties( - dbus::ObjectPath(chromeos::FakeBluetoothAdapterClient::kAdapterPath), - props); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), props); return props.device_path; } @@ -468,11 +468,11 @@ scoped_ptr<base::DictionaryValue> DeviceEmulatorMessageHandler::GetDeviceInfo( const dbus::ObjectPath& object_path) { // Get the device's properties. - chromeos::FakeBluetoothDeviceClient::Properties* props = + bluez::FakeBluetoothDeviceClient::Properties* props = fake_bluetooth_device_client_->GetProperties(object_path); scoped_ptr<base::DictionaryValue> device(new base::DictionaryValue()); scoped_ptr<base::ListValue> uuids(new base::ListValue); - chromeos::FakeBluetoothDeviceClient::SimulatedPairingOptions* options = + bluez::FakeBluetoothDeviceClient::SimulatedPairingOptions* options = fake_bluetooth_device_client_->GetPairingOptions(object_path); device->SetString("path", object_path.value());
diff --git a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.h b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.h index 840111bd..882af77 100644 --- a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.h +++ b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.h
@@ -17,9 +17,12 @@ class ObjectPath; } // namespace dbus +namespace bluez { +class FakeBluetoothDeviceClient; +} + namespace chromeos { -class FakeBluetoothDeviceClient; class FakeCrasAudioClient; class FakePowerManagerClient; @@ -99,7 +102,7 @@ scoped_ptr<base::DictionaryValue> GetDeviceInfo( const dbus::ObjectPath& object_path); - FakeBluetoothDeviceClient* fake_bluetooth_device_client_; + bluez::FakeBluetoothDeviceClient* fake_bluetooth_device_client_; scoped_ptr<BluetoothObserver> bluetooth_observer_; FakeCrasAudioClient* fake_cras_audio_client_;
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc index bf2598e..ea7011d 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -139,6 +139,10 @@ input_methods->insert(input_methods->begin(), input_method); } +bool IsOnline(NetworkPortalDetector::CaptivePortalStatus status) { + return status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE; +} + } // namespace GaiaContext::GaiaContext() {} @@ -347,6 +351,8 @@ AddCallback("toggleEasyBootstrap", &GaiaScreenHandler::HandleToggleEasyBootstrap); AddCallback("identifierEntered", &GaiaScreenHandler::HandleIdentifierEntered); + AddCallback("updateOfflineLogin", + &GaiaScreenHandler::set_offline_login_is_active); } OobeUI::Screen GaiaScreenHandler::GetCurrentScreen() const { @@ -363,13 +369,15 @@ VLOG(1) << "OnPortalDetectionCompleted " << NetworkPortalDetector::CaptivePortalStatusString(state.status); - const NetworkPortalDetector::CaptivePortalStatus status = state.status; - if (status == captive_portal_status_ || + const NetworkPortalDetector::CaptivePortalStatus previous_status = + captive_portal_status_; + captive_portal_status_ = state.status; + if (offline_login_is_active() || + IsOnline(captive_portal_status_) == IsOnline(previous_status) || disable_restrictive_proxy_check_for_test_ || GetCurrentScreen() != OobeUI::SCREEN_GAIA_SIGNIN) return; - captive_portal_status_ = status; LoadAuthExtension(true /* force */, false /* offline */); } @@ -874,13 +882,8 @@ } bool GaiaScreenHandler::IsRestrictiveProxy() const { - if (disable_restrictive_proxy_check_for_test_) - return false; - - return captive_portal_status_ == - NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL || - captive_portal_status_ == - NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE; + return !disable_restrictive_proxy_check_for_test_ && + !IsOnline(captive_portal_status_); } void GaiaScreenHandler::DisableRestrictiveProxyCheckForTest() {
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h index d37fa1a..2fcad06 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
@@ -225,6 +225,11 @@ // into BaseScreenHandler. OobeUI::Screen GetCurrentScreen() const; + bool offline_login_is_active() const { return offline_login_is_active_; } + void set_offline_login_is_active(bool offline_login_is_active) { + offline_login_is_active_ = offline_login_is_active; + } + // Current state of Gaia frame. FrameState frame_state_ = FRAME_STATE_UNKNOWN; @@ -278,7 +283,7 @@ // True if proxy doesn't allow access to google.com/generate_204. NetworkPortalDetector::CaptivePortalStatus captive_portal_status_ = - NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN; + NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE; scoped_ptr<NetworkPortalDetector> network_portal_detector_; bool disable_restrictive_proxy_check_for_test_ = false; @@ -289,6 +294,9 @@ // signin_screen_handler directly. SigninScreenHandler* signin_screen_handler_ = nullptr; + // True if offline GAIA is active. + bool offline_login_is_active_ = false; + base::WeakPtrFactory<GaiaScreenHandler> weak_factory_; DISALLOW_COPY_AND_ASSIGN(GaiaScreenHandler);
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc index 3e4f6e6..1f05411 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -492,8 +492,6 @@ &SigninScreenHandler::HandleUnlockOnLoginSuccess); AddCallback("showLoadingTimeoutError", &SigninScreenHandler::HandleShowLoadingTimeoutError); - AddCallback("updateOfflineLogin", - &SigninScreenHandler::HandleUpdateOfflineLogin); AddCallback("focusPod", &SigninScreenHandler::HandleFocusPod); AddCallback("getPublicSessionKeyboardLayouts", &SigninScreenHandler::HandleGetPublicSessionKeyboardLayouts); @@ -685,8 +683,10 @@ const bool is_gaia_error = FrameError() != net::OK && FrameError() != net::ERR_NETWORK_CHANGED; const bool is_gaia_signin = IsGaiaVisible() || IsGaiaHiddenByError(); + const bool offline_login_active = + gaia_screen_handler_->offline_login_is_active(); const bool error_screen_should_overlay = - !offline_login_active_ && IsGaiaVisible(); + !offline_login_active && IsGaiaVisible(); const bool from_not_online_to_online_transition = is_online && last_network_state_ != NetworkStateInformer::ONLINE; last_network_state_ = state; @@ -706,7 +706,7 @@ } // Use the online login page if the user has not used the machine for awhile. - if (offline_login_active_) + if (offline_login_active) gaia_screen_handler_->MonitorOfflineIdle(is_online); // Reload frame if network state is changed from {!ONLINE} -> ONLINE state. @@ -742,7 +742,7 @@ } if ((!is_online || is_gaia_loading_timeout || is_gaia_error) && - !offline_login_active_) { + !offline_login_active) { SetupAndShowOfflineMessage(state, reason); } else { HideOfflineMessage(state, reason); @@ -1235,10 +1235,6 @@ UpdateState(NetworkError::ERROR_REASON_LOADING_TIMEOUT); } -void SigninScreenHandler::HandleUpdateOfflineLogin(bool offline_login_active) { - offline_login_active_ = offline_login_active; -} - void SigninScreenHandler::HandleFocusPod(const std::string& user_id) { SetUserInputMethod(user_id, ime_state_.get()); WallpaperManager::Get()->SetUserWallpaperDelayed(user_id);
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h index bfe3b13..86ff5797 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -350,7 +350,6 @@ void HandleUnlockOnLoginSuccess(); void HandleLoginScreenUpdate(); void HandleShowLoadingTimeoutError(); - void HandleUpdateOfflineLogin(bool offline_login_active); void HandleShowSupervisedUserCreationScreen(); void HandleFocusPod(const std::string& user_id); void HandleHardlockPod(const std::string& user_id); @@ -445,7 +444,6 @@ NetworkErrorModel* network_error_model_; CoreOobeActor* core_oobe_actor_; - bool offline_login_active_ = false; NetworkStateInformer::State last_network_state_ = NetworkStateInformer::UNKNOWN;
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc index 5422199..cb5719e 100644 --- a/chrome/browser/ui/webui/extensions/extensions_ui.cc +++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -63,6 +63,8 @@ source->AddResourcePath("item.css", IDR_MD_EXTENSIONS_ITEM_CSS); source->AddResourcePath("item.html", IDR_MD_EXTENSIONS_ITEM_HTML); source->AddResourcePath("item.js", IDR_MD_EXTENSIONS_ITEM_JS); + source->AddResourcePath("service.html", IDR_MD_EXTENSIONS_SERVICE_HTML); + source->AddResourcePath("service.js", IDR_MD_EXTENSIONS_SERVICE_JS); source->AddResourcePath("sidebar.css", IDR_MD_EXTENSIONS_SIDEBAR_CSS); source->AddResourcePath("sidebar.html", IDR_MD_EXTENSIONS_SIDEBAR_HTML); source->AddResourcePath("sidebar.js", IDR_MD_EXTENSIONS_SIDEBAR_JS);
diff --git a/chrome/browser/ui/webui/gcm_internals_ui.cc b/chrome/browser/ui/webui/gcm_internals_ui.cc index 490d986..79e45e8 100644 --- a/chrome/browser/ui/webui/gcm_internals_ui.cc +++ b/chrome/browser/ui/webui/gcm_internals_ui.cc
@@ -15,12 +15,12 @@ #include "base/strings/stringprintf.h" #include "base/values.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/services/gcm/gcm_profile_service.h" #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" #include "chrome/common/url_constants.h" #include "components/gcm_driver/gcm_client.h" #include "components/gcm_driver/gcm_driver.h" #include "components/gcm_driver/gcm_internals_constants.h" +#include "components/gcm_driver/gcm_profile_service.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_controller.h" #include "content/public/browser/web_ui_data_source.h" @@ -155,8 +155,9 @@ device_info->SetBoolean(gcm_driver::kProfileServiceCreated, profile_service != NULL); - device_info->SetBoolean(gcm_driver::kGcmEnabled, - gcm::GCMProfileService::IsGCMEnabled(profile)); + device_info->SetBoolean( + gcm_driver::kGcmEnabled, + gcm::GCMProfileService::IsGCMEnabled(profile->GetPrefs())); if (stats) { results.SetBoolean(gcm_driver::kIsRecording, stats->is_recording); device_info->SetBoolean(gcm_driver::kGcmClientCreated,
diff --git a/chrome/browser/ui/webui/options/autofill_options_handler.h b/chrome/browser/ui/webui/options/autofill_options_handler.h index 9db2feb..079318c 100644 --- a/chrome/browser/ui/webui/options/autofill_options_handler.h +++ b/chrome/browser/ui/webui/options/autofill_options_handler.h
@@ -9,6 +9,7 @@ #include "base/compiler_specific.h" #include "base/gtest_prod_util.h" +#include "base/scoped_observer.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/ui/webui/options/options_ui.h" #include "components/autofill/core/browser/personal_data_manager_observer.h"
diff --git a/chrome/browser/ui/webui/options/clear_browser_data_handler.cc b/chrome/browser/ui/webui/options/clear_browser_data_handler.cc index 2c2dac5..d9433b94 100644 --- a/chrome/browser/ui/webui/options/clear_browser_data_handler.cc +++ b/chrome/browser/ui/webui/options/clear_browser_data_handler.cc
@@ -12,6 +12,7 @@ #include "base/metrics/sparse_histogram.h" #include "base/prefs/pref_service.h" #include "base/strings/string16.h" +#include "base/strings/string_number_conversions.h" #include "base/values.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/browser_process.h" @@ -34,6 +35,7 @@ #include "content/public/browser/web_ui.h" #include "ui/base/accelerators/accelerator.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/base/text/bytes_formatting.h" #include "ui/events/keycodes/keyboard_codes.h" namespace { @@ -74,11 +76,9 @@ base::Unretained(this))); if (AreCountersEnabled()) { - AddCounter(make_scoped_ptr(new PasswordsCounter()), - IDS_DEL_PASSWORDS_COUNTER); - AddCounter(make_scoped_ptr(new HistoryCounter()), - IDS_DEL_BROWSING_HISTORY_COUNTER); - AddCounter(make_scoped_ptr(new CacheCounter()), IDS_DEL_CACHE_COUNTER); + AddCounter(make_scoped_ptr(new PasswordsCounter())); + AddCounter(make_scoped_ptr(new HistoryCounter())); + AddCounter(make_scoped_ptr(new CacheCounter())); sync_service_ = ProfileSyncServiceFactory::GetForProfile(Profile::FromWebUI(web_ui())); @@ -308,27 +308,73 @@ } void ClearBrowserDataHandler::AddCounter( - scoped_ptr<BrowsingDataCounter> counter, int text_grd_id) { + scoped_ptr<BrowsingDataCounter> counter) { DCHECK(AreCountersEnabled()); counter->Init( Profile::FromWebUI(web_ui()), base::Bind(&ClearBrowserDataHandler::UpdateCounterText, - base::Unretained(this), - counter->GetPrefName(), - text_grd_id)); + base::Unretained(this))); counters_.push_back(counter.Pass()); } void ClearBrowserDataHandler::UpdateCounterText( - const std::string& pref_name, - int text_grd_id, - bool finished, - BrowsingDataCounter::ResultInt count) { + scoped_ptr<BrowsingDataCounter::Result> result) { DCHECK(AreCountersEnabled()); - base::string16 text = finished - ? l10n_util::GetPluralStringFUTF16(text_grd_id, count) - : l10n_util::GetStringUTF16(IDS_CLEAR_BROWSING_DATA_CALCULATING); + base::string16 text; + std::string pref_name = result->source()->GetPrefName(); + + if (!result->Finished()) { + // The counter is still counting. + text = l10n_util::GetStringUTF16(IDS_CLEAR_BROWSING_DATA_CALCULATING); + + } else if (pref_name == prefs::kDeletePasswords) { + // Passwords counter. + BrowsingDataCounter::ResultInt passwords_count = + static_cast<BrowsingDataCounter::FinishedResult*>( + result.get())->Value(); + text = l10n_util::GetPluralStringFUTF16( + IDS_DEL_PASSWORDS_COUNTER, passwords_count); + + } else if (pref_name == prefs::kDeleteCache) { + // Cache counter. + BrowsingDataCounter::ResultInt cache_size_bytes = + static_cast<BrowsingDataCounter::FinishedResult*>( + result.get())->Value(); + + PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs(); + BrowsingDataRemover::TimePeriod time_period = + static_cast<BrowsingDataRemover::TimePeriod>( + prefs->GetInteger(prefs::kDeleteTimePeriod)); + + // Three cases: Nonzero result for the entire cache, nonzero result for + // a subset of cache (i.e. a finite time interval), and almost zero (< 1MB). + static const int kBytesInAMegabyte = 1024 * 1024; + if (cache_size_bytes >= kBytesInAMegabyte) { + base::string16 formatted_size = ui::FormatBytes(cache_size_bytes); + text = time_period == BrowsingDataRemover::EVERYTHING + ? formatted_size + : l10n_util::GetStringFUTF16(IDS_DEL_CACHE_COUNTER_UPPER_ESTIMATE, + formatted_size); + } else { + base::string16 formatted_size = ui::FormatBytes(kBytesInAMegabyte); + text = l10n_util::GetStringFUTF16(IDS_DEL_CACHE_COUNTER_UPPER_ESTIMATE, + formatted_size); + } + + } else if (pref_name == prefs::kDeleteBrowsingHistory) { + // History counter. + HistoryCounter::HistoryResult* history_result = + static_cast<HistoryCounter::HistoryResult*>(result.get()); + BrowsingDataCounter::ResultInt local_item_count = history_result->Value(); + bool has_synced_visits = history_result->has_synced_visits(); + + text = has_synced_visits + ? l10n_util::GetPluralStringFUTF16( + IDS_DEL_BROWSING_HISTORY_COUNTER_SYNCED, local_item_count) + : l10n_util::GetPluralStringFUTF16( + IDS_DEL_BROWSING_HISTORY_COUNTER, local_item_count); + } web_ui()->CallJavascriptFunction( "ClearBrowserDataOverlay.updateCounter",
diff --git a/chrome/browser/ui/webui/options/clear_browser_data_handler.h b/chrome/browser/ui/webui/options/clear_browser_data_handler.h index 6737cb2..3f08e32 100644 --- a/chrome/browser/ui/webui/options/clear_browser_data_handler.h +++ b/chrome/browser/ui/webui/options/clear_browser_data_handler.h
@@ -47,18 +47,11 @@ // Updates UI when the pref to allow clearing history changes. virtual void OnBrowsingHistoryPrefChanged(); - // Adds a |counter| for browsing data. Its output will be displayed - // in the dialog with the string |text_grd_id|. - void AddCounter(scoped_ptr<BrowsingDataCounter> counter, int text_grd_id); + // Adds a |counter| for browsing data. + void AddCounter(scoped_ptr<BrowsingDataCounter> counter); - // Updates the counter of the pref |pref_name| in the UI according - // to a callback from a |BrowsingDataCounter| that specifies whether - // the counting has |finished| and what the |count| is. The |count| will - // be substituted into the string with the ID |text_grd_id|. - void UpdateCounterText(const std::string& pref_name, - int text_grd_id, - bool finished, - BrowsingDataCounter::ResultInt count); + // Updates a counter in the UI according to the |result|. + void UpdateCounterText(scoped_ptr<BrowsingDataCounter::Result> result); // Implementation of SyncServiceObserver. Updates the support string at the // bottom of the dialog.
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc index 56d11484..58e43745 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -1298,11 +1298,13 @@ GetNumberFormatAndMeasurementSystem(&initial_settings); web_ui()->CallJavascriptFunction("setInitialSettings", initial_settings); + if (cmdline->HasSwitch(switches::kDisablePrintPreviewSimplify)) + return; + WebContents* initiator = GetInitiator(); - if (initiator && cmdline->HasSwitch(switches::kEnableDomDistiller) && - dom_distiller::url_utils::IsUrlDistillable( - initiator->GetLastCommittedURL())) { - web_ui()->CallJavascriptFunction("detectDistillablePage"); + if (initiator && dom_distiller::url_utils::IsUrlDistillable( + initiator->GetLastCommittedURL())) { + web_ui()->CallJavascriptFunction("allowDistillPage"); } }
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index ceb0fcf..7400c3e 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp
@@ -531,19 +531,20 @@ 'chrome_resources.gyp:chrome_strings', 'chrome_strings_grd', 'chrome_version_java', + 'content_setting_java', + 'content_settings_type_java', 'connection_security_levels_java', 'connectivity_check_result_java', 'document_tab_model_info_proto_java', 'infobar_action_type_java', - 'profile_account_management_metrics_java', - 'content_setting_java', - 'content_settings_type_java', 'most_visited_tile_type_java', 'page_info_connection_type_java', + 'profile_account_management_metrics_java', 'resource_id_java', - 'tab_load_status_java', 'shortcut_source_java', + 'tab_load_status_java', '../base/base.gyp:base', + '../build/android/java_google_api_keys.gyp:google_api_keys_java', '../chrome/android/chrome_apk.gyp:custom_tabs_service_aidl', '../components/components.gyp:autocomplete_match_type_java', '../components/components.gyp:bookmarks_java',
diff --git a/chrome/chrome_android_paks.gypi b/chrome/chrome_android_paks.gypi index 1ebd363..aa325740 100644 --- a/chrome/chrome_android_paks.gypi +++ b/chrome/chrome_android_paks.gypi
@@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. { + 'includes': ['../build/android/v8_external_startup_data_arch_suffix.gypi'], 'variables': { 'chrome_android_pak_output_folder': '<@(PRODUCT_DIR)/assets/<(package_name)', 'chrome_android_pak_input_resources': [ @@ -68,13 +69,9 @@ ], }], ['v8_use_external_startup_data==1', { - 'chrome_android_pak_input_resources': [ - '<(PRODUCT_DIR)/natives_blob.bin', - '<(PRODUCT_DIR)/snapshot_blob.bin', - ], 'chrome_android_pak_output_resources': [ - '<(chrome_android_pak_output_folder)/natives_blob.bin', - '<(chrome_android_pak_output_folder)/snapshot_blob.bin', + '<(chrome_android_pak_output_folder)/natives_blob_<(arch_suffix).bin', + '<(chrome_android_pak_output_folder)/snapshot_blob_<(arch_suffix).bin', ], }], ], @@ -93,6 +90,18 @@ '<@(chrome_android_pak_input_resources)', ], 'clear': 1, + 'conditions': [ + ['v8_use_external_startup_data==1', { + 'renaming_sources': [ + '<(PRODUCT_DIR)/snapshot_blob.bin', + '<(PRODUCT_DIR)/natives_blob.bin', + ], + 'renaming_destinations': [ + 'snapshot_blob_<(arch_suffix).bin', + 'natives_blob_<(arch_suffix).bin', + ], + }], + ], }, 'includes': ['../build/android/copy_ex.gypi'], },
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index b1922db9..d4b56567 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi
@@ -129,6 +129,8 @@ 'browser/android/feature_utilities.h', 'browser/android/feedback/connectivity_checker.cc', 'browser/android/feedback/connectivity_checker.h', + 'browser/android/feedback/screenshot_task.cc', + 'browser/android/feedback/screenshot_task.h', 'browser/android/find_in_page/find_in_page_bridge.cc', 'browser/android/find_in_page/find_in_page_bridge.h', 'browser/android/foreign_session_helper.cc', @@ -664,10 +666,10 @@ 'browser/native_window_notification_source.h', 'browser/net/predictor_tab_helper.cc', 'browser/net/predictor_tab_helper.h', - 'browser/page_load_metrics/page_load_metrics_initialize.cc', - 'browser/page_load_metrics/page_load_metrics_initialize.h', 'browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.cc', 'browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.h', + 'browser/page_load_metrics/page_load_metrics_initialize.cc', + 'browser/page_load_metrics/page_load_metrics_initialize.h', 'browser/performance_monitor/performance_monitor.cc', 'browser/performance_monitor/performance_monitor.h', 'browser/performance_monitor/process_metrics_history.cc', @@ -888,6 +890,8 @@ 'browser/net/spdyproxy/data_reduction_proxy_infobar_delegate_android.h', 'browser/password_manager/account_chooser_dialog_android.cc', 'browser/password_manager/account_chooser_dialog_android.h', + 'browser/password_manager/auto_signin_first_run_infobar_delegate.cc', + 'browser/password_manager/auto_signin_first_run_infobar_delegate.h', 'browser/password_manager/credential_android.cc', 'browser/password_manager/credential_android.h', 'browser/password_manager/generated_password_saved_infobar_delegate_android.cc', @@ -1788,6 +1792,7 @@ 'android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java', 'android/java/src/org/chromium/chrome/browser/favicon/LargeIconBridge.java', 'android/java/src/org/chromium/chrome/browser/feedback/ConnectivityChecker.java', + 'android/java/src/org/chromium/chrome/browser/feedback/ScreenshotTask.java', 'android/java/src/org/chromium/chrome/browser/findinpage/FindInPageBridge.java', 'android/java/src/org/chromium/chrome/browser/fullscreen/FullscreenInfoBarDelegate.java', 'android/java/src/org/chromium/chrome/browser/historyreport/HistoryReportJniBridge.java', @@ -1865,6 +1870,7 @@ 'android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java', 'android/java/src/org/chromium/chrome/browser/infobar/PermissionUpdateInfoBarDelegate.java', 'android/java/src/org/chromium/chrome/browser/infobar/SavePasswordInfoBar.java', + 'android/java/src/org/chromium/chrome/browser/infobar/AutoSigninFirstRunInfoBar.java', 'android/java/src/org/chromium/chrome/browser/invalidation/InvalidationServiceFactory.java', 'android/java/src/org/chromium/chrome/browser/metrics/LaunchMetrics.java', 'android/java/src/org/chromium/chrome/browser/ssl/SecurityStateModel.java', @@ -2064,8 +2070,6 @@ 'chrome_browser_password_manager_sources': [ 'browser/password_manager/chrome_password_manager_client.cc', 'browser/password_manager/chrome_password_manager_client.h', - 'browser/password_manager/password_manager_setting_migrator_service.cc', - 'browser/password_manager/password_manager_setting_migrator_service.h', 'browser/password_manager/password_manager_setting_migrator_service_factory.cc', 'browser/password_manager/password_manager_setting_migrator_service_factory.h', 'browser/password_manager/password_store_factory.cc', @@ -2085,9 +2089,9 @@ # Used on Mac and Android platforms. 'chrome_browser_password_manager_mac_android_sources': [ 'browser/password_manager/password_manager_infobar_delegate.cc', + 'browser/password_manager/password_manager_infobar_delegate.h', 'browser/password_manager/save_password_infobar_delegate.cc', 'browser/password_manager/save_password_infobar_delegate.h', - 'browser/password_manager/password_manager_infobar_delegate.h' ], 'chrome_browser_permissions_sources': [ 'browser/permissions/permission_context.cc', @@ -2096,8 +2100,6 @@ 'browser/permissions/permission_context_base.h', 'browser/permissions/permission_context_factory_base.cc', 'browser/permissions/permission_context_factory_base.h', - 'browser/permissions/permission_context_uma_util.cc', - 'browser/permissions/permission_context_uma_util.h', 'browser/permissions/permission_infobar_delegate.cc', 'browser/permissions/permission_infobar_delegate.h', 'browser/permissions/permission_manager.cc', @@ -2106,6 +2108,8 @@ 'browser/permissions/permission_manager_factory.h', 'browser/permissions/permission_request_id.cc', 'browser/permissions/permission_request_id.h', + 'browser/permissions/permission_uma_util.cc', + 'browser/permissions/permission_uma_util.h', 'browser/permissions/permission_update_infobar_delegate_android.cc', 'browser/permissions/permission_update_infobar_delegate_android.h', 'browser/permissions/permission_util.cc', @@ -2436,12 +2440,6 @@ 'chrome_browser_safe_browsing_basic_sources': [ 'browser/renderer_host/data_reduction_proxy_resource_throttle_android.cc', 'browser/renderer_host/data_reduction_proxy_resource_throttle_android.h', - 'browser/safe_browsing/threat_details.cc', - 'browser/safe_browsing/threat_details.h', - 'browser/safe_browsing/threat_details_cache.cc', - 'browser/safe_browsing/threat_details_cache.h', - 'browser/safe_browsing/threat_details_history.cc', - 'browser/safe_browsing/threat_details_history.h', 'browser/safe_browsing/ping_manager.cc', 'browser/safe_browsing/ping_manager.h', 'browser/safe_browsing/protocol_manager_helper.cc', @@ -2452,6 +2450,12 @@ 'browser/safe_browsing/safe_browsing_service.h', 'browser/safe_browsing/safe_browsing_util.cc', 'browser/safe_browsing/safe_browsing_util.h', + 'browser/safe_browsing/threat_details.cc', + 'browser/safe_browsing/threat_details.h', + 'browser/safe_browsing/threat_details_cache.cc', + 'browser/safe_browsing/threat_details_cache.h', + 'browser/safe_browsing/threat_details_history.cc', + 'browser/safe_browsing/threat_details_history.h', 'browser/safe_browsing/ui_manager.cc', 'browser/safe_browsing/ui_manager.h', ], @@ -2650,8 +2654,6 @@ 'browser/local_discovery/service_discovery_shared_client.h', ], 'chrome_browser_services_sources': [ - 'browser/services/gcm/gcm_profile_service.cc', - 'browser/services/gcm/gcm_profile_service.h', 'browser/services/gcm/gcm_profile_service_factory.cc', 'browser/services/gcm/gcm_profile_service_factory.h', 'browser/services/gcm/instance_id/instance_id_profile_service.cc', @@ -2900,12 +2902,6 @@ 'browser/sync/profile_sync_service_factory.h', 'browser/sync/sessions/notification_service_sessions_router.cc', 'browser/sync/sessions/notification_service_sessions_router.h', - 'browser/sync/sessions/page_revisit_broadcaster.cc', - 'browser/sync/sessions/page_revisit_broadcaster.h', - 'browser/sync/sessions/session_data_type_controller.cc', - 'browser/sync/sessions/session_data_type_controller.h', - 'browser/sync/sessions/sessions_sync_manager.cc', - 'browser/sync/sessions/sessions_sync_manager.h', 'browser/sync/supervised_user_signin_manager_wrapper.cc', 'browser/sync/supervised_user_signin_manager_wrapper.h', 'browser/sync/sync_startup_tracker.cc', @@ -3054,17 +3050,6 @@ 'browser/media/webrtc_rtp_dump_writer.cc', 'browser/media/webrtc_rtp_dump_writer.h', ], - 'chrome_browser_wifi_bootstrapping_sources': [ - 'browser/local_discovery/wifi/credential_getter_win.cc', - 'browser/local_discovery/wifi/credential_getter_win.h', - 'browser/local_discovery/wifi/wifi_manager.cc', - 'browser/local_discovery/wifi/wifi_manager.h', - ], - # Parts of wifi bootstrapping (above) used everywhere except chromeos. - 'chrome_browser_wifi_bootstrapping_win_mac_sources': [ - 'browser/local_discovery/wifi/wifi_manager_nonchromeos.cc', - 'browser/local_discovery/wifi/wifi_manager_nonchromeos.h', - ], }, 'targets': [ { @@ -3134,7 +3119,7 @@ '../components/components.gyp:ssl_errors', '../components/components.gyp:suggestions', '../components/components.gyp:signin_core_browser', - '../components/components.gyp:startup_metric_utils', + '../components/components.gyp:startup_metric_utils_browser', '../components/components.gyp:sync_bookmarks', '../components/components.gyp:sync_driver', '../components/components.gyp:sync_sessions', @@ -3875,16 +3860,6 @@ 'browser/autofill/validation_rules_storage_factory.h', ], }], - [ 'enable_wifi_bootstrapping==1', { - 'sources': [ '<@(chrome_browser_wifi_bootstrapping_sources)' ], - 'conditions' : [ - [ 'OS=="win" or OS=="mac"', { - 'sources': [ - '<@(chrome_browser_wifi_bootstrapping_win_mac_sources)', - ] - }] - ] - }], [ 'enable_basic_printing==1 or enable_print_preview==1', { 'dependencies': [ '../components/components.gyp:printing_browser',
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index 9fafe858..1c4feef 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi
@@ -455,6 +455,8 @@ 'browser/ui/android/context_menu_helper.h', 'browser/ui/android/infobars/app_banner_infobar_android.cc', 'browser/ui/android/infobars/app_banner_infobar_android.h', + 'browser/ui/android/infobars/auto_signin_first_run_infobar.cc', + 'browser/ui/android/infobars/auto_signin_first_run_infobar.h', 'browser/ui/android/infobars/confirm_infobar.cc', 'browser/ui/android/infobars/confirm_infobar.h', 'browser/ui/android/infobars/data_reduction_proxy_infobar.cc', @@ -478,8 +480,8 @@ 'browser/ui/android/omnibox/omnibox_view_util.cc', 'browser/ui/android/omnibox/omnibox_view_util.h', 'browser/ui/android/simple_message_box_android.cc', - 'browser/ui/android/snackbars/auto_signin_snackbar_controller.cc', - 'browser/ui/android/snackbars/auto_signin_snackbar_controller.h', + 'browser/ui/android/snackbars/auto_signin_prompt_controller.cc', + 'browser/ui/android/snackbars/auto_signin_prompt_controller.h', 'browser/ui/android/ssl_client_certificate_request.cc', 'browser/ui/android/ssl_client_certificate_request.h', 'browser/ui/android/tab_contents/chrome_web_contents_view_delegate_android.cc', @@ -2108,6 +2110,8 @@ 'browser/ui/views/autofill/save_card_bubble_views.h', 'browser/ui/views/autofill/tooltip_icon.cc', 'browser/ui/views/autofill/tooltip_icon.h', + 'browser/ui/views/bar_control_button.cc', + 'browser/ui/views/bar_control_button.h', 'browser/ui/views/bookmarks/bookmark_bar_instructions_view.cc', 'browser/ui/views/bookmarks/bookmark_bar_instructions_view.h', 'browser/ui/views/bookmarks/bookmark_bar_view.cc', @@ -2180,6 +2184,8 @@ 'browser/ui/views/frame/browser_command_handler_linux.h', 'browser/ui/views/frame/browser_frame.cc', 'browser/ui/views/frame/browser_frame.h', + 'browser/ui/views/frame/browser_frame_android.cc', + 'browser/ui/views/frame/browser_frame_android.h', 'browser/ui/views/frame/browser_frame_common_win.cc', 'browser/ui/views/frame/browser_frame_common_win.h', 'browser/ui/views/frame/browser_frame_mac.h', @@ -2217,6 +2223,7 @@ 'browser/ui/views/frame/native_browser_frame.h', 'browser/ui/views/frame/native_browser_frame_factory.cc', 'browser/ui/views/frame/native_browser_frame_factory.h', + 'browser/ui/views/frame/native_browser_frame_factory_android.cc', 'browser/ui/views/frame/native_browser_frame_factory_chromeos.cc', 'browser/ui/views/frame/native_browser_frame_factory_mac.mm', 'browser/ui/views/frame/system_menu_insertion_delegate_win.cc', @@ -2253,6 +2260,8 @@ 'browser/ui/views/layout_constants.h', 'browser/ui/views/load_complete_listener.cc', 'browser/ui/views/load_complete_listener.h', + 'browser/ui/views/location_bar/background_with_1_px_border.cc', + 'browser/ui/views/location_bar/background_with_1_px_border.h', 'browser/ui/views/location_bar/bubble_icon_view.cc', 'browser/ui/views/location_bar/bubble_icon_view.h', 'browser/ui/views/location_bar/content_setting_image_view.cc',
diff --git a/chrome/chrome_exe.gypi b/chrome/chrome_exe.gypi index 89fbe43..c841c1b 100644 --- a/chrome/chrome_exe.gypi +++ b/chrome/chrome_exe.gypi
@@ -67,8 +67,8 @@ 'app/chrome_watcher_client_win.h', 'app/chrome_watcher_command_line_win.cc', 'app/chrome_watcher_command_line_win.h', - 'app/client_util.cc', - 'app/client_util.h', + 'app/main_dll_loader_win.cc', + 'app/main_dll_loader_win.h', 'app/kasko_client.cc', 'app/kasko_client.h', 'app/signature_validator_win.cc', @@ -365,7 +365,7 @@ # "chrome" etc.; should we try to extract from there instead? ], 'dependencies': [ - '../components/components.gyp:startup_metric_utils', + '../components/components.gyp:startup_metric_utils_browser', 'chrome_resources.gyp:packed_extra_resources', 'chrome_resources.gyp:packed_resources', # Copy Flash Player files to PRODUCT_DIR if applicable. Let the .gyp @@ -409,7 +409,7 @@ 'chrome_process_finder', 'chrome_version_resources', 'installer_util', - 'image_pre_reader', + 'file_pre_reader', '../base/base.gyp:base', '../crypto/crypto.gyp:crypto', '../breakpad/breakpad.gyp:breakpad_handler', @@ -497,10 +497,6 @@ ], }, ], - }, { # 'OS!="win" - 'sources!': [ - 'app/client_util.cc', - ], }], ['OS=="win" and component=="shared_library"', { 'defines': ['COMPILE_CONTENT_STATICALLY'], @@ -512,11 +508,11 @@ ['OS=="win"', { 'targets': [ { - 'target_name': 'image_pre_reader', + 'target_name': 'file_pre_reader', 'type': 'static_library', 'sources': [ - 'app/image_pre_reader_win.cc', - 'app/image_pre_reader_win.h', + 'app/file_pre_reader_win.cc', + 'app/file_pre_reader_win.h', ], 'dependencies': [ '../base/base.gyp:base',
diff --git a/chrome/chrome_installer_util.gypi b/chrome/chrome_installer_util.gypi index f0928a44..710cee0e 100644 --- a/chrome/chrome_installer_util.gypi +++ b/chrome/chrome_installer_util.gypi
@@ -76,6 +76,8 @@ 'installer/util/legacy_firewall_manager_win.h', 'installer/util/master_preferences_constants.cc', 'installer/util/master_preferences_constants.h', + 'installer/util/module_util_win.cc', + 'installer/util/module_util_win.h', 'installer/util/move_tree_work_item.cc', 'installer/util/move_tree_work_item.h', 'installer/util/non_updating_app_registration_data.cc',
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi index ee1800f..cfca4bb 100644 --- a/chrome/chrome_renderer.gypi +++ b/chrome/chrome_renderer.gypi
@@ -251,7 +251,6 @@ '../components/components.gyp:network_hints_renderer', '../components/components.gyp:omnibox_common', '../components/components.gyp:error_page_renderer', - '../components/components.gyp:startup_metric_utils', '../components/components.gyp:page_load_metrics_renderer', '../components/components.gyp:password_manager_content_renderer', '../components/components.gyp:plugins_renderer',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 686876c..e134a8d9 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi
@@ -959,6 +959,7 @@ 'test/data/webui/async_gen.js', 'test/data/webui/certificate_viewer_dialog_test.js', 'test/data/webui/chrome_send_browsertest.js', + 'test/data/webui/extensions/cr_extensions_browsertest.js', 'test/data/webui/history_browsertest.js', 'test/data/webui/mock4js_browsertest.js', 'test/data/webui/net_internals/bandwidth_view.js', @@ -3180,6 +3181,30 @@ ['test_isolation_mode != "noop"', { 'targets': [ { + 'target_name': 'telemetry_chrome_test_base', + 'type': 'none', + 'dependencies': [ + '../content/content_shell_and_tests.gyp:telemetry_base', + ], + 'conditions': [ + ['OS=="linux" or OS=="mac"', { + 'dependencies': [ + '../breakpad/breakpad.gyp:dump_syms', + ], + }], + ['OS=="mac"', { + 'dependencies': [ + '../third_party/crashpad/crashpad/tools/tools.gyp:crashpad_database_util', + ], + }], + ['OS=="win"', { + 'dependencies': [ + 'chrome.gyp:crash_service', + ], + }], + ], + }, + { 'target_name': 'browser_tests_run', 'type': 'none', 'dependencies': [ @@ -3202,6 +3227,20 @@ ], }, { + 'target_name': 'telemetry_perf_unittests', + 'type': 'none', + 'dependencies': [ + 'chrome_run', + 'telemetry_chrome_test_base' + ], + 'includes': [ + '../build/isolate.gypi', + ], + 'sources': [ + 'telemetry_perf_unittests.isolate', + ], + }, + { 'target_name': 'telemetry_gpu_unittests', 'type': 'none', 'dependencies': [ @@ -3297,30 +3336,6 @@ }, }, { - 'target_name': 'telemetry_chrome_test_base', - 'type': 'none', - 'dependencies': [ - '../content/content_shell_and_tests.gyp:telemetry_base', - ], - 'conditions': [ - ['OS=="linux" or OS=="mac"', { - 'dependencies': [ - '../breakpad/breakpad.gyp:dump_syms', - ], - }], - ['OS=="mac"', { - 'dependencies': [ - '../third_party/crashpad/crashpad/tools/tools.gyp:crashpad_database_util', - ], - }], - ['OS=="win"', { - 'dependencies': [ - 'chrome.gyp:crash_service', - ], - }], - ], - }, - { # GN: //gpu:angle_unittests_run 'target_name': 'angle_unittests_run', 'type': 'none',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 1f179ff..4a710d0 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi
@@ -153,7 +153,6 @@ 'browser/page_load_metrics/observers/page_load_metrics_observers_unittest.cc', 'browser/password_manager/chrome_password_manager_client_unittest.cc', 'browser/password_manager/password_manager_internals_service_unittest.cc', - 'browser/password_manager/password_manager_setting_migrator_service_unittest.cc', 'browser/password_manager/password_store_mac_unittest.cc', 'browser/password_manager/password_store_proxy_mac_unittest.cc', 'browser/password_manager/password_store_win_unittest.cc', @@ -234,7 +233,6 @@ 'browser/sync/profile_sync_service_startup_unittest.cc', 'browser/sync/profile_sync_service_typed_url_unittest.cc', 'browser/sync/profile_sync_service_unittest.cc', - 'browser/sync/sessions/session_data_type_controller_unittest.cc', 'browser/sync/startup_controller_unittest.cc', 'browser/sync/sync_startup_tracker_unittest.cc', 'browser/sync/test/test_http_bridge_factory.cc', @@ -533,6 +531,7 @@ 'browser/password_manager/save_password_infobar_delegate_unittest.cc', ], 'chrome_unit_tests_android_sources': [ + 'browser/password_manager/auto_signin_infobar_delegate_unittest.cc', 'browser/permissions/permission_queue_controller_unittest.cc', ], 'chrome_unit_tests_non_mobile_sources': [ @@ -996,7 +995,6 @@ 'browser/safe_browsing/safe_browsing_database_unittest.cc', 'browser/safe_browsing/safe_browsing_store_file_unittest.cc', 'browser/safe_browsing/safe_browsing_store_unittest.cc', - 'browser/safe_browsing/safe_browsing_util_unittest.cc', 'browser/safe_browsing/sandboxed_dmg_analyzer_mac_unittest.cc', 'browser/safe_browsing/sandboxed_zip_analyzer_unittest.cc', 'browser/safe_browsing/signature_evaluator_mac_unittest.cc', @@ -1004,6 +1002,7 @@ 'browser/safe_browsing/test_database_manager.h', 'browser/safe_browsing/two_phase_uploader_unittest.cc', 'browser/safe_browsing/unverified_download_field_trial_unittest.cc', + 'browser/safe_browsing/unverified_download_policy_unittest.cc', 'common/safe_browsing/binary_feature_extractor_mac_unittest.cc', 'common/safe_browsing/binary_feature_extractor_unittest.cc', 'common/safe_browsing/binary_feature_extractor_win_unittest.cc', @@ -1508,7 +1507,6 @@ # GCMDriverAndroid is not yet implemented. 'browser/services/gcm/gcm_profile_service_unittest.cc', 'browser/sessions/persistent_tab_restore_service_unittest.cc', - 'browser/sync/sessions/page_revisit_broadcaster_unittest.cc', 'browser/sync/sessions/sessions_sync_manager_unittest.cc', 'browser/sync/sync_ui_util_unittest.cc', # Sync setup uses native ui. 'browser/translate/translate_manager_render_view_host_unittest.cc', @@ -2107,12 +2105,6 @@ 'renderer/media/mock_webrtc_logging_message_filter.h', ], }], - ['enable_wifi_bootstrapping', { - "sources" : [ - 'browser/local_discovery/wifi/mock_wifi_manager.cc', - 'browser/local_discovery/wifi/mock_wifi_manager.h', - ], - }], ['enable_plugins==1', { 'dependencies': [ '../pdf/pdf.gyp:pdf', @@ -2182,6 +2174,7 @@ '../base/base.gyp:test_support_base', '../components/components_resources.gyp:components_resources', '../components/components.gyp:content_settings_core_test_support', + '../components/components.gyp:gcm_driver', '../components/components.gyp:password_manager_core_browser_test_support', '../components/components.gyp:syncable_prefs_test_support', '../components/components.gyp:ui_zoom_test_support', @@ -2289,6 +2282,7 @@ ], 'dependencies': [ '../testing/android/native_test.gyp:native_test_native_code', + '../components/components.gyp:gcm_driver', ], }, { # Not Android. 'sources': [ '<@(chrome_unit_tests_non_android_sources)' ], @@ -2915,8 +2909,8 @@ ['v8_use_external_startup_data==1', { 'asset_location': '<(PRODUCT_DIR)/unit_tests_apk/assets', 'additional_input_paths': [ - '<(PRODUCT_DIR)/unit_tests_apk/assets/natives_blob.bin', - '<(PRODUCT_DIR)/unit_tests_apk/assets/snapshot_blob.bin', + '<(PRODUCT_DIR)/unit_tests_apk/assets/natives_blob_<(arch_suffix).bin', + '<(PRODUCT_DIR)/unit_tests_apk/assets/snapshot_blob_<(arch_suffix).bin', ], }], ], @@ -2928,16 +2922,23 @@ ], 'variables': { 'dest_path': '<(asset_location)', - 'src_files': [ + 'renaming_sources': [ '<(PRODUCT_DIR)/natives_blob.bin', '<(PRODUCT_DIR)/snapshot_blob.bin', ], + 'renaming_destinations': [ + 'natives_blob_<(arch_suffix).bin', + 'snapshot_blob_<(arch_suffix).bin', + ], 'clear': 1, }, 'includes': ['../build/android/copy_ex.gypi'], }], ], - 'includes': [ '../build/apk_test.gypi' ], + 'includes': [ + '../build/apk_test.gypi', + '../build/android/v8_external_startup_data_arch_suffix.gypi' + ], }, ], 'conditions': [
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index dd498685..6eda83a 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -317,6 +317,9 @@ // Disables print preview (For testing, and for users who don't like us. :[ ) const char kDisablePrintPreview[] = "disable-print-preview"; +// Switch to disable simplify page on the print preview dialog. +const char kDisablePrintPreviewSimplify[] = "disable-print-preview-simplify"; + // Normally when the user attempts to navigate to a page that was the result of // a post we prompt to make sure they want to. This switch may be used to // disable that check. This switch is used during automated testing. @@ -565,10 +568,6 @@ const char kEnableWebNotificationCustomLayouts[] = "enable-web-notification-custom-layouts"; -// Enables webusb notifications, which shows notifications when usb devices with -// landing page are plugged in. -const char kEnableWebUsbNotifications[] = "enable-webusb-notifications"; - // Bypasses the WebUSB permission prompt as it is not yet implemented. // crbug.com/529950 const char kEnableWebUsbOnAnyOrigin[] = "enable-webusb-on-any-origin"; @@ -958,6 +957,15 @@ 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 fe7e8d55..265f508 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -91,6 +91,7 @@ extern const char kDisablePopupBlocking[]; extern const char kDisablePreconnect[]; extern const char kDisablePrintPreview[]; +extern const char kDisablePrintPreviewSimplify[]; extern const char kDisablePromptOnRepost[]; extern const char kDisablePushApiBackgroundMode[]; extern const char kDisableQuic[]; @@ -159,7 +160,6 @@ extern const char kEnableUserAlternateProtocolPorts[]; extern const char kEnableWebAppFrame[]; extern const char kEnableWebNotificationCustomLayouts[]; -extern const char kEnableWebUsbNotifications[]; extern const char kEnableWebUsbOnAnyOrigin[]; extern const char kEnableWifiCredentialSync[]; extern const char kExtensionContentVerificationBootstrap[]; @@ -256,6 +256,7 @@ extern const char kSbDisableAutoUpdate[]; extern const char kSbDisableDownloadProtection[]; extern const char kSbDisableExtensionBlacklist[]; +extern const char kSbManualDownloadBlacklist[]; extern const char kServiceProcess[]; extern const char kSilentDebuggerExtensionAPI[]; extern const char kSilentLaunch[];
diff --git a/chrome/common/extensions/api/language_settings_private.idl b/chrome/common/extensions/api/language_settings_private.idl index 30958c5..f1ac49c 100644 --- a/chrome/common/extensions/api/language_settings_private.idl +++ b/chrome/common/extensions/api/language_settings_private.idl
@@ -55,18 +55,18 @@ DOMString[] languageCodes; // True if the input method is enabled. - boolean enabled; + boolean? enabled; + + // True if the input method extension has an options page. + boolean? hasOptionsPage; }; dictionary InputMethodLists { - // The list of built-in input methods. - InputMethod[] inputMethods; - // The list of component extension input methods. - InputMethod[] componentExtensionIMEs; + InputMethod[] componentExtensionImes; // The list of third-party extension input methods. - InputMethod[] thirdPartyExtensionIMEs; + InputMethod[] thirdPartyExtensionImes; }; callback GetLanguageListCallback = void (Language[] languages); @@ -101,7 +101,8 @@ static void getTranslateTargetLanguage( GetTranslateTargetLanguageCallback callback); - // Gets all supported input methods, including IMEs. Chrome OS only. + // Gets all supported input methods, including third-party IMEs. + // Chrome OS only. static void getInputMethodLists(GetInputMethodListsCallback callback); // Adds the input method to the current user's list of enabled input
diff --git a/chrome/installer/util/BUILD.gn b/chrome/installer/util/BUILD.gn index d6286a4..38d197f6 100644 --- a/chrome/installer/util/BUILD.gn +++ b/chrome/installer/util/BUILD.gn
@@ -149,6 +149,8 @@ "legacy_firewall_manager_win.h", "master_preferences_constants.cc", "master_preferences_constants.h", + "module_util_win.cc", + "module_util_win.h", "move_tree_work_item.cc", "move_tree_work_item.h", "non_updating_app_registration_data.cc",
diff --git a/chrome/installer/util/module_util_win.cc b/chrome/installer/util/module_util_win.cc new file mode 100644 index 0000000..c5892636 --- /dev/null +++ b/chrome/installer/util/module_util_win.cc
@@ -0,0 +1,67 @@ +// Copyright (c) 2015 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 <windows.h> + +#include "chrome/installer/util/module_util_win.h" + +#include "base/file_version_info.h" +#include "base/files/file.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/utf_string_conversions.h" +#include "base/version.h" + +namespace installer { + +namespace { + +// Returns the directory in which the currently running executable resides. +base::FilePath GetExecutableDir() { + base::char16 path[MAX_PATH]; + ::GetModuleFileNameW(nullptr, path, MAX_PATH); + return base::FilePath(path).DirName(); +} + +// Returns the version in the current module's version resource or the empty +// string if none found. +base::string16 GetCurrentModuleVersion() { + scoped_ptr<FileVersionInfo> file_version_info( + CREATE_FILE_VERSION_INFO_FOR_CURRENT_MODULE()); + if (file_version_info.get()) { + base::string16 version_string(file_version_info->file_version()); + if (Version(base::UTF16ToASCII(version_string)).IsValid()) + return version_string; + } + return base::string16(); +} + +// Indicates whether a file can be opened using the same flags that +// ::LoadLibrary() uses to open modules. +bool ModuleCanBeRead(const base::FilePath file_path) { + return base::File(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ) + .IsValid(); +} + +} // namespace + +base::FilePath GetModulePath(base::StringPiece16 module_name, + base::string16* version) { + DCHECK(version); + + base::FilePath module_dir = GetExecutableDir(); + base::FilePath module = module_dir.Append(module_name); + if (ModuleCanBeRead(module)) + return module; + + base::string16 version_string(GetCurrentModuleVersion()); + if (version_string.empty()) { + LOG(ERROR) << "No valid Chrome version found"; + return base::FilePath(); + } + *version = version_string; + return module_dir.Append(version_string).Append(module_name); +} + +} // namespace installer
diff --git a/chrome/installer/util/module_util_win.h b/chrome/installer/util/module_util_win.h new file mode 100644 index 0000000..feb5f05 --- /dev/null +++ b/chrome/installer/util/module_util_win.h
@@ -0,0 +1,29 @@ +// Copyright (c) 2015 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. + +// This file defines a utility function to get the full path of a module. + +#ifndef CHROME_INSTALLER_UTIL_MODULE_UTIL_WIN_H_ +#define CHROME_INSTALLER_UTIL_MODULE_UTIL_WIN_H_ + +#include "base/files/file_path.h" +#include "base/strings/string16.h" +#include "base/strings/string_piece.h" + +namespace installer { + +// Returns the full path to |module_name|. Both dev builds (where |module_name| +// is in the current executable's directory) and proper installs (where +// |module_name| is in a versioned sub-directory of the current executable's +// directory) are suported. In the latter case, |version| is populated with the +// name of the versioned sub-directory (i.e., the current executable's +// version). Returns an empty path if the current executable appears to reside +// in a proper install but version information is missing. The identified file +// is not guaranteed to exist. +base::FilePath GetModulePath(base::StringPiece16 module_name, + base::string16* version); + +} // namespace installer + +#endif // CHROME_INSTALLER_UTIL_MODULE_UTIL_WIN_H_
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn index e041627..13b806d7 100644 --- a/chrome/renderer/BUILD.gn +++ b/chrome/renderer/BUILD.gn
@@ -49,7 +49,6 @@ "//components/password_manager/content/renderer", "//components/plugins/renderer", "//components/printing/renderer", - "//components/startup_metric_utils", "//components/translate/content/renderer", "//components/translate/core/common", "//components/translate/core/language_detection",
diff --git a/chrome/renderer/media/cast_receiver_session_delegate.cc b/chrome/renderer/media/cast_receiver_session_delegate.cc index e7930fa0..06ea93d 100644 --- a/chrome/renderer/media/cast_receiver_session_delegate.cc +++ b/chrome/renderer/media/cast_receiver_session_delegate.cc
@@ -13,12 +13,6 @@ } CastReceiverSessionDelegate::~CastReceiverSessionDelegate() {} -void CastReceiverSessionDelegate::LogRawEvents( - const std::vector<media::cast::PacketEvent>& packet_events, - const std::vector<media::cast::FrameEvent>& frame_events) { - NOTREACHED(); -} - void CastReceiverSessionDelegate::Start( const media::cast::FrameReceiverConfig& audio_config, const media::cast::FrameReceiverConfig& video_config,
diff --git a/chrome/renderer/media/cast_receiver_session_delegate.h b/chrome/renderer/media/cast_receiver_session_delegate.h index 98de8fd..7f6b963 100644 --- a/chrome/renderer/media/cast_receiver_session_delegate.h +++ b/chrome/renderer/media/cast_receiver_session_delegate.h
@@ -19,9 +19,6 @@ ~CastReceiverSessionDelegate() override; void ReceivePacket(scoped_ptr<media::cast::Packet> packet) override; - void LogRawEvents( - const std::vector<media::cast::PacketEvent>& packet_events, - const std::vector<media::cast::FrameEvent>& frame_events) override; void Start(const media::cast::FrameReceiverConfig& audio_config, const media::cast::FrameReceiverConfig& video_config,
diff --git a/chrome/renderer/media/cast_session_delegate.cc b/chrome/renderer/media/cast_session_delegate.cc index 5cca597..f39154d 100644 --- a/chrome/renderer/media/cast_session_delegate.cc +++ b/chrome/renderer/media/cast_session_delegate.cc
@@ -79,8 +79,8 @@ base::Unretained(this)), base::Bind(&CastSessionDelegateBase::StatusNotificationCB, base::Unretained(this), error_callback), - base::Bind(&CastSessionDelegateBase::LogRawEvents, - base::Unretained(this)))); + base::Bind(&media::cast::LogEventDispatcher::DispatchBatchOfEvents, + base::Unretained(cast_environment_->logger())))); } void CastSessionDelegateBase::StatusNotificationCB( @@ -313,44 +313,3 @@ scoped_ptr<media::cast::Packet> packet) { // Do nothing (frees packet) } - -void CastSessionDelegate::LogRawEvents( - const std::vector<media::cast::PacketEvent>& packet_events, - const std::vector<media::cast::FrameEvent>& frame_events) { - DCHECK(io_task_runner_->BelongsToCurrentThread()); - - for (std::vector<media::cast::PacketEvent>::const_iterator it = - packet_events.begin(); - it != packet_events.end(); - ++it) { - cast_environment_->Logging()->InsertPacketEvent(it->timestamp, - it->type, - it->media_type, - it->rtp_timestamp, - it->frame_id, - it->packet_id, - it->max_packet_id, - it->size); - } - for (std::vector<media::cast::FrameEvent>::const_iterator it = - frame_events.begin(); - it != frame_events.end(); - ++it) { - if (it->type == media::cast::FRAME_PLAYOUT) { - cast_environment_->Logging()->InsertFrameEventWithDelay( - it->timestamp, - it->type, - it->media_type, - it->rtp_timestamp, - it->frame_id, - it->delay_delta); - } else { - cast_environment_->Logging()->InsertFrameEvent( - it->timestamp, - it->type, - it->media_type, - it->rtp_timestamp, - it->frame_id); - } - } -}
diff --git a/chrome/renderer/media/cast_session_delegate.h b/chrome/renderer/media/cast_session_delegate.h index 378c50e..cd4e63a2f 100644 --- a/chrome/renderer/media/cast_session_delegate.h +++ b/chrome/renderer/media/cast_session_delegate.h
@@ -62,9 +62,6 @@ media::cast::CastTransportStatus status); virtual void ReceivePacket(scoped_ptr<media::cast::Packet> packet) = 0; - virtual void LogRawEvents( - const std::vector<media::cast::PacketEvent>& packet_events, - const std::vector<media::cast::FrameEvent>& frame_events) = 0; base::ThreadChecker thread_checker_; scoped_refptr<media::cast::CastEnvironment> cast_environment_; @@ -136,10 +133,6 @@ private: void ReceivePacket(scoped_ptr<media::cast::Packet> packet) override; - // Adds logs collected from transport on browser side. - void LogRawEvents(const std::vector<media::cast::PacketEvent>& packet_events, - const std::vector<media::cast::FrameEvent>& frame_events) - override; scoped_ptr<media::cast::CastSender> cast_sender_;
diff --git a/chrome/renderer/media/cast_transport_sender_ipc.cc b/chrome/renderer/media/cast_transport_sender_ipc.cc index e814dc2..afa858a 100644 --- a/chrome/renderer/media/cast_transport_sender_ipc.cc +++ b/chrome/renderer/media/cast_transport_sender_ipc.cc
@@ -142,7 +142,19 @@ void CastTransportSenderIPC::OnRawEvents( const std::vector<media::cast::PacketEvent>& packet_events, const std::vector<media::cast::FrameEvent>& frame_events) { - raw_events_callback_.Run(packet_events, frame_events); + // Note: Casting away const to avoid having to copy all the data elements. As + // the only consumer of this data in the IPC message, mutating the inputs + // should be acceptable. Just nod and blame the interface we were given here. + scoped_ptr<std::vector<media::cast::FrameEvent>> taken_frame_events( + new std::vector<media::cast::FrameEvent>()); + taken_frame_events->swap( + const_cast<std::vector<media::cast::FrameEvent>&>(frame_events)); + scoped_ptr<std::vector<media::cast::PacketEvent>> taken_packet_events( + new std::vector<media::cast::PacketEvent>()); + taken_packet_events->swap( + const_cast<std::vector<media::cast::PacketEvent>&>(packet_events)); + raw_events_callback_.Run(taken_frame_events.Pass(), + taken_packet_events.Pass()); } void CastTransportSenderIPC::OnRtt(uint32 ssrc, base::TimeDelta rtt) {
diff --git a/chrome/telemetry_perf_unittests.isolate b/chrome/telemetry_perf_unittests.isolate new file mode 100644 index 0000000..36dcaac --- /dev/null +++ b/chrome/telemetry_perf_unittests.isolate
@@ -0,0 +1,26 @@ +# Copyright 2015 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. +{ + 'includes': [ + '../tools/perf/perf.isolate', + ], + 'conditions': [ + ['OS=="mac" or OS=="win"', { + 'variables': { + 'files': [ + # Other dependencies of the tests and their harness. + '../testing/test_env.py', + '../testing/xvfb.py', + '../testing/scripts/common.py', + '../testing/scripts/run_telemetry_as_googletest.py', + ], + 'command': [ + '../testing/scripts/run_telemetry_as_googletest.py', + '../tools/perf/run_tests', + '-v', + ], + }, + }], + ] +}
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 1f3ccb1..a795e123 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -217,7 +217,7 @@ ] } - if (enable_plugins) { + if (enable_plugins && enable_pdf) { deps += [ "//pdf" ] } @@ -2203,10 +2203,8 @@ dest = "$root_out_dir/unit_tests_apk/assets" if (v8_use_external_startup_data) { - sources = [ - "$root_out_dir/natives_blob.bin", - "$root_out_dir/snapshot_blob.bin", - ] + renaming_sources = v8_external_startup_data_renaming_sources + renaming_destinations = v8_external_startup_data_renaming_destinations deps = [ "//v8", ]
diff --git a/chrome/test/DEPS b/chrome/test/DEPS index 2d596c8..2167a411 100644 --- a/chrome/test/DEPS +++ b/chrome/test/DEPS
@@ -6,6 +6,7 @@ "+chrome/grit", # For generated headers "+chromeos", "+components", + "+device/bluetooth/dbus", "+extensions", # Tests under chrome/ shouldn't need to access the internals of content/ and
diff --git a/chrome/test/base/js2gtest.gni b/chrome/test/base/js2gtest.gni index a995869..6dae74a 100644 --- a/chrome/test/base/js2gtest.gni +++ b/chrome/test/base/js2gtest.gni
@@ -126,7 +126,9 @@ deps += invoker.deps } if (defined(invoker.extra_js_files)) { - data_deps = [ ":$copy_target_name" ] + data_deps = [ + ":$copy_target_name", + ] } } }
diff --git a/chrome/test/base/testing_io_thread_state.cc b/chrome/test/base/testing_io_thread_state.cc index 8ebd202b8..09b07f2 100644 --- a/chrome/test/base/testing_io_thread_state.cc +++ b/chrome/test/base/testing_io_thread_state.cc
@@ -16,6 +16,7 @@ #if defined(OS_CHROMEOS) #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/network/network_handler.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" #endif using content::BrowserThread; @@ -42,6 +43,10 @@ #if defined(OS_CHROMEOS) // Needed by IOThread constructor. chromeos::DBusThreadManager::Initialize(); + bluez::BluezDBusManager::Initialize( + chromeos::DBusThreadManager::Get()->GetSystemBus(), + chromeos::DBusThreadManager::Get()->IsUsingStub( + chromeos::DBusClientBundle::BLUETOOTH)); chromeos::NetworkHandler::Initialize(); #endif @@ -75,6 +80,7 @@ #if defined(OS_CHROMEOS) chromeos::NetworkHandler::Shutdown(); + bluez::BluezDBusManager::Shutdown(); chromeos::DBusThreadManager::Shutdown(); #endif }
diff --git a/chrome/test/base/view_event_test_platform_part_chromeos.cc b/chrome/test/base/view_event_test_platform_part_chromeos.cc index 2cf14ef..16a678e 100644 --- a/chrome/test/base/view_event_test_platform_part_chromeos.cc +++ b/chrome/test/base/view_event_test_platform_part_chromeos.cc
@@ -15,6 +15,7 @@ #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/network/network_handler.h" #include "content/public/browser/browser_thread.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" #include "ui/aura/env.h" #include "ui/aura/window_tree_host.h" #include "ui/message_center/message_center.h" @@ -46,6 +47,10 @@ // also create the message center. message_center::MessageCenter::Initialize(); chromeos::DBusThreadManager::Initialize(); + bluez::BluezDBusManager::Initialize( + chromeos::DBusThreadManager::Get()->GetSystemBus(), + chromeos::DBusThreadManager::Get()->IsUsingStub( + chromeos::DBusClientBundle::BLUETOOTH)); chromeos::CrasAudioHandler::InitializeForTesting(); chromeos::NetworkHandler::Initialize(); @@ -70,6 +75,7 @@ chromeos::NetworkHandler::Shutdown(); chromeos::CrasAudioHandler::Shutdown(); + bluez::BluezDBusManager::Shutdown(); chromeos::DBusThreadManager::Shutdown(); // Ash Shell can't just live on its own without a browser process, we need to // also shut down the message center.
diff --git a/chrome/test/chromedriver/client/webelement.py b/chrome/test/chromedriver/client/webelement.py index 64d3b31..1e150f38 100644 --- a/chrome/test/chromedriver/client/webelement.py +++ b/chrome/test/chromedriver/client/webelement.py
@@ -28,6 +28,9 @@ def GetText(self): return self._Execute(Command.GET_ELEMENT_TEXT) + def GetAttribute(self,name): + return self._Execute(Command.GET_ELEMENT_ATTRIBUTE, {'name': name}) + def HoverOver(self): self._Execute(Command.HOVER_OVER_ELEMENT)
diff --git a/chrome/test/chromedriver/server/http_handler.cc b/chrome/test/chromedriver/server/http_handler.cc index c3941b0..0c37fc5 100644 --- a/chrome/test/chromedriver/server/http_handler.cc +++ b/chrome/test/chromedriver/server/http_handler.cc
@@ -14,6 +14,7 @@ #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" #include "base/sys_info.h" #include "base/thread_task_runner_handle.h" #include "base/values.h" @@ -29,6 +30,7 @@ #include "chrome/test/chromedriver/version.h" #include "net/server/http_server_request_info.h" #include "net/server/http_server_response_info.h" +#include "url/url_util.h" #if defined(OS_MACOSX) #include "base/mac/scoped_nsautorelease_pool.h" @@ -756,10 +758,19 @@ std::string name = command_path_parts[i]; name.erase(0, 1); CHECK(name.length()); + url::RawCanonOutputT<base::char16> output; + url::DecodeURLEscapeSequences( + path_parts[i].data(), path_parts[i].length(), &output); + std::string decoded = base::UTF16ToASCII( + base::string16(output.data(), output.length())); + // Due to crbug.com/533361, the url decoding libraries decodes all of the + // % escape sequences except for %%. We need to handle this case manually. + // So, replacing all the instances of "%%" with "%". + base::ReplaceSubstringsAfterOffset(&decoded, 0 , "%%" , "%"); if (name == "sessionId") - *session_id = path_parts[i]; + *session_id = decoded; else - params.SetString(name, path_parts[i]); + params.SetString(name, decoded); } else if (command_path_parts[i] != path_parts[i]) { return false; }
diff --git a/chrome/test/chromedriver/server/http_handler_unittest.cc b/chrome/test/chromedriver/server/http_handler_unittest.cc index 59c191f..3ff85c6 100644 --- a/chrome/test/chromedriver/server/http_handler_unittest.cc +++ b/chrome/test/chromedriver/server/http_handler_unittest.cc
@@ -172,3 +172,28 @@ ASSERT_TRUE(params.GetString("b", ¶m)); ASSERT_EQ("3", param); } + +TEST(MatchesCommandTest, DecodeEscape) { + CommandMapping command(kPost, "path/:sessionId/attribute/:xyz", + base::Bind(&DummyCommand, Status(kOk))); + std::string session_id; + base::DictionaryValue params; + ASSERT_TRUE(internal::MatchesCommand( + "post", "path/123/attribute/xyz%2Furl%7Ce%3A%40v", + command, &session_id, ¶ms)); + std::string param; + ASSERT_TRUE(params.GetString("xyz", ¶m)); + ASSERT_EQ("xyz/url|e:@v", param); +} + +TEST(MatchesCommandTest, DecodePercent) { + CommandMapping command(kPost, "path/:xyz", + base::Bind(&DummyCommand, Status(kOk))); + std::string session_id; + base::DictionaryValue params; + ASSERT_TRUE(internal::MatchesCommand( + "post", "path/%40a%%b%%c%%%%", command, &session_id, ¶ms)); + std::string param; + ASSERT_TRUE(params.GetString("xyz", ¶m)); + ASSERT_EQ("@a%b%c%%", param); +}
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py index 55f4c1e..924b12f5 100755 --- a/chrome/test/chromedriver/test/run_py_tests.py +++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -526,6 +526,18 @@ value = self._driver.ExecuteScript('return arguments[0].value;', text) self.assertEquals('0123456789+-*/ Hi, there!', value) + def testGetElementAttribute(self): + self._driver.Load(self.GetHttpUrlForFile( + '/chromedriver/attribute_colon_test.html')) + elem = self._driver.FindElement("name", "phones") + self.assertEquals('3', elem.GetAttribute('size')) + + def testGetElementSpecialCharAttribute(self): + self._driver.Load(self.GetHttpUrlForFile( + '/chromedriver/attribute_colon_test.html')) + elem = self._driver.FindElement("name", "phones") + self.assertEquals('colonvalue', elem.GetAttribute('ext:qtip')) + def testGetCurrentUrl(self): url = self.GetHttpUrlForFile('/chromedriver/frame_test.html') self._driver.Load(url)
diff --git a/chrome/test/data/banners/main.js b/chrome/test/data/banners/main.js index 8fe1af3..bb349f1 100644 --- a/chrome/test/data/banners/main.js +++ b/chrome/test/data/banners/main.js
@@ -2,22 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -var registration; -var interval; - -function waitUntilActivated() { - if (registration && registration.active) { - window.location = "#sw_activated"; - window.clearInterval(interval); - } else { - console.log("SW not yet active."); - } -} - function initialize() { - navigator.serviceWorker.register('service_worker.js') - .then(function(r) { - registration = r; - }); - interval = window.setInterval(function() {waitUntilActivated()}, 50); -} \ No newline at end of file + navigator.serviceWorker.register('service_worker.js'); +}
diff --git a/chrome/test/data/chromedriver/attribute_colon_test.html b/chrome/test/data/chromedriver/attribute_colon_test.html new file mode 100644 index 0000000..3add5c4 --- /dev/null +++ b/chrome/test/data/chromedriver/attribute_colon_test.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="UTF-8"> + <title>Test Attribute with escape characters</title> + </head> + <body> + <select name="phones" size="3" onchange="alert('hello');" ext:qtip="colonvalue"> + <option value="iphone">Apple IPhone</option> + <option value="android">Google Android</option> + <option value="wp">MS Windows Phone</option> + </select> + </body> +</html>
diff --git a/chrome/test/data/extensions/api_test/gcd_private/api/wifi_message.html b/chrome/test/data/extensions/api_test/gcd_private/api/wifi_message.html deleted file mode 100644 index 875d684..0000000 --- a/chrome/test/data/extensions/api_test/gcd_private/api/wifi_message.html +++ /dev/null
@@ -1 +0,0 @@ -<script src="wifi_message.js"></script>
diff --git a/chrome/test/data/extensions/api_test/gcd_private/api/wifi_message.js b/chrome/test/data/extensions/api_test/gcd_private/api/wifi_message.js deleted file mode 100644 index ad99fe06..0000000 --- a/chrome/test/data/extensions/api_test/gcd_private/api/wifi_message.js +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -onload = function() { - chrome.test.runTests([ - function wifiMessage() { - var messagesNeeded = 4; - var sessionId = -1; - - function onMessageSent(expected_status, status, output) { - chrome.test.assertEq(expected_status, status); - messagesNeeded--; - console.log("Messages needed " + messagesNeeded); - - if (messagesNeeded == 0) { - chrome.test.notifyPass(); - } - }; - - chrome.gcdPrivate.sendMessage(sessionId, "/privet/v3/setup/start", { - "wifi" : { - } - }, onMessageSent.bind(null, "setupParseError")); - - chrome.gcdPrivate.sendMessage(sessionId, "/privet/v3/setup/start", { - "wifi" : { - "passphrase": "Blah" - } - }, onMessageSent.bind(null, "setupParseError")); - - chrome.gcdPrivate.sendMessage(sessionId, "/privet/v3/setup/start", { - "wifi" : { - "ssid": "Blah" - } - }, onMessageSent.bind(null, "wifiPasswordError")); - - chrome.gcdPrivate.sendMessage(sessionId, "/privet/v3/setup/start", { - "wifi": { - "ssid": "Blah", - "passphrase": "111" - } - }, onMessageSent.bind(null, "unknownSessionError")); - } - ]); -};
diff --git a/chrome/test/data/extensions/api_test/gcd_private/api/wifi_password.html b/chrome/test/data/extensions/api_test/gcd_private/api/wifi_password.html deleted file mode 100644 index 80d0173c..0000000 --- a/chrome/test/data/extensions/api_test/gcd_private/api/wifi_password.html +++ /dev/null
@@ -1 +0,0 @@ -<script src="wifi_password.js"></script>
diff --git a/chrome/test/data/extensions/api_test/gcd_private/api/wifi_password.js b/chrome/test/data/extensions/api_test/gcd_private/api/wifi_password.js deleted file mode 100644 index ad12257..0000000 --- a/chrome/test/data/extensions/api_test/gcd_private/api/wifi_password.js +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -onload = function() { - chrome.test.runTests([ - function wifiPassword() { - var succeeded = false; - var failed = false; - - function expectResult(expectedResult, result) { - chrome.test.assertEq(expectedResult, result); - - if (expectedResult) succeeded = true; - else failed = true; - - if (succeeded && failed) { - chrome.gcdPrivate.getPrefetchedWifiNameList(onWifiList); - } - } - - function onWifiList(list) { - chrome.test.assertEq(["SuccessNetwork"], list); - - chrome.test.notifyPass(); - } - - chrome.gcdPrivate.prefetchWifiPassword("SuccessNetwork", - expectResult.bind(null, true)); - - chrome.gcdPrivate.prefetchWifiPassword("FailureNetwork", - expectResult.bind(null, false)); - } - ]); -};
diff --git a/chrome/test/data/save_page/b.saved1.htm b/chrome/test/data/save_page/b.saved1.htm index db7d559a..1289d498 100644 --- a/chrome/test/data/save_page/b.saved1.htm +++ b/chrome/test/data/save_page/b.saved1.htm
@@ -12,4 +12,5 @@ The picture below is the back button.<br> <img src="./b_files/1.png"> -</body></html> + +</body></html> \ No newline at end of file
diff --git a/chrome/test/data/save_page/b.saved2.htm b/chrome/test/data/save_page/b.saved2.htm index 7a489139..9239e5f 100644 --- a/chrome/test/data/save_page/b.saved2.htm +++ b/chrome/test/data/save_page/b.saved2.htm
@@ -12,4 +12,5 @@ The picture below is the back button.<br> <img src="./Test page for saving page feature_files/1.png"> -</body></html> + +</body></html> \ No newline at end of file
diff --git a/chrome/test/data/translate/basic_fr_test.html b/chrome/test/data/translate/basic_fr_test.html new file mode 100644 index 0000000..4dafbf3 --- /dev/null +++ b/chrome/test/data/translate/basic_fr_test.html
@@ -0,0 +1,9 @@ +<html> +<head> + <title>basic_fr_test.html: check if Chrome Translate works for a basic case</title> + <meta http-equiv="content-language" content="fr"> +</head> +<body> + <div>bonjour Chrome Translate.</div> +</body> +</html>
diff --git a/chrome/test/data/webui/extensions/OWNERS b/chrome/test/data/webui/extensions/OWNERS new file mode 100644 index 0000000..aad0b92 --- /dev/null +++ b/chrome/test/data/webui/extensions/OWNERS
@@ -0,0 +1 @@ +rdevlin.cronin@chromium.org
diff --git a/chrome/test/data/webui/extensions/cr_extensions_browsertest.js b/chrome/test/data/webui/extensions/cr_extensions_browsertest.js new file mode 100644 index 0000000..e194af3d --- /dev/null +++ b/chrome/test/data/webui/extensions/cr_extensions_browsertest.js
@@ -0,0 +1,75 @@ +// Copyright 2015 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. + +/** @fileoverview Runs the Polymer Settings tests. */ + +/** @const {string} Path to source root. */ +var ROOT_PATH = '../../../../../'; + +// Polymer BrowserTest fixture. +GEN_INCLUDE([ + ROOT_PATH + 'chrome/test/data/webui/polymer_browser_test_base.js']); +GEN('#include "base/command_line.h"'); +GEN('#include "chrome/browser/ui/webui/extensions/' + + 'extension_settings_browsertest.h"'); + +/** + * Test fixture for Polymer Settings elements. + * @constructor + * @extends {PolymerTest} +*/ +function CrExtensionsBrowserTest() {} + +CrExtensionsBrowserTest.prototype = { + __proto__: PolymerTest.prototype, + + /** @override */ + browsePreload: 'chrome://extensions/', + + /** @override */ + commandLineSwitches: [{ + switchName: 'enable-md-extensions', + }], + + /** @override */ + extraLibraries: PolymerTest.getLibraries(ROOT_PATH).concat([ + 'extension_service_test.js', + ]), + + /** @override */ + typedefCppFixture: 'ExtensionSettingsUIBrowserTest', +}; + +function CrExtensionsBrowserTestWithInstalledExtension() {} + +CrExtensionsBrowserTestWithInstalledExtension.prototype = { + __proto__: CrExtensionsBrowserTest.prototype, + + /** @override */ + testGenPreamble: function() { + GEN(' InstallGoodExtension();'); + GEN(' SetAutoConfirmUninstall();'); + }, +}; + +TEST_F('CrExtensionsBrowserTestWithInstalledExtension', + 'ExtensionServiceToggleEnableTest', function() { + extension_service_tests.registerToggleEnableTests(); + mocha.run(); +}); +TEST_F('CrExtensionsBrowserTestWithInstalledExtension', + 'ExtensionServiceToggleIncognitoTest', function() { + extension_service_tests.registerToggleIncognitoTests(); + mocha.run(); +}); +TEST_F('CrExtensionsBrowserTestWithInstalledExtension', + 'ExtensionServiceUninstallTest', function() { + extension_service_tests.registerUninstallTests(); + mocha.run(); +}); +TEST_F('CrExtensionsBrowserTestWithInstalledExtension', + 'ExtensionServiceProfileSettingsTest', function() { + extension_service_tests.registerProfileSettingsTests(); + mocha.run(); +});
diff --git a/chrome/test/data/webui/extensions/extension_service_test.js b/chrome/test/data/webui/extensions/extension_service_test.js new file mode 100644 index 0000000..a3a47fc --- /dev/null +++ b/chrome/test/data/webui/extensions/extension_service_test.js
@@ -0,0 +1,228 @@ +// Copyright 2015 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. + +/** @fileoverview Suite of tests for extension-item. */ +cr.define('extension_service_tests', function() { + /** @const */ + var kExtensionId = 'ldnnhddmnhbkjipkidpdiheffobcpfmf'; + + /** @const */ + var EventType = chrome.developerPrivate.EventType; + + /** @const */ + var ExtensionState = chrome.developerPrivate.ExtensionState; + + /** @constructor */ + function ChangeListener() {} + + ChangeListener.prototype = { + /** + * @param {!ChromeEvent} chromeEvent + * @param {!function(...):boolean} matchFunction + */ + init_: function(chromeEvent, matchFunction) { + this.onUpdate = new Promise(function(resolve, reject) { + this.resolvePromise_ = resolve; + }.bind(this)); + this.listener_ = this.onChanged_.bind(this); + this.event_ = chromeEvent; + this.matches_ = matchFunction; + this.event_.addListener(this.listener_); + }, + + /** @private */ + onChanged_: function() { + if (this.matches_.apply(null, arguments)) { + setTimeout(function() { + this.event_.removeListener(this.listener_); + this.resolvePromise_(); + }.bind(this)); + } + }, + }; + + /** + * @param {string} id The id of the item to watch. + * @param {chrome.developerPrivate.EventType} eventType The type of event + * to wait for. + * @extends {extension_service_tests.ChangeListener} + * @constructor + */ + function ItemChangedListener(id, eventType) { + this.__proto__ = ChangeListener.prototype, + this.init_(chrome.developerPrivate.onItemStateChanged, + function(data) { + return data.event_type == eventType && data.item_id == id; + }); + } + + /** + * @extends {extension_service_tests.ChangeListener} + * @constructor + */ + function ProfileChangedListener() { + this.__proto__ = ChangeListener.prototype, + this.init_(chrome.developerPrivate.onProfileStateChanged, + function() { return true; }); + } + + function registerToggleEnableTests() { + suite('ExtensionServiceTest', function() { + var service; + var manager; + + suiteSetup(function() { + return PolymerTest.importHtml('chrome://extensions/service.html'); + }); + + // Initialize an extension item before each test. + setup(function() { + service = extensions.Service.getInstance(); + manager = document.getElementsByTagName('extensions-manager')[0]; + }); + + test('Test extension service enable and disable', function(done) { + var item = manager.getItem(kExtensionId); + assertTrue(!!item); + expectEquals(kExtensionId, item.id); + expectEquals('My extension 1', item.data.name); + expectEquals(ExtensionState.ENABLED, item.data.state); + + var disabledListener = + new ItemChangedListener(kExtensionId, EventType.UNLOADED); + service.setItemEnabled(kExtensionId, false); + disabledListener.onUpdate.then(function() { + expectEquals(ExtensionState.DISABLED, item.data.state); + + enabledListener = + new ItemChangedListener(kExtensionId, EventType.LOADED); + service.setItemEnabled(kExtensionId, true); + return enabledListener.onUpdate; + }).then(function() { + expectEquals(ExtensionState.ENABLED, item.data.state); + done(); + }); + }); + }); + } + + function registerToggleIncognitoTests() { + suite('ExtensionServiceToggleIncognitoTest', function() { + var service; + var manager; + + suiteSetup(function() { + return PolymerTest.importHtml('chrome://extensions/service.html'); + }); + + // Initialize an extension item before each test. + setup(function() { + service = extensions.Service.getInstance(); + manager = document.getElementsByTagName('extensions-manager')[0]; + }); + + test('Test extension service toggle incognito mode', function(done) { + var item = manager.getItem(kExtensionId); + assertTrue(!!item); + expectTrue(item.data.incognitoAccess.isEnabled); + expectFalse(item.data.incognitoAccess.isActive); + + var incognitoListener = + new ItemChangedListener(kExtensionId, EventType.LOADED); + chrome.test.runWithUserGesture(function() { + service.setItemAllowedIncognito(kExtensionId, true); + }); + incognitoListener.onUpdate.then(function() { + expectTrue(item.data.incognitoAccess.isActive); + + var disabledIncognitoListener = + new ItemChangedListener(kExtensionId, EventType.LOADED); + chrome.test.runWithUserGesture(function() { + service.setItemAllowedIncognito(kExtensionId, false); + }); + return disabledIncognitoListener.onUpdate; + }).then(function() { + expectFalse(item.data.incognitoAccess.isActive); + done(); + }); + }); + }); + } + + function registerUninstallTests() { + suite('ExtensionServiceUninstallTest', function() { + var service; + var manager; + + suiteSetup(function() { + return PolymerTest.importHtml('chrome://extensions/service.html'); + }); + + // Initialize an extension item before each test. + setup(function() { + service = extensions.Service.getInstance(); + manager = document.querySelector('extensions-manager'); + }); + + test('Test extension service uninstall', function(done) { + var item = manager.getItem(kExtensionId); + assertTrue(!!item); + var uninstallListener = + new ItemChangedListener(kExtensionId, EventType.UNINSTALLED); + chrome.test.runWithUserGesture(function() { + service.deleteItem(kExtensionId); + }); + uninstallListener.onUpdate.then(function() { + expectFalse(!!manager.getItem(kExtensionId)); + done(); + }); + }); + }); + } + + function registerProfileSettingsTests() { + suite('ExtensionServiceProfileSettingsTest', function() { + var service; + var manager; + + suiteSetup(function() { + return PolymerTest.importHtml('chrome://extensions/service.html'); + }); + + // Initialize an extension item before each test. + setup(function() { + service = extensions.Service.getInstance(); + manager = document.getElementsByTagName('extensions-manager')[0]; + }); + + test('Test extension service profile settings', function(done) { + var item = manager.getItem(kExtensionId); + assertTrue(!!item); + expectFalse(item.inDevMode); + + var profileListener = new ProfileChangedListener(); + service.setProfileInDevMode(true); + + profileListener.onUpdate.then(function() { + expectTrue(item.inDevMode); + + var noDevModeProfileListener = new ProfileChangedListener(); + service.setProfileInDevMode(false); + return noDevModeProfileListener.onUpdate; + }).then(function() { + expectFalse(item.inDevMode); + done(); + }); + }); + }); + } + + return { + ChangeListener: ChangeListener, + registerToggleEnableTests: registerToggleEnableTests, + registerToggleIncognitoTests: registerToggleIncognitoTests, + registerUninstallTests: registerUninstallTests, + registerProfileSettingsTests: registerProfileSettingsTests, + }; +});
diff --git a/chrome/test/data/webui/polymer_browser_test_base.js b/chrome/test/data/webui/polymer_browser_test_base.js index b768ef7..d79ce51 100644 --- a/chrome/test/data/webui/polymer_browser_test_base.js +++ b/chrome/test/data/webui/polymer_browser_test_base.js
@@ -46,15 +46,48 @@ setUp: function() { testing.Test.prototype.setUp.call(this); + // List of imported URLs for debugging purposes. + PolymerTest.importUrls_ = []; + + // Importing a URL like "chrome://md-settings/foo" redirects to the base + // ("chrome://md-settings") page, which due to how browsePreload works can + // result in duplicate imports. Wrap document.registerElement so failures + // caused by re-registering Polymer elements are caught; otherwise Chrome + // simply throws "Script error" which is unhelpful. + var originalRegisterElement = document.registerElement; + document.registerElement = function() { + try { + return originalRegisterElement.apply(document, arguments); + } catch (e) { + var msg = + 'If the call to document.registerElement failed because a type ' + + 'is already registered, perhaps you have loaded a script twice. ' + + 'Incorrect resource URLs can redirect to base WebUI pages; make ' + + 'sure the following URLs are correct and unique:\n'; + for (var i = 0; i < PolymerTest.importUrls_.length; i++) + msg += ' ' + PolymerTest.importUrls_[i] + '\n'; + console.error(msg); + + // Mocha will handle the error. + throw e; + } + }; + // Import Polymer and iron-test-helpers before running tests. suiteSetup(function() { - return Promise.all([ - PolymerTest.importHtml( - 'chrome://resources/polymer/v1_0/polymer/polymer.html'), - PolymerTest.importHtml( - 'chrome://resources/polymer/v1_0/iron-test-helpers/' + - 'iron-test-helpers.html'), - ]); + var promises = []; + if (typeof Polymer != 'function') { + promises.push( + PolymerTest.importHtml( + 'chrome://resources/polymer/v1_0/polymer/polymer.html')); + } + if (typeof TestHelpers != 'object') { + promises.push( + PolymerTest.importHtml( + 'chrome://resources/polymer/v1_0/iron-test-helpers/' + + 'iron-test-helpers.html')); + } + return Promise.all(promises); }); }, }; @@ -65,6 +98,7 @@ * @return {Promise} A promise that is resolved/rejected on success/failure. */ PolymerTest.importHtml = function(src) { + PolymerTest.importUrls_.push(src); var link = document.createElement('link'); link.rel = 'import'; var promise = new Promise(function(resolve, reject) {
diff --git a/chrome/test/ppapi/ppapi_filechooser_browsertest.cc b/chrome/test/ppapi/ppapi_filechooser_browsertest.cc index 3066fcc..54c04b5 100644 --- a/chrome/test/ppapi/ppapi_filechooser_browsertest.cc +++ b/chrome/test/ppapi/ppapi_filechooser_browsertest.cc
@@ -14,6 +14,11 @@ #include "ui/shell_dialogs/select_file_dialog_factory.h" #include "ui/shell_dialogs/selected_file_info.h" +#if defined(FULL_SAFE_BROWSING) +#include "chrome/browser/safe_browsing/safe_browsing_service.h" +#include "chrome/browser/safe_browsing/test_database_manager.h" +#endif + namespace { class TestSelectFileDialogFactory final : public ui::SelectFileDialogFactory { @@ -117,8 +122,54 @@ Mode mode_; }; +class FakeDatabaseManager : public TestSafeBrowsingDatabaseManager { + public: + bool IsSupported() const override { return true; } + bool MatchDownloadWhitelistUrl(const GURL& url) override { + // This matches the behavior in RunTestViaHTTP(). + return url.SchemeIsHTTPOrHTTPS() && url.has_path() && + url.path().find("/files/test_case.html") == 0; + } + + protected: + ~FakeDatabaseManager() override {} +}; + +class TestSafeBrowsingService : public SafeBrowsingService { + public: + SafeBrowsingDatabaseManager* CreateDatabaseManager() override { + return new FakeDatabaseManager(); + } + + protected: + ~TestSafeBrowsingService() override {} +}; + +class TestSafeBrowsingServiceFactory : public SafeBrowsingServiceFactory { + public: + SafeBrowsingService* CreateSafeBrowsingService() override { + SafeBrowsingService* service = new TestSafeBrowsingService(); + return service; + } +}; + class PPAPIFileChooserTest : public OutOfProcessPPAPITest {}; +class PPAPIFileChooserTestWithSBService : public PPAPIFileChooserTest { + public: + void SetUp() override { + SafeBrowsingService::RegisterFactory(&safe_browsing_service_factory_); + PPAPIFileChooserTest::SetUp(); + } + void TearDown() override { + PPAPIFileChooserTest::TearDown(); + SafeBrowsingService::RegisterFactory(nullptr); + } + + private: + TestSafeBrowsingServiceFactory safe_browsing_service_factory_; +}; + } // namespace IN_PROC_BROWSER_TEST_F(PPAPIFileChooserTest, FileChooser_Open_Success) { @@ -211,7 +262,7 @@ } #if defined(FULL_SAFE_BROWSING) -// These two tests only make sense when SafeBrowsing is enabled. They verify +// These tests only make sense when SafeBrowsing is enabled. They verify // that files written via the FileChooser_Trusted API are properly passed // through Safe Browsing. @@ -248,4 +299,32 @@ RunTestViaHTTP("FileChooser_SaveAsDangerousExecutableDisallowed"); } +// The kDisallowUncheckedDangerousDownloads switch (whose behavior is verified +// by the FileChooser_SaveAs_DangerousExecutable_Disallowed test above) should +// block the file being downloaded. However, the FakeDatabaseManager reports +// that the requestors document URL matches the Safe Browsing whitelist. Hence +// the download succeeds. +IN_PROC_BROWSER_TEST_F(PPAPIFileChooserTestWithSBService, + FileChooser_SaveAs_DangerousExecutable_Whitelist) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kDisallowUncheckedDangerousDownloads); + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + base::FilePath suggested_filename = temp_dir.path().AppendASCII("foo"); + + TestSelectFileDialogFactory::SelectedFileInfoList file_info_list; + file_info_list.push_back( + ui::SelectedFileInfo(suggested_filename, suggested_filename)); + TestSelectFileDialogFactory test_dialog_factory( + TestSelectFileDialogFactory::REPLACE_BASENAME, file_info_list); + + RunTestViaHTTP("FileChooser_SaveAsDangerousExecutableAllowed"); + base::FilePath actual_filename = temp_dir.path().AppendASCII("dangerous.exe"); + + ASSERT_TRUE(base::PathExists(actual_filename)); + std::string file_contents; + ASSERT_TRUE(base::ReadFileToString(actual_filename, &file_contents, 100)); + EXPECT_EQ("Hello from PPAPI", file_contents); +} + #endif // FULL_SAFE_BROWSING
diff --git a/chromecast/chromecast.gyp b/chromecast/chromecast.gyp index 3e5ea4a..87988e61 100644 --- a/chromecast/chromecast.gyp +++ b/chromecast/chromecast.gyp
@@ -538,6 +538,7 @@ # Targets for Android receiver. 'conditions': [ ['OS=="android"', { + 'includes': ['../build/android/v8_external_startup_data_arch_suffix.gypi',], 'variables': { 'cast_shell_assets_path': '<(PRODUCT_DIR)/assets/cast_shell_apk', }, @@ -554,9 +555,15 @@ 'src_files': [ '<(PRODUCT_DIR)/icudtl.dat', '<(PRODUCT_DIR)/assets/cast_shell.pak', + ], + 'renaming_sources': [ '<(PRODUCT_DIR)/natives_blob.bin', '<(PRODUCT_DIR)/snapshot_blob.bin', ], + 'renaming_destinations': [ + 'natives_blob_<(arch_suffix).bin', + 'snapshot_blob_<(arch_suffix).bin', + ], 'clear': 1, }, 'includes': ['../build/android/copy_ex.gypi'], @@ -665,8 +672,8 @@ 'additional_input_paths': [ '<(asset_location)/cast_shell.pak', '<(asset_location)/icudtl.dat', - '<(asset_location)/natives_blob.bin', - '<(asset_location)/snapshot_blob.bin', + '<(asset_location)/natives_blob_<(arch_suffix).bin', + '<(asset_location)/snapshot_blob_<(arch_suffix).bin', ], }, 'includes': [ '../build/java_apk.gypi' ],
diff --git a/chromecast/media/audio/cast_audio_output_stream.cc b/chromecast/media/audio/cast_audio_output_stream.cc index cd0cb8e2..e8f7e59 100644 --- a/chromecast/media/audio/cast_audio_output_stream.cc +++ b/chromecast/media/audio/cast_audio_output_stream.cc
@@ -68,7 +68,8 @@ : audio_params_(audio_params), decoder_(nullptr), first_start_(true), - error_(false) { + error_(false), + weak_factory_(this) { thread_checker_.DetachFromThread(); } ~Backend() override {} @@ -174,6 +175,10 @@ OnPushBufferComplete(decoder_, MediaPipelineBackend::kBufferFailed); } + base::WeakPtr<CastAudioOutputStream::Backend> GetWeakPtr() { + return weak_factory_.GetWeakPtr(); + } + private: const ::media::AudioParameters audio_params_; scoped_ptr<MediaPipelineBackend> backend_; @@ -184,6 +189,8 @@ bool error_; scoped_refptr<DecoderBufferBase> backend_buffer_; base::ThreadChecker thread_checker_; + base::WeakPtrFactory<CastAudioOutputStream::Backend> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(Backend); }; @@ -205,7 +212,9 @@ << audio_params_.AsHumanReadableString(); } -CastAudioOutputStream::~CastAudioOutputStream() {} +CastAudioOutputStream::~CastAudioOutputStream() { + backend_task_runner_->DeleteSoon(FROM_HERE, backend_.release()); +} bool CastAudioOutputStream::Open() { DCHECK(audio_task_runner_->BelongsToCurrentThread()); @@ -229,7 +238,7 @@ bool success = false; base::WaitableEvent completion_event(false, false); backend_task_runner_->PostTask( - FROM_HERE, base::Bind(&Backend::Open, base::Unretained(backend_.get()), + FROM_HERE, base::Bind(&Backend::Open, backend_->GetWeakPtr(), audio_manager_, &success, &completion_event)); completion_event.Wait(); @@ -251,7 +260,7 @@ VLOG(1) << __FUNCTION__ << " : " << this; backend_task_runner_->PostTaskAndReply( - FROM_HERE, base::Bind(&Backend::Close, base::Unretained(backend_.get())), + FROM_HERE, base::Bind(&Backend::Close, backend_->GetWeakPtr()), base::Bind(&CastAudioOutputStream::OnClosed, base::Unretained(this))); } @@ -261,7 +270,7 @@ source_callback_ = source_callback; backend_task_runner_->PostTask( - FROM_HERE, base::Bind(&Backend::Start, base::Unretained(backend_.get()))); + FROM_HERE, base::Bind(&Backend::Start, backend_->GetWeakPtr())); next_push_time_ = base::TimeTicks::Now(); if (!push_in_progress_) { @@ -279,7 +288,7 @@ source_callback_ = nullptr; backend_task_runner_->PostTask( - FROM_HERE, base::Bind(&Backend::Stop, base::Unretained(backend_.get()))); + FROM_HERE, base::Bind(&Backend::Stop, backend_->GetWeakPtr())); } void CastAudioOutputStream::SetVolume(double volume) { @@ -288,7 +297,7 @@ volume_ = volume; backend_task_runner_->PostTask( FROM_HERE, base::Bind(&Backend::SetVolume, - base::Unretained(backend_.get()), volume)); + backend_->GetWeakPtr(), volume)); } void CastAudioOutputStream::GetVolume(double* volume) { @@ -334,7 +343,7 @@ weak_factory_.GetWeakPtr())); backend_task_runner_->PostTask(FROM_HERE, base::Bind(&Backend::PushBuffer, - base::Unretained(backend_.get()), + backend_->GetWeakPtr(), decoder_buffer_, completion_cb)); }
diff --git a/chromecast/media/audio/cast_audio_output_stream.h b/chromecast/media/audio/cast_audio_output_stream.h index 6c54fce..18e92e9 100644 --- a/chromecast/media/audio/cast_audio_output_stream.h +++ b/chromecast/media/audio/cast_audio_output_stream.h
@@ -58,6 +58,7 @@ scoped_refptr<base::SingleThreadTaskRunner> backend_task_runner_; base::WeakPtrFactory<CastAudioOutputStream> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(CastAudioOutputStream); };
diff --git a/chromecast/media/cdm/browser_cdm_cast.cc b/chromecast/media/cdm/browser_cdm_cast.cc index 8d8ed64..9e7042d 100644 --- a/chromecast/media/cdm/browser_cdm_cast.cc +++ b/chromecast/media/cdm/browser_cdm_cast.cc
@@ -111,11 +111,6 @@ player_tracker_impl_->UnregisterPlayer(registration_id); } -::media::CdmContext* BrowserCdmCast::GetCdmContext() { - NOTREACHED(); - return nullptr; -} - void BrowserCdmCast::OnSessionMessage( const std::string& session_id, const std::vector<uint8_t>& message, @@ -231,11 +226,6 @@ base::Passed(BindPromiseToCurrentLoop(promise.Pass()))); } -::media::CdmContext* BrowserCdmCastUi::GetCdmContext() { - NOTREACHED(); - return nullptr; -} - // A default empty implementation for subclasses that don't need to provide // any key system specific initialization. void BrowserCdmCast::InitializeInternal() {
diff --git a/chromecast/media/cdm/browser_cdm_cast.h b/chromecast/media/cdm/browser_cdm_cast.h index b738b009..72fbce2d 100644 --- a/chromecast/media/cdm/browser_cdm_cast.h +++ b/chromecast/media/cdm/browser_cdm_cast.h
@@ -56,9 +56,6 @@ const base::Closure& cdm_unset_cb) override; void UnregisterPlayer(int registration_id) override; - // ::media::MediaKeys implementation: - ::media::CdmContext* GetCdmContext() override; - // Returns the decryption context needed to decrypt frames encrypted with // |key_id|. // Returns null if |key_id| is not available. @@ -66,6 +63,8 @@ const std::string& key_id) const = 0; protected: + ~BrowserCdmCast() override; + void OnSessionMessage(const std::string& session_id, const std::vector<uint8_t>& message, const GURL& destination_url, @@ -77,8 +76,6 @@ private: friend class BrowserCdmCastUi; - ~BrowserCdmCast() override; - // Allow subclasses to override to provide key sysytem specific // initialization. virtual void InitializeInternal(); @@ -129,7 +126,6 @@ scoped_ptr<::media::SimpleCdmPromise> promise) override; void RemoveSession(const std::string& session_id, scoped_ptr<::media::SimpleCdmPromise> promise) override; - ::media::CdmContext* GetCdmContext() override; scoped_refptr<BrowserCdmCast> browser_cdm_cast_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/chromecast/renderer/media/hole_frame_factory.cc b/chromecast/renderer/media/hole_frame_factory.cc index cd905d2..62dad08 100644 --- a/chromecast/renderer/media/hole_frame_factory.cc +++ b/chromecast/renderer/media/hole_frame_factory.cc
@@ -16,7 +16,7 @@ HoleFrameFactory::HoleFrameFactory( ::media::GpuVideoAcceleratorFactories* gpu_factories) - : gpu_factories_(gpu_factories), texture_(0), image_id_(0), sync_point_(0) { + : gpu_factories_(gpu_factories), texture_(0), image_id_(0) { if (gpu_factories_) { scoped_ptr<::media::GpuVideoAcceleratorFactories::ScopedGLContextLock> lock( gpu_factories_->GetGLContextLock()); @@ -32,7 +32,7 @@ gl->GenMailboxCHROMIUM(mailbox_.name); gl->ProduceTextureDirectCHROMIUM(texture_, GL_TEXTURE_2D, mailbox_.name); - sync_point_ = gl->InsertSyncPointCHROMIUM(); + sync_token_ = gpu::SyncToken(gl->InsertSyncPointCHROMIUM()); } } @@ -55,7 +55,7 @@ scoped_refptr<::media::VideoFrame> frame = ::media::VideoFrame::WrapNativeTexture( ::media::PIXEL_FORMAT_XRGB, - gpu::MailboxHolder(mailbox_, GL_TEXTURE_2D, sync_point_), + gpu::MailboxHolder(mailbox_, sync_token_, GL_TEXTURE_2D), ::media::VideoFrame::ReleaseMailboxCB(), size, // coded_size gfx::Rect(size), // visible rect
diff --git a/chromecast/renderer/media/hole_frame_factory.h b/chromecast/renderer/media/hole_frame_factory.h index 524f9653..febeef73 100644 --- a/chromecast/renderer/media/hole_frame_factory.h +++ b/chromecast/renderer/media/hole_frame_factory.h
@@ -9,6 +9,7 @@ #include "base/memory/ref_counted.h" #include "gpu/command_buffer/common/mailbox.h" +#include "gpu/command_buffer/common/sync_token.h" namespace gfx { class Size; @@ -36,9 +37,9 @@ private: ::media::GpuVideoAcceleratorFactories* gpu_factories_; gpu::Mailbox mailbox_; + gpu::SyncToken sync_token_; GLuint texture_; GLuint image_id_; - GLuint sync_point_; DISALLOW_COPY_AND_ASSIGN(HoleFrameFactory); };
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 375bda3..6558c09 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -7606.0.0 \ No newline at end of file +7609.0.0 \ No newline at end of file
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp index bce686c..d2f05119 100644 --- a/chromeos/chromeos.gyp +++ b/chromeos/chromeos.gyp
@@ -61,44 +61,6 @@ 'dbus/audio_node.h', 'dbus/blocking_method_caller.cc', 'dbus/blocking_method_caller.h', - 'dbus/bluetooth_adapter_client.cc', - 'dbus/bluetooth_adapter_client.h', - 'dbus/bluetooth_le_advertising_manager_client.cc', - 'dbus/bluetooth_le_advertising_manager_client.h', - 'dbus/bluetooth_le_advertisement_service_provider.cc', - 'dbus/bluetooth_le_advertisement_service_provider.h', - 'dbus/bluetooth_agent_manager_client.cc', - 'dbus/bluetooth_agent_manager_client.h', - 'dbus/bluetooth_agent_service_provider.cc', - 'dbus/bluetooth_agent_service_provider.h', - 'dbus/bluetooth_device_client.cc', - 'dbus/bluetooth_device_client.h', - 'dbus/bluetooth_gatt_characteristic_client.cc', - 'dbus/bluetooth_gatt_characteristic_client.h', - 'dbus/bluetooth_gatt_characteristic_service_provider.cc', - 'dbus/bluetooth_gatt_characteristic_service_provider.h', - 'dbus/bluetooth_gatt_descriptor_client.cc', - 'dbus/bluetooth_gatt_descriptor_client.h', - 'dbus/bluetooth_gatt_descriptor_service_provider.cc', - 'dbus/bluetooth_gatt_descriptor_service_provider.h', - 'dbus/bluetooth_gatt_manager_client.cc', - 'dbus/bluetooth_gatt_manager_client.h', - 'dbus/bluetooth_gatt_service_client.cc', - 'dbus/bluetooth_gatt_service_client.h', - 'dbus/bluetooth_gatt_service_service_provider.cc', - 'dbus/bluetooth_gatt_service_service_provider.h', - 'dbus/bluetooth_input_client.cc', - 'dbus/bluetooth_input_client.h', - 'dbus/bluetooth_media_client.cc', - 'dbus/bluetooth_media_client.h', - 'dbus/bluetooth_media_endpoint_service_provider.cc', - 'dbus/bluetooth_media_endpoint_service_provider.h', - 'dbus/bluetooth_media_transport_client.cc', - 'dbus/bluetooth_media_transport_client.h', - 'dbus/bluetooth_profile_manager_client.cc', - 'dbus/bluetooth_profile_manager_client.h', - 'dbus/bluetooth_profile_service_provider.cc', - 'dbus/bluetooth_profile_service_provider.h', 'dbus/cras_audio_client.cc', 'dbus/cras_audio_client.h', 'dbus/cros_disks_client.cc', @@ -124,44 +86,6 @@ 'dbus/fake_arc_bridge_client.h', 'dbus/fake_audio_dsp_client.cc', 'dbus/fake_audio_dsp_client.h', - 'dbus/fake_bluetooth_adapter_client.cc', - 'dbus/fake_bluetooth_adapter_client.h', - 'dbus/fake_bluetooth_le_advertising_manager_client.cc', - 'dbus/fake_bluetooth_le_advertising_manager_client.h', - 'dbus/fake_bluetooth_le_advertisement_service_provider.cc', - 'dbus/fake_bluetooth_le_advertisement_service_provider.h', - 'dbus/fake_bluetooth_agent_manager_client.cc', - 'dbus/fake_bluetooth_agent_manager_client.h', - 'dbus/fake_bluetooth_agent_service_provider.cc', - 'dbus/fake_bluetooth_agent_service_provider.h', - 'dbus/fake_bluetooth_device_client.cc', - 'dbus/fake_bluetooth_device_client.h', - 'dbus/fake_bluetooth_gatt_characteristic_client.cc', - 'dbus/fake_bluetooth_gatt_characteristic_client.h', - 'dbus/fake_bluetooth_gatt_characteristic_service_provider.cc', - 'dbus/fake_bluetooth_gatt_characteristic_service_provider.h', - 'dbus/fake_bluetooth_gatt_descriptor_client.cc', - 'dbus/fake_bluetooth_gatt_descriptor_client.h', - 'dbus/fake_bluetooth_gatt_descriptor_service_provider.cc', - 'dbus/fake_bluetooth_gatt_descriptor_service_provider.h', - 'dbus/fake_bluetooth_gatt_manager_client.cc', - 'dbus/fake_bluetooth_gatt_manager_client.h', - 'dbus/fake_bluetooth_gatt_service_client.cc', - 'dbus/fake_bluetooth_gatt_service_client.h', - 'dbus/fake_bluetooth_gatt_service_service_provider.cc', - 'dbus/fake_bluetooth_gatt_service_service_provider.h', - 'dbus/fake_bluetooth_input_client.cc', - 'dbus/fake_bluetooth_input_client.h', - 'dbus/fake_bluetooth_media_client.cc', - 'dbus/fake_bluetooth_media_client.h', - 'dbus/fake_bluetooth_media_endpoint_service_provider.cc', - 'dbus/fake_bluetooth_media_endpoint_service_provider.h', - 'dbus/fake_bluetooth_media_transport_client.cc', - 'dbus/fake_bluetooth_media_transport_client.h', - 'dbus/fake_bluetooth_profile_manager_client.cc', - 'dbus/fake_bluetooth_profile_manager_client.h', - 'dbus/fake_bluetooth_profile_service_provider.cc', - 'dbus/fake_bluetooth_profile_service_provider.h', 'dbus/fake_cras_audio_client.cc', 'dbus/fake_cras_audio_client.h', 'dbus/fake_cros_disks_client.cc',
diff --git a/chromeos/dbus/bluetooth_adapter_client.cc b/chromeos/dbus/bluetooth_adapter_client.cc deleted file mode 100644 index 064262e8..0000000 --- a/chromeos/dbus/bluetooth_adapter_client.cc +++ /dev/null
@@ -1,350 +0,0 @@ -// Copyright 2013 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 "chromeos/dbus/bluetooth_adapter_client.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "dbus/bus.h" -#include "dbus/message.h" -#include "dbus/object_manager.h" -#include "dbus/object_proxy.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -BluetoothAdapterClient::DiscoveryFilter::DiscoveryFilter() {} - -BluetoothAdapterClient::DiscoveryFilter::~DiscoveryFilter() {} - -void BluetoothAdapterClient::DiscoveryFilter::CopyFrom( - const DiscoveryFilter& filter) { - if (filter.rssi.get()) - rssi.reset(new int16_t(*filter.rssi)); - else - rssi.reset(); - - if (filter.pathloss.get()) - pathloss.reset(new uint16_t(*filter.pathloss)); - else - pathloss.reset(); - - if (filter.transport.get()) - transport.reset(new std::string(*filter.transport)); - else - transport.reset(); - - if (filter.uuids.get()) - uuids.reset(new std::vector<std::string>(*filter.uuids)); - else - uuids.reset(); -} - -const char BluetoothAdapterClient::kNoResponseError[] = - "org.chromium.Error.NoResponse"; -const char BluetoothAdapterClient::kUnknownAdapterError[] = - "org.chromium.Error.UnknownAdapter"; - -BluetoothAdapterClient::Properties::Properties( - dbus::ObjectProxy* object_proxy, - const std::string& interface_name, - const PropertyChangedCallback& callback) - : dbus::PropertySet(object_proxy, interface_name, callback) { - RegisterProperty(bluetooth_adapter::kAddressProperty, &address); - RegisterProperty(bluetooth_adapter::kNameProperty, &name); - RegisterProperty(bluetooth_adapter::kAliasProperty, &alias); - RegisterProperty(bluetooth_adapter::kClassProperty, &bluetooth_class); - RegisterProperty(bluetooth_adapter::kPoweredProperty, &powered); - RegisterProperty(bluetooth_adapter::kDiscoverableProperty, &discoverable); - RegisterProperty(bluetooth_adapter::kPairableProperty, &pairable); - RegisterProperty(bluetooth_adapter::kPairableTimeoutProperty, - &pairable_timeout); - RegisterProperty(bluetooth_adapter::kDiscoverableTimeoutProperty, - &discoverable_timeout); - RegisterProperty(bluetooth_adapter::kDiscoveringProperty, &discovering); - RegisterProperty(bluetooth_adapter::kUUIDsProperty, &uuids); - RegisterProperty(bluetooth_adapter::kModaliasProperty, &modalias); -} - -BluetoothAdapterClient::Properties::~Properties() {} - -// The BluetoothAdapterClient implementation used in production. -class BluetoothAdapterClientImpl : public BluetoothAdapterClient, - public dbus::ObjectManager::Interface { - public: - BluetoothAdapterClientImpl() - : object_manager_(NULL), weak_ptr_factory_(this) {} - - ~BluetoothAdapterClientImpl() override { - object_manager_->UnregisterInterface( - bluetooth_adapter::kBluetoothAdapterInterface); - } - - // BluetoothAdapterClient override. - void AddObserver(BluetoothAdapterClient::Observer* observer) override { - DCHECK(observer); - observers_.AddObserver(observer); - } - - // BluetoothAdapterClient override. - void RemoveObserver(BluetoothAdapterClient::Observer* observer) override { - DCHECK(observer); - observers_.RemoveObserver(observer); - } - - // Returns the list of adapter object paths known to the system. - std::vector<dbus::ObjectPath> GetAdapters() override { - return object_manager_->GetObjectsWithInterface( - bluetooth_adapter::kBluetoothAdapterInterface); - } - - // dbus::ObjectManager::Interface override. - dbus::PropertySet* CreateProperties( - dbus::ObjectProxy* object_proxy, - const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - Properties* properties = new Properties( - object_proxy, interface_name, - base::Bind(&BluetoothAdapterClientImpl::OnPropertyChanged, - weak_ptr_factory_.GetWeakPtr(), object_path)); - return static_cast<dbus::PropertySet*>(properties); - } - - // BluetoothAdapterClient override. - Properties* GetProperties(const dbus::ObjectPath& object_path) override { - return static_cast<Properties*>(object_manager_->GetProperties( - object_path, bluetooth_adapter::kBluetoothAdapterInterface)); - } - - // BluetoothAdapterClient override. - void StartDiscovery(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call(bluetooth_adapter::kBluetoothAdapterInterface, - bluetooth_adapter::kStartDiscovery); - - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(object_path); - if (!object_proxy) { - error_callback.Run(kUnknownAdapterError, ""); - return; - } - - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothAdapterClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothAdapterClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothAdapterClient override. - void StopDiscovery(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call(bluetooth_adapter::kBluetoothAdapterInterface, - bluetooth_adapter::kStopDiscovery); - - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(object_path); - if (!object_proxy) { - error_callback.Run(kUnknownAdapterError, ""); - return; - } - - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothAdapterClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothAdapterClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothAdapterClient override. - void RemoveDevice(const dbus::ObjectPath& object_path, - const dbus::ObjectPath& device_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call(bluetooth_adapter::kBluetoothAdapterInterface, - bluetooth_adapter::kRemoveDevice); - - dbus::MessageWriter writer(&method_call); - writer.AppendObjectPath(device_path); - - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(object_path); - if (!object_proxy) { - error_callback.Run(kUnknownAdapterError, ""); - return; - } - - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothAdapterClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothAdapterClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothAdapterClient override. - void SetDiscoveryFilter(const dbus::ObjectPath& object_path, - const DiscoveryFilter& discovery_filter, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call(bluetooth_adapter::kBluetoothAdapterInterface, - bluetooth_adapter::kSetDiscoveryFilter); - - dbus::MessageWriter writer(&method_call); - dbus::MessageWriter dict_writer(nullptr); - - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(object_path); - if (!object_proxy) { - error_callback.Run(kUnknownAdapterError, ""); - return; - } - - writer.OpenArray("{sv}", &dict_writer); - - if (discovery_filter.uuids.get()) { - std::vector<std::string>* uuids = discovery_filter.uuids.get(); - dbus::MessageWriter uuids_entry_writer(nullptr); - dict_writer.OpenDictEntry(&uuids_entry_writer); - uuids_entry_writer.AppendString( - bluetooth_adapter::kDiscoveryFilterParameterUUIDs); - - dbus::MessageWriter uuids_array_variant(nullptr); - uuids_entry_writer.OpenVariant("as", &uuids_array_variant); - dbus::MessageWriter uuids_array(nullptr); - uuids_array_variant.OpenArray("s", &uuids_array); - - for (auto& it : *uuids) - uuids_array.AppendString(it); - - uuids_array_variant.CloseContainer(&uuids_array); - uuids_entry_writer.CloseContainer(&uuids_array_variant); - dict_writer.CloseContainer(&uuids_entry_writer); - } - - if (discovery_filter.rssi.get()) { - dbus::MessageWriter rssi_entry_writer(nullptr); - dict_writer.OpenDictEntry(&rssi_entry_writer); - rssi_entry_writer.AppendString( - bluetooth_adapter::kDiscoveryFilterParameterRSSI); - rssi_entry_writer.AppendVariantOfInt16(*discovery_filter.rssi.get()); - dict_writer.CloseContainer(&rssi_entry_writer); - } - - if (discovery_filter.pathloss.get()) { - dbus::MessageWriter pathloss_entry_writer(nullptr); - dict_writer.OpenDictEntry(&pathloss_entry_writer); - pathloss_entry_writer.AppendString( - bluetooth_adapter::kDiscoveryFilterParameterPathloss); - pathloss_entry_writer.AppendVariantOfUint16( - *discovery_filter.pathloss.get()); - dict_writer.CloseContainer(&pathloss_entry_writer); - } - - if (discovery_filter.transport.get()) { - dbus::MessageWriter transport_entry_writer(nullptr); - dict_writer.OpenDictEntry(&transport_entry_writer); - transport_entry_writer.AppendString( - bluetooth_adapter::kDiscoveryFilterParameterTransport); - transport_entry_writer.AppendVariantOfString( - *discovery_filter.transport.get()); - dict_writer.CloseContainer(&transport_entry_writer); - } - - writer.CloseContainer(&dict_writer); - - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothAdapterClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothAdapterClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - protected: - void Init(dbus::Bus* bus) override { - object_manager_ = bus->GetObjectManager( - bluetooth_object_manager::kBluetoothObjectManagerServiceName, - dbus::ObjectPath( - bluetooth_object_manager::kBluetoothObjectManagerServicePath)); - object_manager_->RegisterInterface( - bluetooth_adapter::kBluetoothAdapterInterface, this); - } - - private: - // Called by dbus::ObjectManager when an object with the adapter interface - // is created. Informs observers. - void ObjectAdded(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, - AdapterAdded(object_path)); - } - - // Called by dbus::ObjectManager when an object with the adapter interface - // is removed. Informs observers. - void ObjectRemoved(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, - AdapterRemoved(object_path)); - } - - // Called by dbus::PropertySet when a property value is changed, - // either by result of a signal or response to a GetAll() or Get() - // call. Informs observers. - void OnPropertyChanged(const dbus::ObjectPath& object_path, - const std::string& property_name) { - FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, - AdapterPropertyChanged(object_path, property_name)); - } - - // Called when a response for successful method call is received. - void OnSuccess(const base::Closure& callback, dbus::Response* response) { - DCHECK(response); - callback.Run(); - } - - // Called when a response for a failed method call is received. - void OnError(const ErrorCallback& error_callback, - dbus::ErrorResponse* response) { - // Error response has optional error message argument. - std::string error_name; - std::string error_message; - if (response) { - dbus::MessageReader reader(response); - error_name = response->GetErrorName(); - reader.PopString(&error_message); - } else { - error_name = kNoResponseError; - error_message = ""; - } - error_callback.Run(error_name, error_message); - } - - dbus::ObjectManager* object_manager_; - - // List of observers interested in event notifications from us. - base::ObserverList<BluetoothAdapterClient::Observer> observers_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<BluetoothAdapterClientImpl> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterClientImpl); -}; - -BluetoothAdapterClient::BluetoothAdapterClient() {} - -BluetoothAdapterClient::~BluetoothAdapterClient() {} - -BluetoothAdapterClient* BluetoothAdapterClient::Create() { - return new BluetoothAdapterClientImpl; -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_adapter_client.h b/chromeos/dbus/bluetooth_adapter_client.h deleted file mode 100644 index c7237d74c..0000000 --- a/chromeos/dbus/bluetooth_adapter_client.h +++ /dev/null
@@ -1,184 +0,0 @@ -// Copyright 2013 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 CHROMEOS_DBUS_BLUETOOTH_ADAPTER_CLIENT_H_ -#define CHROMEOS_DBUS_BLUETOOTH_ADAPTER_CLIENT_H_ - -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/observer_list.h" -#include "base/values.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/dbus_client.h" -#include "dbus/object_path.h" -#include "dbus/property.h" - -namespace chromeos { - -// BluetoothAdapterClient is used to communicate with objects representing -// local Bluetooth Adapters. -class CHROMEOS_EXPORT BluetoothAdapterClient : public DBusClient { - public: - // A DiscoveryFilter represents a filter passed to the SetDiscoveryFilter - // method. - struct DiscoveryFilter { - DiscoveryFilter(); - ~DiscoveryFilter(); - - // Copy content of |filter| into this filter - void CopyFrom(const DiscoveryFilter& filter); - - scoped_ptr<std::vector<std::string>> uuids; - scoped_ptr<int16_t> rssi; - scoped_ptr<uint16_t> pathloss; - scoped_ptr<std::string> transport; - - DISALLOW_COPY_AND_ASSIGN(DiscoveryFilter); - }; - - // Structure of properties associated with bluetooth adapters. - struct Properties : public dbus::PropertySet { - // The Bluetooth device address of the adapter. Read-only. - dbus::Property<std::string> address; - - // The Bluetooth system name, generally derived from the hostname. - dbus::Property<std::string> name; - - // The Bluetooth friendly name of the adapter, unlike remote devices, - // this property can be changed to change the presentation for when - // the adapter is discoverable. - dbus::Property<std::string> alias; - - // The Bluetooth class of the adapter device. Read-only. - dbus::Property<uint32> bluetooth_class; - - // Whether the adapter radio is powered. - dbus::Property<bool> powered; - - // Whether the adapter is discoverable by other Bluetooth devices. - // |discovering_timeout| is used to automatically disable after a time - // period. - dbus::Property<bool> discoverable; - - // Whether the adapter accepts incoming pairing requests from other - // Bluetooth devices. |pairable_timeout| is used to automatically disable - // after a time period. - dbus::Property<bool> pairable; - - // The timeout in seconds to cease accepting incoming pairing requests - // after |pairable| is set to true. Zero means adapter remains pairable - // forever. - dbus::Property<uint32> pairable_timeout; - - // The timeout in seconds to cease the adapter being discoverable by - // other Bluetooth devices after |discoverable| is set to true. Zero - // means adapter remains discoverable forever. - dbus::Property<uint32> discoverable_timeout; - - // Indicates that the adapter is discovering other Bluetooth Devices. - // Read-only. Use StartDiscovery() to begin discovery. - dbus::Property<bool> discovering; - - // List of 128-bit UUIDs that represent the available local services. - // Read-only. - dbus::Property<std::vector<std::string>> uuids; - - // Local Device ID information in Linux kernel modalias format. Read-only. - dbus::Property<std::string> modalias; - - Properties(dbus::ObjectProxy* object_proxy, - const std::string& interface_name, - const PropertyChangedCallback& callback); - ~Properties() override; - }; - - // Interface for observing changes from a local bluetooth adapter. - class Observer { - public: - virtual ~Observer() {} - - // Called when the adapter with object path |object_path| is added to the - // system. - virtual void AdapterAdded(const dbus::ObjectPath& object_path) {} - - // Called when the adapter with object path |object_path| is removed from - // the system. - virtual void AdapterRemoved(const dbus::ObjectPath& object_path) {} - - // Called when the adapter with object path |object_path| has a - // change in value of the property named |property_name|. - virtual void AdapterPropertyChanged(const dbus::ObjectPath& object_path, - const std::string& property_name) {} - }; - - ~BluetoothAdapterClient() override; - - // Adds and removes observers for events on all local bluetooth - // adapters. Check the |object_path| parameter of observer methods to - // determine which adapter is issuing the event. - virtual void AddObserver(Observer* observer) = 0; - virtual void RemoveObserver(Observer* observer) = 0; - - // Returns the list of adapter object paths known to the system. - virtual std::vector<dbus::ObjectPath> GetAdapters() = 0; - - // Obtain the properties for the adapter with object path |object_path|, - // any values should be copied if needed. - virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; - - // The ErrorCallback is used by adapter methods to indicate failure. - // It receives two arguments: the name of the error in |error_name| and - // an optional message in |error_message|. - typedef base::Callback<void(const std::string& error_name, - const std::string& error_message)> ErrorCallback; - - // Starts a device discovery on the adapter with object path |object_path|. - virtual void StartDiscovery(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Cancels any previous device discovery on the adapter with object path - // |object_path|. - virtual void StopDiscovery(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Removes from the adapter with object path |object_path| the remote - // device with object path |object_path| from the list of known devices - // and discards any pairing information. - virtual void RemoveDevice(const dbus::ObjectPath& object_path, - const dbus::ObjectPath& device_path, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Sets the device discovery filter on the adapter with object path - // |object_path|. When this method is called with no filter parameter, filter - // is removed. - // SetDiscoveryFilter can be called before StartDiscovery. It is useful when - // client will create first discovery session, to ensure that proper scan - // will be started right after call to StartDiscovery. - virtual void SetDiscoveryFilter(const dbus::ObjectPath& object_path, - const DiscoveryFilter& discovery_filter, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Creates the instance. - static BluetoothAdapterClient* Create(); - - // Constants used to indicate exceptional error conditions. - static const char kNoResponseError[]; - static const char kUnknownAdapterError[]; - - protected: - BluetoothAdapterClient(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_ADAPTER_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_agent_manager_client.cc b/chromeos/dbus/bluetooth_agent_manager_client.cc deleted file mode 100644 index a5606a94..0000000 --- a/chromeos/dbus/bluetooth_agent_manager_client.cc +++ /dev/null
@@ -1,137 +0,0 @@ -// Copyright 2013 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 "chromeos/dbus/bluetooth_agent_manager_client.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "dbus/bus.h" -#include "dbus/message.h" -#include "dbus/object_proxy.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -const char BluetoothAgentManagerClient::kNoResponseError[] = - "org.chromium.Error.NoResponse"; - -// The BluetoothAgentManagerClient implementation used in production. -class BluetoothAgentManagerClientImpl : public BluetoothAgentManagerClient { - public: - BluetoothAgentManagerClientImpl() : weak_ptr_factory_(this) {} - - ~BluetoothAgentManagerClientImpl() override {} - - // BluetoothAgentManagerClient override. - void RegisterAgent(const dbus::ObjectPath& agent_path, - const std::string& capability, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call( - bluetooth_agent_manager::kBluetoothAgentManagerInterface, - bluetooth_agent_manager::kRegisterAgent); - - dbus::MessageWriter writer(&method_call); - writer.AppendObjectPath(agent_path); - writer.AppendString(capability); - - object_proxy_->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothAgentManagerClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothAgentManagerClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothAgentManagerClient override. - void UnregisterAgent(const dbus::ObjectPath& agent_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call( - bluetooth_agent_manager::kBluetoothAgentManagerInterface, - bluetooth_agent_manager::kUnregisterAgent); - - dbus::MessageWriter writer(&method_call); - writer.AppendObjectPath(agent_path); - - object_proxy_->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothAgentManagerClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothAgentManagerClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothAgentManagerClient override. - void RequestDefaultAgent(const dbus::ObjectPath& agent_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call( - bluetooth_agent_manager::kBluetoothAgentManagerInterface, - bluetooth_agent_manager::kRequestDefaultAgent); - - dbus::MessageWriter writer(&method_call); - writer.AppendObjectPath(agent_path); - - object_proxy_->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothAgentManagerClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothAgentManagerClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - protected: - void Init(dbus::Bus* bus) override { - DCHECK(bus); - object_proxy_ = bus->GetObjectProxy( - bluetooth_agent_manager::kBluetoothAgentManagerServiceName, - dbus::ObjectPath( - bluetooth_agent_manager::kBluetoothAgentManagerServicePath)); - } - - private: - // Called when a response for successful method call is received. - void OnSuccess(const base::Closure& callback, dbus::Response* response) { - DCHECK(response); - callback.Run(); - } - - // Called when a response for a failed method call is received. - void OnError(const ErrorCallback& error_callback, - dbus::ErrorResponse* response) { - // Error response has optional error message argument. - std::string error_name; - std::string error_message; - if (response) { - dbus::MessageReader reader(response); - error_name = response->GetErrorName(); - reader.PopString(&error_message); - } else { - error_name = kNoResponseError; - error_message = ""; - } - error_callback.Run(error_name, error_message); - } - - dbus::ObjectProxy* object_proxy_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<BluetoothAgentManagerClientImpl> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothAgentManagerClientImpl); -}; - -BluetoothAgentManagerClient::BluetoothAgentManagerClient() {} - -BluetoothAgentManagerClient::~BluetoothAgentManagerClient() {} - -BluetoothAgentManagerClient* BluetoothAgentManagerClient::Create() { - return new BluetoothAgentManagerClientImpl(); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_agent_manager_client.h b/chromeos/dbus/bluetooth_agent_manager_client.h deleted file mode 100644 index f43f4f8..0000000 --- a/chromeos/dbus/bluetooth_agent_manager_client.h +++ /dev/null
@@ -1,68 +0,0 @@ -// Copyright 2013 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 CHROMEOS_DBUS_BLUETOOTH_AGENT_MANAGER_CLIENT_H_ -#define CHROMEOS_DBUS_BLUETOOTH_AGENT_MANAGER_CLIENT_H_ - -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/values.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/dbus_client.h" -#include "dbus/object_path.h" - -namespace chromeos { - -// BluetoothAgentManagerClient is used to communicate with the agent manager -// object of the Bluetooth daemon. -class CHROMEOS_EXPORT BluetoothAgentManagerClient : public DBusClient { - public: - ~BluetoothAgentManagerClient() override; - - // The ErrorCallback is used by agent manager methods to indicate failure. - // It receives two arguments: the name of the error in |error_name| and - // an optional message in |error_message|. - typedef base::Callback<void(const std::string& error_name, - const std::string& error_message)> ErrorCallback; - - // Registers an agent within the local process at the D-bus object path - // |agent_path| with the remote agent manager. The agent is used for pairing - // and for authorization of incoming connection requests. |capability| - // specifies the input and display capabilities of the agent and should be - // one of the constants declared in the bluetooth_agent_manager:: namespace. - virtual void RegisterAgent(const dbus::ObjectPath& agent_path, - const std::string& capability, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Unregisters the agent with the D-Bus object path |agent_path| from the - // remote agent manager. - virtual void UnregisterAgent(const dbus::ObjectPath& agent_path, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Requests that the agent with the D-Bus object path |agent_path| be made - // the default. - virtual void RequestDefaultAgent(const dbus::ObjectPath& agent_path, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Creates the instance. - static BluetoothAgentManagerClient* Create(); - - // Constants used to indicate exceptional error conditions. - static const char kNoResponseError[]; - - protected: - BluetoothAgentManagerClient(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothAgentManagerClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_AGENT_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_agent_service_provider.cc b/chromeos/dbus/bluetooth_agent_service_provider.cc deleted file mode 100644 index 54ebeb3..0000000 --- a/chromeos/dbus/bluetooth_agent_service_provider.cc +++ /dev/null
@@ -1,444 +0,0 @@ -// Copyright 2013 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 "chromeos/dbus/bluetooth_agent_service_provider.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/threading/platform_thread.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_agent_service_provider.h" -#include "dbus/exported_object.h" -#include "dbus/message.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -// The BluetoothAgentServiceProvider implementation used in production. -class BluetoothAgentServiceProviderImpl : public BluetoothAgentServiceProvider { - public: - BluetoothAgentServiceProviderImpl(dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate) - : origin_thread_id_(base::PlatformThread::CurrentId()), - bus_(bus), - delegate_(delegate), - object_path_(object_path), - weak_ptr_factory_(this) { - VLOG(1) << "Creating Bluetooth Agent: " << object_path_.value(); - - exported_object_ = bus_->GetExportedObject(object_path_); - - exported_object_->ExportMethod( - bluetooth_agent::kBluetoothAgentInterface, bluetooth_agent::kRelease, - base::Bind(&BluetoothAgentServiceProviderImpl::Release, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - bluetooth_agent::kBluetoothAgentInterface, - bluetooth_agent::kRequestPinCode, - base::Bind(&BluetoothAgentServiceProviderImpl::RequestPinCode, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - bluetooth_agent::kBluetoothAgentInterface, - bluetooth_agent::kDisplayPinCode, - base::Bind(&BluetoothAgentServiceProviderImpl::DisplayPinCode, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - bluetooth_agent::kBluetoothAgentInterface, - bluetooth_agent::kRequestPasskey, - base::Bind(&BluetoothAgentServiceProviderImpl::RequestPasskey, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - bluetooth_agent::kBluetoothAgentInterface, - bluetooth_agent::kDisplayPasskey, - base::Bind(&BluetoothAgentServiceProviderImpl::DisplayPasskey, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - bluetooth_agent::kBluetoothAgentInterface, - bluetooth_agent::kRequestConfirmation, - base::Bind(&BluetoothAgentServiceProviderImpl::RequestConfirmation, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - bluetooth_agent::kBluetoothAgentInterface, - bluetooth_agent::kRequestAuthorization, - base::Bind(&BluetoothAgentServiceProviderImpl::RequestAuthorization, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - bluetooth_agent::kBluetoothAgentInterface, - bluetooth_agent::kAuthorizeService, - base::Bind(&BluetoothAgentServiceProviderImpl::AuthorizeService, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - bluetooth_agent::kBluetoothAgentInterface, bluetooth_agent::kCancel, - base::Bind(&BluetoothAgentServiceProviderImpl::Cancel, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - } - - ~BluetoothAgentServiceProviderImpl() override { - VLOG(1) << "Cleaning up Bluetooth Agent: " << object_path_.value(); - - // Unregister the object path so we can reuse with a new agent. - bus_->UnregisterExportedObject(object_path_); - } - - private: - // Returns true if the current thread is on the origin thread. - bool OnOriginThread() { - return base::PlatformThread::CurrentId() == origin_thread_id_; - } - - // Called by dbus:: when the agent is unregistered from the Bluetooth - // daemon, generally at the end of a pairing request. - void Release(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - delegate_->Released(); - - response_sender.Run(dbus::Response::FromMethodCall(method_call)); - } - - // Called by dbus:: when the Bluetooth daemon requires a PIN Code for - // device authentication. - void RequestPinCode(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - dbus::MessageReader reader(method_call); - dbus::ObjectPath device_path; - if (!reader.PopObjectPath(&device_path)) { - LOG(WARNING) << "RequestPinCode called with incorrect paramters: " - << method_call->ToString(); - return; - } - - Delegate::PinCodeCallback callback = base::Bind( - &BluetoothAgentServiceProviderImpl::OnPinCode, - weak_ptr_factory_.GetWeakPtr(), method_call, response_sender); - - delegate_->RequestPinCode(device_path, callback); - } - - // Called by dbus:: when the Bluetooth daemon requires that the user - // enter a PIN Code into the remote device so that it may be - // authenticated. - void DisplayPinCode(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - dbus::MessageReader reader(method_call); - dbus::ObjectPath device_path; - std::string pincode; - if (!reader.PopObjectPath(&device_path) || !reader.PopString(&pincode)) { - LOG(WARNING) << "DisplayPinCode called with incorrect paramters: " - << method_call->ToString(); - return; - } - - delegate_->DisplayPinCode(device_path, pincode); - - response_sender.Run(dbus::Response::FromMethodCall(method_call)); - } - - // Called by dbus:: when the Bluetooth daemon requires a Passkey for - // device authentication. - void RequestPasskey(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - dbus::MessageReader reader(method_call); - dbus::ObjectPath device_path; - if (!reader.PopObjectPath(&device_path)) { - LOG(WARNING) << "RequestPasskey called with incorrect paramters: " - << method_call->ToString(); - return; - } - - Delegate::PasskeyCallback callback = base::Bind( - &BluetoothAgentServiceProviderImpl::OnPasskey, - weak_ptr_factory_.GetWeakPtr(), method_call, response_sender); - - delegate_->RequestPasskey(device_path, callback); - } - - // Called by dbus:: when the Bluetooth daemon requires that the user - // enter a Passkey into the remote device so that it may be - // authenticated. - void DisplayPasskey(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - dbus::MessageReader reader(method_call); - dbus::ObjectPath device_path; - uint32 passkey; - uint16 entered; - if (!reader.PopObjectPath(&device_path) || !reader.PopUint32(&passkey) || - !reader.PopUint16(&entered)) { - LOG(WARNING) << "DisplayPasskey called with incorrect paramters: " - << method_call->ToString(); - return; - } - - delegate_->DisplayPasskey(device_path, passkey, entered); - - response_sender.Run(dbus::Response::FromMethodCall(method_call)); - } - - // Called by dbus:: when the Bluetooth daemon requires that the user - // confirm that a Passkey is displayed on the screen of the remote - // device so that it may be authenticated. - void RequestConfirmation( - dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - dbus::MessageReader reader(method_call); - dbus::ObjectPath device_path; - uint32 passkey; - if (!reader.PopObjectPath(&device_path) || !reader.PopUint32(&passkey)) { - LOG(WARNING) << "RequestConfirmation called with incorrect paramters: " - << method_call->ToString(); - return; - } - - Delegate::ConfirmationCallback callback = base::Bind( - &BluetoothAgentServiceProviderImpl::OnConfirmation, - weak_ptr_factory_.GetWeakPtr(), method_call, response_sender); - - delegate_->RequestConfirmation(device_path, passkey, callback); - } - - // Called by dbus:: when the Bluetooth daemon requires that the user - // confirm an incoming just-works pairing. - void RequestAuthorization( - dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - dbus::MessageReader reader(method_call); - dbus::ObjectPath device_path; - if (!reader.PopObjectPath(&device_path)) { - LOG(WARNING) << "RequestAuthorization called with incorrect paramters: " - << method_call->ToString(); - return; - } - - Delegate::ConfirmationCallback callback = base::Bind( - &BluetoothAgentServiceProviderImpl::OnConfirmation, - weak_ptr_factory_.GetWeakPtr(), method_call, response_sender); - - delegate_->RequestAuthorization(device_path, callback); - } - - // Called by dbus:: when the Bluetooth daemon requires that the user - // confirm that that a remote device is authorized to connect to a service - // UUID. - void AuthorizeService(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - dbus::MessageReader reader(method_call); - dbus::ObjectPath device_path; - std::string uuid; - if (!reader.PopObjectPath(&device_path) || !reader.PopString(&uuid)) { - LOG(WARNING) << "AuthorizeService called with incorrect paramters: " - << method_call->ToString(); - return; - } - - Delegate::ConfirmationCallback callback = base::Bind( - &BluetoothAgentServiceProviderImpl::OnConfirmation, - weak_ptr_factory_.GetWeakPtr(), method_call, response_sender); - - delegate_->AuthorizeService(device_path, uuid, callback); - } - - // Called by dbus:: when the request failed before a reply was returned - // from the device. - void Cancel(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - delegate_->Cancel(); - - response_sender.Run(dbus::Response::FromMethodCall(method_call)); - } - - // Called by dbus:: when a method is exported. - void OnExported(const std::string& interface_name, - const std::string& method_name, - bool success) { - LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "." - << method_name; - } - - // Called by the Delegate to response to a method requesting a PIN code. - void OnPinCode(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender, - Delegate::Status status, - const std::string& pincode) { - DCHECK(OnOriginThread()); - - switch (status) { - case Delegate::SUCCESS: { - scoped_ptr<dbus::Response> response( - dbus::Response::FromMethodCall(method_call)); - dbus::MessageWriter writer(response.get()); - writer.AppendString(pincode); - response_sender.Run(response.Pass()); - break; - } - case Delegate::REJECTED: { - response_sender.Run(dbus::ErrorResponse::FromMethodCall( - method_call, bluetooth_agent::kErrorRejected, "rejected")); - break; - } - case Delegate::CANCELLED: { - response_sender.Run(dbus::ErrorResponse::FromMethodCall( - method_call, bluetooth_agent::kErrorCanceled, "canceled")); - break; - } - default: - NOTREACHED() << "Unexpected status code from delegate: " << status; - } - } - - // Called by the Delegate to response to a method requesting a Passkey. - void OnPasskey(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender, - Delegate::Status status, - uint32 passkey) { - DCHECK(OnOriginThread()); - - switch (status) { - case Delegate::SUCCESS: { - scoped_ptr<dbus::Response> response( - dbus::Response::FromMethodCall(method_call)); - dbus::MessageWriter writer(response.get()); - writer.AppendUint32(passkey); - response_sender.Run(response.Pass()); - break; - } - case Delegate::REJECTED: { - response_sender.Run(dbus::ErrorResponse::FromMethodCall( - method_call, bluetooth_agent::kErrorRejected, "rejected")); - break; - } - case Delegate::CANCELLED: { - response_sender.Run(dbus::ErrorResponse::FromMethodCall( - method_call, bluetooth_agent::kErrorCanceled, "canceled")); - break; - } - default: - NOTREACHED() << "Unexpected status code from delegate: " << status; - } - } - - // Called by the Delegate in response to a method requiring confirmation. - void OnConfirmation(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender, - Delegate::Status status) { - DCHECK(OnOriginThread()); - - switch (status) { - case Delegate::SUCCESS: { - response_sender.Run(dbus::Response::FromMethodCall(method_call)); - break; - } - case Delegate::REJECTED: { - response_sender.Run(dbus::ErrorResponse::FromMethodCall( - method_call, bluetooth_agent::kErrorRejected, "rejected")); - break; - } - case Delegate::CANCELLED: { - response_sender.Run(dbus::ErrorResponse::FromMethodCall( - method_call, bluetooth_agent::kErrorCanceled, "canceled")); - break; - } - default: - NOTREACHED() << "Unexpected status code from delegate: " << status; - } - } - - // Origin thread (i.e. the UI thread in production). - base::PlatformThreadId origin_thread_id_; - - // D-Bus bus object is exported on, not owned by this object and must - // outlive it. - dbus::Bus* bus_; - - // All incoming method calls are passed on to the Delegate and a callback - // passed to generate the reply. |delegate_| is generally the object that - // owns this one, and must outlive it. - Delegate* delegate_; - - // D-Bus object path of object we are exporting, kept so we can unregister - // again in our destructor. - dbus::ObjectPath object_path_; - - // D-Bus object we are exporting, owned by this object. - scoped_refptr<dbus::ExportedObject> exported_object_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<BluetoothAgentServiceProviderImpl> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothAgentServiceProviderImpl); -}; - -BluetoothAgentServiceProvider::BluetoothAgentServiceProvider() {} - -BluetoothAgentServiceProvider::~BluetoothAgentServiceProvider() {} - -// static -BluetoothAgentServiceProvider* BluetoothAgentServiceProvider::Create( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate) { - if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) { - return new BluetoothAgentServiceProviderImpl(bus, object_path, delegate); - } else { - return new FakeBluetoothAgentServiceProvider(object_path, delegate); - } -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_agent_service_provider.h b/chromeos/dbus/bluetooth_agent_service_provider.h deleted file mode 100644 index 8e84fa5..0000000 --- a/chromeos/dbus/bluetooth_agent_service_provider.h +++ /dev/null
@@ -1,178 +0,0 @@ -// Copyright 2013 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 CHROMEOS_DBUS_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_ -#define CHROMEOS_DBUS_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_ - -#include <string> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "chromeos/chromeos_export.h" -#include "dbus/bus.h" -#include "dbus/object_path.h" - -namespace chromeos { - -// BluetoothAgentServiceProvider is used to provide a D-Bus object that -// the bluetooth daemon can communicate with during a remote device pairing -// request. -// -// Instantiate with a chosen D-Bus object path and delegate object, and pass -// the D-Bus object path as the |agent_path| argument to the -// chromeos::BluetoothAgentManagerClient::RegisterAgent() method. -// -// After initiating the pairing process with a device, using the -// chromeos::BluetoothDeviceClient::Pair() method, the Bluetooth daemon will -// make calls to this agent object and they will be passed on to your Delegate -// object for handling. Responses should be returned using the callbacks -// supplied to those methods. -class CHROMEOS_EXPORT BluetoothAgentServiceProvider { - public: - // Interface for reacting to agent requests. - class Delegate { - public: - virtual ~Delegate() {} - - // Possible status values that may be returned to callbacks. Success - // indicates that a pincode or passkey has been obtained, or permission - // granted; rejected indicates the user rejected the request or denied - // permission; cancelled indicates the user cancelled the request - // without confirming either way. - enum Status { SUCCESS, REJECTED, CANCELLED }; - - // The PinCodeCallback is used for the RequestPinCode() method, it should - // be called with two arguments, the |status| of the request (success, - // rejected or cancelled) and the |pincode| requested. - typedef base::Callback<void(Status, const std::string&)> PinCodeCallback; - - // The PasskeyCallback is used for the RequestPasskey() method, it should - // be called with two arguments, the |status| of the request (success, - // rejected or cancelled) and the |passkey| requested, a numeric in the - // range 0-999999, - typedef base::Callback<void(Status, uint32)> PasskeyCallback; - - // The ConfirmationCallback is used for methods which request confirmation - // or authorization, it should be called with one argument, the |status| - // of the request (success, rejected or cancelled). - typedef base::Callback<void(Status)> ConfirmationCallback; - - // This method will be called when the agent is unregistered from the - // Bluetooth daemon, generally at the end of a pairing request. It may be - // used to perform cleanup tasks. This corresponds to the - // org.bluez.Agent1.Release method and is renamed to avoid a conflict - // with base::Refcounted<T>. - virtual void Released() = 0; - - // This method will be called when the Bluetooth daemon requires a - // PIN Code for authentication of the device with object path |device_path|, - // the agent should obtain the code from the user and call |callback| - // to provide it, or indicate rejection or cancellation of the request. - // - // PIN Codes are generally required for Bluetooth 2.0 and earlier devices - // for which there is no automatic pairing or special handling. - virtual void RequestPinCode(const dbus::ObjectPath& device_path, - const PinCodeCallback& callback) = 0; - - // This method will be called when the Bluetooth daemon requires that the - // user enter the PIN code |pincode| into the device with object path - // |device_path| so that it may be authenticated. The Cancel() method - // will be called to dismiss the display once pairing is complete or - // cancelled. - // - // This is used for Bluetooth 2.0 and earlier keyboard devices, the - // |pincode| will always be a six-digit numeric in the range 000000-999999 - // for compatibilty with later specifications. - virtual void DisplayPinCode(const dbus::ObjectPath& device_path, - const std::string& pincode) = 0; - - // This method will be called when the Bluetooth daemon requires a - // Passkey for authentication of the device with object path |device_path|, - // the agent should obtain the passkey from the user (a numeric in the - // range 0-999999) and call |callback| to provide it, or indicate - // rejection or cancellation of the request. - // - // Passkeys are generally required for Bluetooth 2.1 and later devices - // which cannot provide input or display on their own, and don't accept - // passkey-less pairing. - virtual void RequestPasskey(const dbus::ObjectPath& device_path, - const PasskeyCallback& callback) = 0; - - // This method will be called when the Bluetooth daemon requires that the - // user enter the Passkey |passkey| into the device with object path - // |device_path| so that it may be authenticated. The Cancel() method - // will be called to dismiss the display once pairing is complete or - // cancelled. - // - // This is used for Bluetooth 2.1 and later devices that support input - // but not display, such as keyboards. The Passkey is a numeric in the - // range 0-999999 and should be always presented zero-padded to six - // digits. - // - // As the user enters the passkey onto the device, |entered| will be - // updated to reflect the number of digits entered so far. - virtual void DisplayPasskey(const dbus::ObjectPath& device_path, - uint32 passkey, - uint16 entered) = 0; - - // This method will be called when the Bluetooth daemon requires that the - // user confirm that the Passkey |passkey| is displayed on the screen - // of the device with object path |object_path| so that it may be - // authenticated. The agent should display to the user and ask for - // confirmation, then call |callback| to provide their response (success, - // rejected or cancelled). - // - // This is used for Bluetooth 2.1 and later devices that support display, - // such as other computers or phones. The Passkey is a numeric in the - // range 0-999999 and should be always present zero-padded to six - // digits. - virtual void RequestConfirmation(const dbus::ObjectPath& device_path, - uint32 passkey, - const ConfirmationCallback& callback) = 0; - - // This method will be called when the Bluetooth daemon requires - // authorization of an incoming pairing attempt from the device with object - // path |device_path| that would have otherwised triggered the just-works - // pairing model. - // - // The agent should confirm the incoming pairing with the user and call - // |callback| to provide their response (success, rejected or cancelled). - virtual void RequestAuthorization(const dbus::ObjectPath& device_path, - const ConfirmationCallback& callback) = 0; - - // This method will be called when the Bluetooth daemon requires that the - // user confirm that the device with object path |object_path| is - // authorized to connect to the service with UUID |uuid|. The agent should - // confirm with the user and call |callback| to provide their response - // (success, rejected or cancelled). - virtual void AuthorizeService(const dbus::ObjectPath& device_path, - const std::string& uuid, - const ConfirmationCallback& callback) = 0; - - // This method will be called by the Bluetooth daemon to indicate that - // the request failed before a reply was returned from the device. - virtual void Cancel() = 0; - }; - - virtual ~BluetoothAgentServiceProvider(); - - // Creates the instance where |bus| is the D-Bus bus connection to export - // the object onto, |object_path| is the object path that it should have - // and |delegate| is the object to which all method calls will be passed - // and responses generated from. - static BluetoothAgentServiceProvider* Create( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate); - - protected: - BluetoothAgentServiceProvider(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothAgentServiceProvider); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/bluetooth_device_client.cc b/chromeos/dbus/bluetooth_device_client.cc deleted file mode 100644 index 8fcf74b..0000000 --- a/chromeos/dbus/bluetooth_device_client.cc +++ /dev/null
@@ -1,379 +0,0 @@ -// Copyright 2013 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 "chromeos/dbus/bluetooth_device_client.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/stl_util.h" -#include "dbus/bus.h" -#include "dbus/message.h" -#include "dbus/object_manager.h" -#include "dbus/object_proxy.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -namespace { - -// Value returned for the the RSSI or TX power if it cannot be read. -const int kUnknownPower = 127; - -} // namespace - -const char BluetoothDeviceClient::kNoResponseError[] = - "org.chromium.Error.NoResponse"; -const char BluetoothDeviceClient::kUnknownDeviceError[] = - "org.chromium.Error.UnknownDevice"; - -BluetoothDeviceClient::Properties::Properties( - dbus::ObjectProxy* object_proxy, - const std::string& interface_name, - const PropertyChangedCallback& callback) - : dbus::PropertySet(object_proxy, interface_name, callback) { - RegisterProperty(bluetooth_device::kAddressProperty, &address); - RegisterProperty(bluetooth_device::kNameProperty, &name); - RegisterProperty(bluetooth_device::kIconProperty, &icon); - RegisterProperty(bluetooth_device::kClassProperty, &bluetooth_class); - RegisterProperty(bluetooth_device::kAppearanceProperty, &appearance); - RegisterProperty(bluetooth_device::kUUIDsProperty, &uuids); - RegisterProperty(bluetooth_device::kPairedProperty, &paired); - RegisterProperty(bluetooth_device::kConnectedProperty, &connected); - RegisterProperty(bluetooth_device::kTrustedProperty, &trusted); - RegisterProperty(bluetooth_device::kBlockedProperty, &blocked); - RegisterProperty(bluetooth_device::kAliasProperty, &alias); - RegisterProperty(bluetooth_device::kAdapterProperty, &adapter); - RegisterProperty(bluetooth_device::kLegacyPairingProperty, &legacy_pairing); - RegisterProperty(bluetooth_device::kModaliasProperty, &modalias); - RegisterProperty(bluetooth_device::kRSSIProperty, &rssi); - RegisterProperty(bluetooth_device::kTxPowerProperty, &tx_power); - RegisterProperty(bluetooth_device::kGattServicesProperty, &gatt_services); -} - -BluetoothDeviceClient::Properties::~Properties() {} - -// The BluetoothDeviceClient implementation used in production. -class BluetoothDeviceClientImpl : public BluetoothDeviceClient, - public dbus::ObjectManager::Interface { - public: - BluetoothDeviceClientImpl() - : object_manager_(NULL), weak_ptr_factory_(this) {} - - ~BluetoothDeviceClientImpl() override { - object_manager_->UnregisterInterface( - bluetooth_device::kBluetoothDeviceInterface); - } - - // BluetoothDeviceClient override. - void AddObserver(BluetoothDeviceClient::Observer* observer) override { - DCHECK(observer); - observers_.AddObserver(observer); - } - - // BluetoothDeviceClient override. - void RemoveObserver(BluetoothDeviceClient::Observer* observer) override { - DCHECK(observer); - observers_.RemoveObserver(observer); - } - - // dbus::ObjectManager::Interface override. - dbus::PropertySet* CreateProperties( - dbus::ObjectProxy* object_proxy, - const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - Properties* properties = - new Properties(object_proxy, interface_name, - base::Bind(&BluetoothDeviceClientImpl::OnPropertyChanged, - weak_ptr_factory_.GetWeakPtr(), object_path)); - return static_cast<dbus::PropertySet*>(properties); - } - - // BluetoothDeviceClient override. - std::vector<dbus::ObjectPath> GetDevicesForAdapter( - const dbus::ObjectPath& adapter_path) override { - std::vector<dbus::ObjectPath> object_paths, device_paths; - device_paths = object_manager_->GetObjectsWithInterface( - bluetooth_device::kBluetoothDeviceInterface); - for (std::vector<dbus::ObjectPath>::iterator iter = device_paths.begin(); - iter != device_paths.end(); ++iter) { - Properties* properties = GetProperties(*iter); - if (properties->adapter.value() == adapter_path) - object_paths.push_back(*iter); - } - return object_paths; - } - - // BluetoothDeviceClient override. - Properties* GetProperties(const dbus::ObjectPath& object_path) override { - return static_cast<Properties*>(object_manager_->GetProperties( - object_path, bluetooth_device::kBluetoothDeviceInterface)); - } - - // BluetoothDeviceClient override. - void Connect(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface, - bluetooth_device::kConnect); - - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(object_path); - if (!object_proxy) { - error_callback.Run(kUnknownDeviceError, ""); - return; - } - - // Connect may take an arbitrary length of time, so use no timeout. - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_INFINITE, - base::Bind(&BluetoothDeviceClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothDeviceClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothDeviceClient override. - void Disconnect(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface, - bluetooth_device::kDisconnect); - - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(object_path); - if (!object_proxy) { - error_callback.Run(kUnknownDeviceError, ""); - return; - } - - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothDeviceClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothDeviceClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothDeviceClient override. - void ConnectProfile(const dbus::ObjectPath& object_path, - const std::string& uuid, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface, - bluetooth_device::kConnectProfile); - - dbus::MessageWriter writer(&method_call); - writer.AppendString(uuid); - - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(object_path); - if (!object_proxy) { - error_callback.Run(kUnknownDeviceError, ""); - return; - } - - // Connect may take an arbitrary length of time, so use no timeout. - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_INFINITE, - base::Bind(&BluetoothDeviceClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothDeviceClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothDeviceClient override. - void DisconnectProfile(const dbus::ObjectPath& object_path, - const std::string& uuid, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface, - bluetooth_device::kDisconnectProfile); - - dbus::MessageWriter writer(&method_call); - writer.AppendString(uuid); - - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(object_path); - if (!object_proxy) { - error_callback.Run(kUnknownDeviceError, ""); - return; - } - - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothDeviceClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothDeviceClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothDeviceClient override. - void Pair(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface, - bluetooth_device::kPair); - - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(object_path); - if (!object_proxy) { - error_callback.Run(kUnknownDeviceError, ""); - return; - } - - // Pairing may take an arbitrary length of time, so use no timeout. - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_INFINITE, - base::Bind(&BluetoothDeviceClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothDeviceClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothDeviceClient override. - void CancelPairing(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface, - bluetooth_device::kCancelPairing); - - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(object_path); - if (!object_proxy) { - error_callback.Run(kUnknownDeviceError, ""); - return; - } - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothDeviceClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothDeviceClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothDeviceClient override. - void GetConnInfo(const dbus::ObjectPath& object_path, - const ConnInfoCallback& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call( - bluetooth_plugin_device::kBluetoothPluginInterface, - bluetooth_plugin_device::kGetConnInfo); - - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(object_path); - if (!object_proxy) { - error_callback.Run(kUnknownDeviceError, ""); - return; - } - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothDeviceClientImpl::OnGetConnInfoSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothDeviceClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - protected: - void Init(dbus::Bus* bus) override { - object_manager_ = bus->GetObjectManager( - bluetooth_object_manager::kBluetoothObjectManagerServiceName, - dbus::ObjectPath( - bluetooth_object_manager::kBluetoothObjectManagerServicePath)); - object_manager_->RegisterInterface( - bluetooth_device::kBluetoothDeviceInterface, this); - } - - private: - // Called by dbus::ObjectManager when an object with the device interface - // is created. Informs observers. - void ObjectAdded(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, - DeviceAdded(object_path)); - } - - // Called by dbus::ObjectManager when an object with the device interface - // is removed. Informs observers. - void ObjectRemoved(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, - DeviceRemoved(object_path)); - } - - // Called by BluetoothPropertySet when a property value is changed, - // either by result of a signal or response to a GetAll() or Get() - // call. Informs observers. - void OnPropertyChanged(const dbus::ObjectPath& object_path, - const std::string& property_name) { - FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, - DevicePropertyChanged(object_path, property_name)); - } - - // Called when a response for successful method call is received. - void OnSuccess(const base::Closure& callback, dbus::Response* response) { - DCHECK(response); - callback.Run(); - } - - // Called when a response for the GetConnInfo method is received. - void OnGetConnInfoSuccess(const ConnInfoCallback& callback, - dbus::Response* response) { - int16 rssi = kUnknownPower; - int16 transmit_power = kUnknownPower; - int16 max_transmit_power = kUnknownPower; - - if (!response) { - LOG(ERROR) << "GetConnInfo succeeded, but no response received."; - callback.Run(rssi, transmit_power, max_transmit_power); - return; - } - - dbus::MessageReader reader(response); - if (!reader.PopInt16(&rssi) || !reader.PopInt16(&transmit_power) || - !reader.PopInt16(&max_transmit_power)) { - LOG(ERROR) << "Arguments for GetConnInfo invalid."; - } - callback.Run(rssi, transmit_power, max_transmit_power); - } - - // Called when a response for a failed method call is received. - void OnError(const ErrorCallback& error_callback, - dbus::ErrorResponse* response) { - // Error response has optional error message argument. - std::string error_name; - std::string error_message; - if (response) { - dbus::MessageReader reader(response); - error_name = response->GetErrorName(); - reader.PopString(&error_message); - } else { - error_name = kNoResponseError; - error_message = ""; - } - error_callback.Run(error_name, error_message); - } - - dbus::ObjectManager* object_manager_; - - // List of observers interested in event notifications from us. - base::ObserverList<BluetoothDeviceClient::Observer> observers_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<BluetoothDeviceClientImpl> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceClientImpl); -}; - -BluetoothDeviceClient::BluetoothDeviceClient() {} - -BluetoothDeviceClient::~BluetoothDeviceClient() {} - -BluetoothDeviceClient* BluetoothDeviceClient::Create() { - return new BluetoothDeviceClientImpl(); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_device_client.h b/chromeos/dbus/bluetooth_device_client.h deleted file mode 100644 index e9c2905..0000000 --- a/chromeos/dbus/bluetooth_device_client.h +++ /dev/null
@@ -1,212 +0,0 @@ -// Copyright 2013 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 CHROMEOS_DBUS_BLUETOOTH_DEVICE_CLIENT_H_ -#define CHROMEOS_DBUS_BLUETOOTH_DEVICE_CLIENT_H_ - -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/observer_list.h" -#include "base/values.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/dbus_client.h" -#include "dbus/object_path.h" -#include "dbus/property.h" - -namespace chromeos { - -// BluetoothDeviceClient is used to communicate with objects representing -// remote Bluetooth Devices. -class CHROMEOS_EXPORT BluetoothDeviceClient : public DBusClient { - public: - // Structure of properties associated with bluetooth devices. - struct Properties : public dbus::PropertySet { - // The Bluetooth device address of the device. Read-only. - dbus::Property<std::string> address; - - // The Bluetooth friendly name of the device. Read-only, to give a - // different local name, use the |alias| property. - dbus::Property<std::string> name; - - // Proposed icon name for the device according to the freedesktop.org - // icon naming specification. Read-only. - dbus::Property<std::string> icon; - - // The Bluetooth class of the device. Read-only. - dbus::Property<uint32> bluetooth_class; - - // The GAP external appearance of the device. Read-only. - dbus::Property<uint16> appearance; - - // Unique numeric identifier for the vendor of the device. Read-only. - dbus::Property<uint16> vendor; - - // List of 128-bit UUIDs that represent the available remote services. - // Read-only. - dbus::Property<std::vector<std::string>> uuids; - - // Transmitted power level. This field is avaliable only for LE devices - // that include this field in AD. Read-only. - dbus::Property<int16> tx_power; - - // Indicates that the device is currently paired. Read-only. - dbus::Property<bool> paired; - - // Indicates that the device is currently connected. Read-only. - dbus::Property<bool> connected; - - // Whether the device is trusted, and connections should be always - // accepted and attempted when the device is visible. - dbus::Property<bool> trusted; - - // Whether the device is blocked, connections will be always rejected - // and the device will not be visible. - dbus::Property<bool> blocked; - - // Local alias for the device, if not set, is equal to |name|. - dbus::Property<std::string> alias; - - // Object path of the adapter the device belongs to. Read-only. - dbus::Property<dbus::ObjectPath> adapter; - - // Indicates whether the device is likely to only support pre-2.1 - // PIN Code pairing rather than 2.1 Secure Simple Pairing, this can - // give false positives. Read-only. - dbus::Property<bool> legacy_pairing; - - // Remote Device ID information in Linux kernel modalias format. Read-only. - dbus::Property<std::string> modalias; - - // Received signal strength indicator that is set when the device is - // discovered during inquiry. Read-only. - dbus::Property<int16> rssi; - - // List of GATT service object paths. Each referenced object exports the - // org.bluez.GattService1 interface and represents a remote GATT service. - // This property will be updated once all remote GATT services of this - // device have been discovered and exported over D-Bus. Read-only. - dbus::Property<std::vector<dbus::ObjectPath>> gatt_services; - - Properties(dbus::ObjectProxy* object_proxy, - const std::string& interface_name, - const PropertyChangedCallback& callback); - ~Properties() override; - }; - - // Interface for observing changes from a remote bluetooth device. - class Observer { - public: - virtual ~Observer() {} - - // Called when the remote device with object path |object_path| is added - // to the set of known devices. - virtual void DeviceAdded(const dbus::ObjectPath& object_path) {} - - // Called when the remote device with object path |object_path| is removed - // from the set of known devices. - virtual void DeviceRemoved(const dbus::ObjectPath& object_path) {} - - // Called when the device with object path |object_path| has a - // change in value of the property named |property_name|. - virtual void DevicePropertyChanged(const dbus::ObjectPath& object_path, - const std::string& property_name) {} - }; - - ~BluetoothDeviceClient() override; - - // Adds and removes observers for events on all remote bluetooth - // devices. Check the |object_path| parameter of observer methods to - // determine which device is issuing the event. - virtual void AddObserver(Observer* observer) = 0; - virtual void RemoveObserver(Observer* observer) = 0; - - // Returns the list of device object paths associated with the given adapter - // identified by the D-Bus object path |adapter_path|. - virtual std::vector<dbus::ObjectPath> GetDevicesForAdapter( - const dbus::ObjectPath& adapter_path) = 0; - - // Obtain the properties for the device with object path |object_path|, - // any values should be copied if needed. - virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; - - // The ErrorCallback is used by device methods to indicate failure. - // It receives two arguments: the name of the error in |error_name| and - // an optional message in |error_message|. - typedef base::Callback<void(const std::string& error_name, - const std::string& error_message)> ErrorCallback; - - // Connects to the device with object path |object_path|, connecting any - // profiles that can be connected to and have been flagged as auto-connected; - // may be used to connect additional profiles for an already connected device, - // and succeeds if at least one profile is connected. - virtual void Connect(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Disconnects the device with object path |object_path|, terminating - // the low-level ACL connection and any profiles using it. - virtual void Disconnect(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Connects to the profile |uuid| on the device with object path - // |object_path|, provided that the profile has been registered with a - // handler on the local device. - virtual void ConnectProfile(const dbus::ObjectPath& object_path, - const std::string& uuid, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Disconnects from the profile |uuid| on the device with object path - // |object_path|. - virtual void DisconnectProfile(const dbus::ObjectPath& object_path, - const std::string& uuid, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Initiates pairing with the device with object path |object_path| and - // retrieves all SDP records or GATT primary services. An agent must be - // registered to handle the pairing request. - virtual void Pair(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Cancels an in-progress pairing with the device with object path - // |object_path| initiated by Pair(). - virtual void CancelPairing(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // The callback invoked for a successful GetConnInfo API call with the - // RSSI, TX power, and maximum TX power of the current connection. - typedef base::Callback<void(int16 rssi, - int16 transmit_power, - int16 max_transmit_power)> ConnInfoCallback; - - // Returns the RSSI, TX power, and maximum TX power of a connection to the - // device with object path |object_path|. If the device is not connected, then - // an error will be returned. - virtual void GetConnInfo(const dbus::ObjectPath& object_path, - const ConnInfoCallback& callback, - const ErrorCallback& error_callback) = 0; - - // Creates the instance. - static BluetoothDeviceClient* Create(); - - // Constants used to indicate exceptional error conditions. - static const char kNoResponseError[]; - static const char kUnknownDeviceError[]; - - protected: - BluetoothDeviceClient(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_DEVICE_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_gatt_characteristic_client.cc b/chromeos/dbus/bluetooth_gatt_characteristic_client.cc deleted file mode 100644 index 8e241e6..0000000 --- a/chromeos/dbus/bluetooth_gatt_characteristic_client.cc +++ /dev/null
@@ -1,303 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/bluetooth_gatt_characteristic_client.h" - -#include "base/bind.h" -#include "base/memory/weak_ptr.h" -#include "base/observer_list.h" -#include "dbus/bus.h" -#include "dbus/object_manager.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -namespace { - -// TODO(armansito): Move this constant to cros_system_api. -const char kValueProperty[] = "Value"; - -} // namespace - -// static -const char BluetoothGattCharacteristicClient::kNoResponseError[] = - "org.chromium.Error.NoResponse"; -// static -const char BluetoothGattCharacteristicClient::kUnknownCharacteristicError[] = - "org.chromium.Error.UnknownCharacteristic"; - -BluetoothGattCharacteristicClient::Properties::Properties( - dbus::ObjectProxy* object_proxy, - const std::string& interface_name, - const PropertyChangedCallback& callback) - : dbus::PropertySet(object_proxy, interface_name, callback) { - RegisterProperty(bluetooth_gatt_characteristic::kUUIDProperty, &uuid); - RegisterProperty(bluetooth_gatt_characteristic::kServiceProperty, &service); - RegisterProperty(kValueProperty, &value); - RegisterProperty(bluetooth_gatt_characteristic::kNotifyingProperty, - ¬ifying); - RegisterProperty(bluetooth_gatt_characteristic::kFlagsProperty, &flags); - RegisterProperty(bluetooth_gatt_characteristic::kDescriptorsProperty, - &descriptors); -} - -BluetoothGattCharacteristicClient::Properties::~Properties() {} - -// The BluetoothGattCharacteristicClient implementation used in production. -class BluetoothGattCharacteristicClientImpl - : public BluetoothGattCharacteristicClient, - public dbus::ObjectManager::Interface { - public: - BluetoothGattCharacteristicClientImpl() - : object_manager_(NULL), weak_ptr_factory_(this) {} - - ~BluetoothGattCharacteristicClientImpl() override { - object_manager_->UnregisterInterface( - bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface); - } - - // BluetoothGattCharacteristicClient override. - void AddObserver( - BluetoothGattCharacteristicClient::Observer* observer) override { - DCHECK(observer); - observers_.AddObserver(observer); - } - - // BluetoothGattCharacteristicClient override. - void RemoveObserver( - BluetoothGattCharacteristicClient::Observer* observer) override { - DCHECK(observer); - observers_.RemoveObserver(observer); - } - - // BluetoothGattCharacteristicClient override. - std::vector<dbus::ObjectPath> GetCharacteristics() override { - DCHECK(object_manager_); - return object_manager_->GetObjectsWithInterface( - bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface); - } - - // BluetoothGattCharacteristicClient override. - Properties* GetProperties(const dbus::ObjectPath& object_path) override { - DCHECK(object_manager_); - return static_cast<Properties*>(object_manager_->GetProperties( - object_path, - bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface)); - } - - // BluetoothGattCharacteristicClient override. - void ReadValue(const dbus::ObjectPath& object_path, - const ValueCallback& callback, - const ErrorCallback& error_callback) override { - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(object_path); - if (!object_proxy) { - error_callback.Run(kUnknownCharacteristicError, ""); - return; - } - - dbus::MethodCall method_call( - bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, - bluetooth_gatt_characteristic::kReadValue); - - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothGattCharacteristicClientImpl::OnValueSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothGattCharacteristicClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothGattCharacteristicClient override. - void WriteValue(const dbus::ObjectPath& object_path, - const std::vector<uint8>& value, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(object_path); - if (!object_proxy) { - error_callback.Run(kUnknownCharacteristicError, ""); - return; - } - - dbus::MethodCall method_call( - bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, - bluetooth_gatt_characteristic::kWriteValue); - dbus::MessageWriter writer(&method_call); - writer.AppendArrayOfBytes(value.data(), value.size()); - - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothGattCharacteristicClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothGattCharacteristicClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothGattCharacteristicClient override. - void StartNotify(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(object_path); - if (!object_proxy) { - error_callback.Run(kUnknownCharacteristicError, ""); - return; - } - - dbus::MethodCall method_call( - bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, - bluetooth_gatt_characteristic::kStartNotify); - - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothGattCharacteristicClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothGattCharacteristicClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothGattCharacteristicClient override. - void StopNotify(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(object_path); - if (!object_proxy) { - error_callback.Run(kUnknownCharacteristicError, ""); - return; - } - - dbus::MethodCall method_call( - bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, - bluetooth_gatt_characteristic::kStopNotify); - - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothGattCharacteristicClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothGattCharacteristicClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // dbus::ObjectManager::Interface override. - dbus::PropertySet* CreateProperties( - dbus::ObjectProxy* object_proxy, - const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - Properties* properties = new Properties( - object_proxy, interface_name, - base::Bind(&BluetoothGattCharacteristicClientImpl::OnPropertyChanged, - weak_ptr_factory_.GetWeakPtr(), object_path)); - return static_cast<dbus::PropertySet*>(properties); - } - - // dbus::ObjectManager::Interface override. - void ObjectAdded(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - VLOG(2) << "Remote GATT characteristic added: " << object_path.value(); - FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, - GattCharacteristicAdded(object_path)); - } - - // dbus::ObjectManager::Interface override. - void ObjectRemoved(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - VLOG(2) << "Remote GATT characteristic removed: " << object_path.value(); - FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, - GattCharacteristicRemoved(object_path)); - } - - protected: - // chromeos::DBusClient override. - void Init(dbus::Bus* bus) override { - object_manager_ = bus->GetObjectManager( - bluetooth_object_manager::kBluetoothObjectManagerServiceName, - dbus::ObjectPath( - bluetooth_object_manager::kBluetoothObjectManagerServicePath)); - object_manager_->RegisterInterface( - bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, - this); - } - - private: - // Called by dbus::PropertySet when a property value is changed, either by - // result of a signal or response to a GetAll() or Get() call. Informs - // observers. - virtual void OnPropertyChanged(const dbus::ObjectPath& object_path, - const std::string& property_name) { - VLOG(2) << "Remote GATT characteristic property changed: " - << object_path.value() << ": " << property_name; - FOR_EACH_OBSERVER( - BluetoothGattCharacteristicClient::Observer, observers_, - GattCharacteristicPropertyChanged(object_path, property_name)); - } - - // Called when a response for successful method call is received. - void OnSuccess(const base::Closure& callback, dbus::Response* response) { - DCHECK(response); - callback.Run(); - } - - // Called when a characteristic value response for a successful method call - // is received. - void OnValueSuccess(const ValueCallback& callback, dbus::Response* response) { - DCHECK(response); - dbus::MessageReader reader(response); - - const uint8* bytes = NULL; - size_t length = 0; - - if (!reader.PopArrayOfBytes(&bytes, &length)) - VLOG(2) << "Error reading array of bytes in ValueCallback"; - - std::vector<uint8> value; - - if (bytes) - value.assign(bytes, bytes + length); - - callback.Run(value); - } - - // Called when a response for a failed method call is received. - void OnError(const ErrorCallback& error_callback, - dbus::ErrorResponse* response) { - // Error response has optional error message argument. - std::string error_name; - std::string error_message; - if (response) { - dbus::MessageReader reader(response); - error_name = response->GetErrorName(); - reader.PopString(&error_message); - } else { - error_name = kNoResponseError; - error_message = ""; - } - error_callback.Run(error_name, error_message); - } - - dbus::ObjectManager* object_manager_; - - // List of observers interested in event notifications from us. - base::ObserverList<BluetoothGattCharacteristicClient::Observer> observers_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<BluetoothGattCharacteristicClientImpl> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothGattCharacteristicClientImpl); -}; - -BluetoothGattCharacteristicClient::BluetoothGattCharacteristicClient() {} - -BluetoothGattCharacteristicClient::~BluetoothGattCharacteristicClient() {} - -// static -BluetoothGattCharacteristicClient* BluetoothGattCharacteristicClient::Create() { - return new BluetoothGattCharacteristicClientImpl(); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_gatt_characteristic_client.h b/chromeos/dbus/bluetooth_gatt_characteristic_client.h deleted file mode 100644 index b040b56..0000000 --- a/chromeos/dbus/bluetooth_gatt_characteristic_client.h +++ /dev/null
@@ -1,143 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_ -#define CHROMEOS_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_ - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/dbus_client.h" -#include "dbus/object_path.h" -#include "dbus/property.h" - -namespace chromeos { - -// BluetoothGattCharacteristicClient is used to communicate with remote GATT -// characteristic objects exposed by the Bluetooth daemon. -class CHROMEOS_EXPORT BluetoothGattCharacteristicClient : public DBusClient { - public: - // Structure of properties associated with GATT characteristics. - struct Properties : public dbus::PropertySet { - // The 128-bit characteristic UUID. [read-only] - dbus::Property<std::string> uuid; - - // Object path of the GATT service the characteristic belongs to. - // [read-only] - dbus::Property<dbus::ObjectPath> service; - - // The cached value of the characteristic. This property gets updated only - // after a successful read request and when a notification or indication is - // received. [read-only] - dbus::Property<std::vector<uint8_t>> value; - - // Whether or not this characteristic is currently sending ValueUpdated - // signals. [read-only] - dbus::Property<bool> notifying; - - // List of flags representing the GATT "Characteristic Properties bit field" - // and properties read from the GATT "Characteristic Extended Properties" - // descriptor bit field. [read-only, optional] - dbus::Property<std::vector<std::string>> flags; - - // Array of object paths representing the descriptors of this - // characteristic. [read-only] - dbus::Property<std::vector<dbus::ObjectPath>> descriptors; - - Properties(dbus::ObjectProxy* object_proxy, - const std::string& interface_name, - const PropertyChangedCallback& callback); - ~Properties() override; - }; - - // Interface for observing changes from a remote GATT characteristic. - class Observer { - public: - virtual ~Observer() {} - - // Called when the GATT characteristic with object path |object_path| is - // added to the system. - virtual void GattCharacteristicAdded(const dbus::ObjectPath& object_path) {} - - // Called when the GATT characteristic with object path |object_path| is - // removed from the system. - virtual void GattCharacteristicRemoved( - const dbus::ObjectPath& object_path) {} - - // Called when the GATT characteristic with object path |object_path| has a - // change in the value of the property named |property_name|. - virtual void GattCharacteristicPropertyChanged( - const dbus::ObjectPath& object_path, - const std::string& property_name) {} - }; - - // Callbacks used to report the result of asynchronous methods. - typedef base::Callback<void(const std::string& error_name, - const std::string& error_message)> ErrorCallback; - typedef base::Callback<void(const std::vector<uint8>& value)> ValueCallback; - - ~BluetoothGattCharacteristicClient() override; - - // Adds and removes observers for events on all remote GATT characteristics. - // Check the |object_path| parameter of observer methods to determine which - // GATT characteristic is issuing the event. - virtual void AddObserver(Observer* observer) = 0; - virtual void RemoveObserver(Observer* observer) = 0; - - // Returns the list of GATT characteristic object paths known to the system. - virtual std::vector<dbus::ObjectPath> GetCharacteristics() = 0; - - // Obtain the properties for the GATT characteristic with object path - // |object_path|. Values should be copied if needed. - virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; - - // Issues a request to read the value of GATT characteristic with object path - // |object_path| and returns the value in |callback| on success. On error, - // invokes |error_callback|. - virtual void ReadValue(const dbus::ObjectPath& object_path, - const ValueCallback& callback, - const ErrorCallback& error_callback) = 0; - - // Issues a request to write the value of GATT characteristic with object path - // |object_path| with value |value|. Invokes |callback| on success and - // |error_callback| on failure. - virtual void WriteValue(const dbus::ObjectPath& object_path, - const std::vector<uint8>& value, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Starts a notification session from this characteristic with object path - // |object_path| if it supports value notifications or indications. Invokes - // |callback| on success and |error_callback| on failure. - virtual void StartNotify(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Cancels any previous StartNotify transaction for characteristic with - // object path |object_path|. Invokes |callback| on success and - // |error_callback| on failure. - virtual void StopNotify(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Creates the instance. - static BluetoothGattCharacteristicClient* Create(); - - // Constants used to indicate exceptional error conditions. - static const char kNoResponseError[]; - static const char kUnknownCharacteristicError[]; - - protected: - BluetoothGattCharacteristicClient(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothGattCharacteristicClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_gatt_characteristic_service_provider.cc b/chromeos/dbus/bluetooth_gatt_characteristic_service_provider.cc deleted file mode 100644 index 856e60da..0000000 --- a/chromeos/dbus/bluetooth_gatt_characteristic_service_provider.cc +++ /dev/null
@@ -1,464 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/bluetooth_gatt_characteristic_service_provider.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/memory/weak_ptr.h" -#include "base/strings/string_util.h" -#include "base/threading/platform_thread.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.h" -#include "dbus/exported_object.h" -#include "dbus/message.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { -namespace { -const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs"; -const char kErrorPropertyReadOnly[] = - "org.freedesktop.DBus.Error.PropertyReadOnly"; -const char kErrorFailed[] = "org.freedesktop.DBus.Error.Failed"; -} // namespace - -// The BluetoothGattCharacteristicServiceProvider implementation used in -// production. -class BluetoothGattCharacteristicServiceProviderImpl - : public BluetoothGattCharacteristicServiceProvider { - public: - BluetoothGattCharacteristicServiceProviderImpl( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate, - const std::string& uuid, - const std::vector<std::string>& flags, - const std::vector<std::string>& permissions, - const dbus::ObjectPath& service_path) - : origin_thread_id_(base::PlatformThread::CurrentId()), - uuid_(uuid), - bus_(bus), - delegate_(delegate), - object_path_(object_path), - service_path_(service_path), - weak_ptr_factory_(this) { - VLOG(1) << "Created Bluetooth GATT characteristic: " << object_path.value() - << " UUID: " << uuid; - DCHECK(bus_); - DCHECK(delegate_); - DCHECK(!uuid_.empty()); - DCHECK(object_path_.IsValid()); - DCHECK(service_path_.IsValid()); - DCHECK(base::StartsWith(object_path_.value(), service_path_.value() + "/", - base::CompareCase::SENSITIVE)); - - exported_object_ = bus_->GetExportedObject(object_path_); - - exported_object_->ExportMethod( - dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet, - base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::Get, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesSet, - base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::Set, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll, - base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::GetAll, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - } - - ~BluetoothGattCharacteristicServiceProviderImpl() override { - VLOG(1) << "Cleaning up Bluetooth GATT characteristic: " - << object_path_.value(); - bus_->UnregisterExportedObject(object_path_); - } - - // BluetoothGattCharacteristicServiceProvider override. - void SendValueChanged(const std::vector<uint8>& value) override { - VLOG(2) << "Emitting a PropertiesChanged signal for characteristic value."; - dbus::Signal signal(dbus::kDBusPropertiesInterface, - dbus::kDBusPropertiesChangedSignal); - dbus::MessageWriter writer(&signal); - dbus::MessageWriter array_writer(NULL); - dbus::MessageWriter dict_entry_writer(NULL); - dbus::MessageWriter variant_writer(NULL); - - // interface_name - writer.AppendString( - bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface); - - // changed_properties - writer.OpenArray("{sv}", &array_writer); - array_writer.OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString( - bluetooth_gatt_characteristic::kValueProperty); - dict_entry_writer.OpenVariant("ay", &variant_writer); - variant_writer.AppendArrayOfBytes(value.data(), value.size()); - dict_entry_writer.CloseContainer(&variant_writer); - array_writer.CloseContainer(&dict_entry_writer); - writer.CloseContainer(&array_writer); - - // invalidated_properties. - writer.OpenArray("s", &array_writer); - writer.CloseContainer(&array_writer); - - exported_object_->SendSignal(&signal); - } - - private: - // Returns true if the current thread is on the origin thread. - bool OnOriginThread() { - return base::PlatformThread::CurrentId() == origin_thread_id_; - } - - // Called by dbus:: when the Bluetooth daemon fetches a single property of - // the characteristic. - void Get(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(2) << "BluetoothGattCharacteristicServiceProvider::Get: " - << object_path_.value(); - DCHECK(OnOriginThread()); - - dbus::MessageReader reader(method_call); - - std::string interface_name; - std::string property_name; - if (!reader.PopString(&interface_name) || - !reader.PopString(&property_name) || reader.HasMoreData()) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, - "Expected 'ss'."); - response_sender.Run(error_response.Pass()); - return; - } - - // Only the GATT characteristic interface is supported. - if (interface_name != - bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidArgs, - "No such interface: '" + interface_name + "'."); - response_sender.Run(error_response.Pass()); - return; - } - - // If getting the "Value" property, obtain the value from the delegate. - if (property_name == bluetooth_gatt_characteristic::kValueProperty) { - DCHECK(delegate_); - delegate_->GetCharacteristicValue( - base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnGet, - weak_ptr_factory_.GetWeakPtr(), method_call, - response_sender), - base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure, - weak_ptr_factory_.GetWeakPtr(), method_call, - response_sender)); - return; - } - - scoped_ptr<dbus::Response> response = - dbus::Response::FromMethodCall(method_call); - dbus::MessageWriter writer(response.get()); - dbus::MessageWriter variant_writer(NULL); - - // TODO(armansito): Process the "Flags" and "Permissions" properties below. - if (property_name == bluetooth_gatt_characteristic::kUUIDProperty) { - writer.OpenVariant("s", &variant_writer); - variant_writer.AppendString(uuid_); - writer.CloseContainer(&variant_writer); - } else if (property_name == - bluetooth_gatt_characteristic::kServiceProperty) { - writer.OpenVariant("o", &variant_writer); - variant_writer.AppendObjectPath(service_path_); - writer.CloseContainer(&variant_writer); - } else { - response = dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidArgs, - "No such property: '" + property_name + "'."); - } - - response_sender.Run(response.Pass()); - } - - // Called by dbus:: when the Bluetooth daemon sets a single property of the - // characteristic. - void Set(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(2) << "BluetoothGattCharacteristicServiceProvider::Set: " - << object_path_.value(); - DCHECK(OnOriginThread()); - - dbus::MessageReader reader(method_call); - - std::string interface_name; - std::string property_name; - dbus::MessageReader variant_reader(NULL); - if (!reader.PopString(&interface_name) || - !reader.PopString(&property_name) || - !reader.PopVariant(&variant_reader) || reader.HasMoreData()) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, - "Expected 'ssv'."); - response_sender.Run(error_response.Pass()); - return; - } - - // Only the GATT characteristic interface is allowed. - if (interface_name != - bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidArgs, - "No such interface: '" + interface_name + "'."); - response_sender.Run(error_response.Pass()); - return; - } - - // Only the "Value" property is writeable. - if (property_name != bluetooth_gatt_characteristic::kValueProperty) { - std::string error_name; - std::string error_message; - if (property_name == bluetooth_gatt_characteristic::kUUIDProperty || - property_name == bluetooth_gatt_characteristic::kServiceProperty) { - error_name = kErrorPropertyReadOnly; - error_message = "Read-only property: '" + property_name + "'."; - } else { - error_name = kErrorInvalidArgs; - error_message = "No such property: '" + property_name + "'."; - } - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall(method_call, error_name, - error_message); - response_sender.Run(error_response.Pass()); - return; - } - - // Obtain the value. - const uint8* bytes = NULL; - size_t length = 0; - if (!variant_reader.PopArrayOfBytes(&bytes, &length)) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidArgs, - "Property '" + property_name + "' has type 'ay'."); - response_sender.Run(error_response.Pass()); - return; - } - - // Pass the set request onto the delegate. - std::vector<uint8> value(bytes, bytes + length); - DCHECK(delegate_); - delegate_->SetCharacteristicValue( - value, - base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnSet, - weak_ptr_factory_.GetWeakPtr(), method_call, - response_sender), - base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure, - weak_ptr_factory_.GetWeakPtr(), method_call, - response_sender)); - } - - // Called by dbus:: when the Bluetooth daemon fetches all properties of the - // characteristic. - void GetAll(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(2) << "BluetoothGattCharacteristicServiceProvider::GetAll: " - << object_path_.value(); - DCHECK(OnOriginThread()); - - dbus::MessageReader reader(method_call); - - std::string interface_name; - if (!reader.PopString(&interface_name) || reader.HasMoreData()) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, - "Expected 's'."); - response_sender.Run(error_response.Pass()); - return; - } - - // Only the GATT characteristic interface is supported. - if (interface_name != - bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidArgs, - "No such interface: '" + interface_name + "'."); - response_sender.Run(error_response.Pass()); - return; - } - - // Try to obtain the value from the delegate. We will construct the - // response in the success callback. - DCHECK(delegate_); - delegate_->GetCharacteristicValue( - base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnGetAll, - weak_ptr_factory_.GetWeakPtr(), method_call, - response_sender), - base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure, - weak_ptr_factory_.GetWeakPtr(), method_call, - response_sender)); - } - - // Called by dbus:: when a method is exported. - void OnExported(const std::string& interface_name, - const std::string& method_name, - bool success) { - LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "." - << method_name; - } - - // Called by the Delegate in response to a method to call to get all - // properties, in which the delegate has successfully returned the - // characteristic value. - void OnGetAll(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender, - const std::vector<uint8>& value) { - VLOG(2) << "Characteristic value obtained from delegate. Responding to " - << "GetAll."; - - scoped_ptr<dbus::Response> response = - dbus::Response::FromMethodCall(method_call); - dbus::MessageWriter writer(response.get()); - dbus::MessageWriter array_writer(NULL); - dbus::MessageWriter dict_entry_writer(NULL); - dbus::MessageWriter variant_writer(NULL); - - writer.OpenArray("{sv}", &array_writer); - - array_writer.OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString( - bluetooth_gatt_characteristic::kUUIDProperty); - dict_entry_writer.AppendVariantOfString(uuid_); - array_writer.CloseContainer(&dict_entry_writer); - - array_writer.OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString( - bluetooth_gatt_characteristic::kServiceProperty); - dict_entry_writer.AppendVariantOfObjectPath(service_path_); - array_writer.CloseContainer(&dict_entry_writer); - - array_writer.OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString( - bluetooth_gatt_characteristic::kValueProperty); - dict_entry_writer.OpenVariant("ay", &variant_writer); - variant_writer.AppendArrayOfBytes(value.data(), value.size()); - dict_entry_writer.CloseContainer(&variant_writer); - array_writer.CloseContainer(&dict_entry_writer); - - // TODO(armansito): Process Flags & Permissions properties. - - writer.CloseContainer(&array_writer); - - response_sender.Run(response.Pass()); - } - - // Called by the Delegate in response to a successful method call to get the - // characteristic value. - void OnGet(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender, - const std::vector<uint8>& value) { - VLOG(2) << "Returning characteristic value obtained from delegate."; - scoped_ptr<dbus::Response> response = - dbus::Response::FromMethodCall(method_call); - dbus::MessageWriter writer(response.get()); - dbus::MessageWriter variant_writer(NULL); - - writer.OpenVariant("ay", &variant_writer); - variant_writer.AppendArrayOfBytes(value.data(), value.size()); - writer.CloseContainer(&variant_writer); - - response_sender.Run(response.Pass()); - } - - // Called by the Delegate in response to a successful method call to set the - // characteristic value. - void OnSet(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(2) << "Successfully set characteristic value. Return success."; - response_sender.Run(dbus::Response::FromMethodCall(method_call)); - } - - // Called by the Delegate in response to a failed method call to get or set - // the characteristic value. - void OnFailure(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(2) << "Failed to get/set characteristic value. Report error."; - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall( - method_call, kErrorFailed, - "Failed to get/set characteristic value."); - response_sender.Run(error_response.Pass()); - } - - // Origin thread (i.e. the UI thread in production). - base::PlatformThreadId origin_thread_id_; - - // 128-bit characteristic UUID of this object. - std::string uuid_; - - // D-Bus bus object is exported on, not owned by this object and must - // outlive it. - dbus::Bus* bus_; - - // Incoming methods to get and set the "Value" property are passed on to the - // delegate and callbacks passed to generate a reply. |delegate_| is generally - // the object that owns this one and must outlive it. - Delegate* delegate_; - - // D-Bus object path of object we are exporting, kept so we can unregister - // again in our destructor. - dbus::ObjectPath object_path_; - - // Object path of the GATT service that the exported characteristic belongs - // to. - dbus::ObjectPath service_path_; - - // D-Bus object we are exporting, owned by this object. - scoped_refptr<dbus::ExportedObject> exported_object_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<BluetoothGattCharacteristicServiceProviderImpl> - weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothGattCharacteristicServiceProviderImpl); -}; - -BluetoothGattCharacteristicServiceProvider:: - BluetoothGattCharacteristicServiceProvider() {} - -BluetoothGattCharacteristicServiceProvider:: - ~BluetoothGattCharacteristicServiceProvider() {} - -// static -BluetoothGattCharacteristicServiceProvider* -BluetoothGattCharacteristicServiceProvider::Create( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate, - const std::string& uuid, - const std::vector<std::string>& flags, - const std::vector<std::string>& permissions, - const dbus::ObjectPath& service_path) { - if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) { - return new BluetoothGattCharacteristicServiceProviderImpl( - bus, object_path, delegate, uuid, flags, permissions, service_path); - } - return new FakeBluetoothGattCharacteristicServiceProvider( - object_path, delegate, uuid, flags, permissions, service_path); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_gatt_characteristic_service_provider.h b/chromeos/dbus/bluetooth_gatt_characteristic_service_provider.h deleted file mode 100644 index 174a908..0000000 --- a/chromeos/dbus/bluetooth_gatt_characteristic_service_provider.h +++ /dev/null
@@ -1,113 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_ -#define CHROMEOS_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_ - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "chromeos/chromeos_export.h" -#include "dbus/bus.h" -#include "dbus/object_path.h" - -namespace chromeos { - -// BluetoothGattCharacteristicServiceProvider is used to provide a D-Bus object -// that represents a local GATT characteristic that the Bluetooth daemon can -// communicate with. -// -// Instantiate with a chosen D-Bus object path, delegate, and other fields. -// The Bluetooth daemon communicates with a GATT characteristic using the -// standard DBus.Properties interface. While most properties of the GATT -// characteristic interface are read-only and don't change throughout the -// life-time of the object, the "Value" property is both writeable and its -// value can change. Both Get and Set operations performed on the "Value" -// property are delegated to the Delegate object, an instance of which is -// mandatory during initialization. In addition, a "SendValueChanged" method is -// provided, which emits a DBus.Properties.PropertyChanged signal for the -// "Value" property. -class CHROMEOS_EXPORT BluetoothGattCharacteristicServiceProvider { - public: - // Interface for reacting to GATT characteristic value requests. - class Delegate { - public: - virtual ~Delegate() {} - - // ValueCallback is used for methods that require a characteristic value - // to be returned. - typedef base::Callback<void(const std::vector<uint8>&)> ValueCallback; - - // ErrorCallback is used by methods to report failure. - typedef base::Closure ErrorCallback; - - // This method will be called when a remote device requests to read the - // value of the exported GATT characteristic. Invoke |callback| with a value - // to return that value to the requester. Invoke |error_callback| to report - // a failure to read the value. This can happen, for example, if the - // characteristic has no read permission set. Either callback should be - // invoked after a reasonable amount of time, since the request will time - // out if left pending for too long. - virtual void GetCharacteristicValue( - const ValueCallback& callback, - const ErrorCallback& error_callback) = 0; - - // This method will be called, when a remote device requests to write the - // value of the exported GATT characteristic. Invoke |callback| to report - // that the value was successfully written. Invoke |error_callback| to - // report a failure to write the value. This can happen, for example, if the - // characteristic has no write permission set. Either callback should be - // invoked after a reasonable amount of time, since the request will time - // out if left pending for too long. - // - // The delegate should use this method to perform any side-effects that may - // occur based on the set value and potentially send a property changed - // signal to notify the Bluetooth daemon that the value has changed. - virtual void SetCharacteristicValue( - const std::vector<uint8>& value, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - }; - - virtual ~BluetoothGattCharacteristicServiceProvider(); - - // Send a PropertyChanged signal to notify the Bluetooth daemon that the value - // of the "Value" property has changed to |value|. - virtual void SendValueChanged(const std::vector<uint8>& value) = 0; - - // Creates the instance, where |bus| is the D-Bus bus connection to export - // the object onto, |uuid| is the 128-bit GATT characteristic UUID, - // |flags| is the list of GATT characteristic properties, |permissions| is the - // list of attribute permissions, |service_path| is the object path of the - // exported GATT service the characteristic belongs to, |object_path| is the - // object path that the characteristic should have, and |delegate| is the - // object that "Value" Get/Set requests will be passed to and responses - // generated from. - // - // Object paths of GATT characteristics must be hierarchical to the path of - // the GATT service they belong to. Hence, |object_path| must have - // |service_path| as its prefix. Ownership of |delegate| is not taken, thus - // the delegate should outlive this instance. A delegate should handle only - // a single exported characteristic and own it. - static BluetoothGattCharacteristicServiceProvider* Create( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate, - const std::string& uuid, - const std::vector<std::string>& flags, - const std::vector<std::string>& permissions, - const dbus::ObjectPath& service_path); - - protected: - BluetoothGattCharacteristicServiceProvider(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothGattCharacteristicServiceProvider); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/bluetooth_gatt_descriptor_client.cc b/chromeos/dbus/bluetooth_gatt_descriptor_client.cc deleted file mode 100644 index 4d974158..0000000 --- a/chromeos/dbus/bluetooth_gatt_descriptor_client.cc +++ /dev/null
@@ -1,251 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/bluetooth_gatt_descriptor_client.h" - -#include "base/bind.h" -#include "base/memory/weak_ptr.h" -#include "base/observer_list.h" -#include "dbus/bus.h" -#include "dbus/object_manager.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -namespace { - -// TODO(armansito): Move this constant to cros_system_api. -const char kValueProperty[] = "Value"; - -} // namespace - -// static -const char BluetoothGattDescriptorClient::kNoResponseError[] = - "org.chromium.Error.NoResponse"; -// static -const char BluetoothGattDescriptorClient::kUnknownDescriptorError[] = - "org.chromium.Error.UnknownDescriptor"; - -BluetoothGattDescriptorClient::Properties::Properties( - dbus::ObjectProxy* object_proxy, - const std::string& interface_name, - const PropertyChangedCallback& callback) - : dbus::PropertySet(object_proxy, interface_name, callback) { - RegisterProperty(bluetooth_gatt_descriptor::kUUIDProperty, &uuid); - RegisterProperty(bluetooth_gatt_descriptor::kCharacteristicProperty, - &characteristic); - RegisterProperty(kValueProperty, &value); -} - -BluetoothGattDescriptorClient::Properties::~Properties() {} - -// The BluetoothGattDescriptorClient implementation used in production. -class BluetoothGattDescriptorClientImpl - : public BluetoothGattDescriptorClient, - public dbus::ObjectManager::Interface { - public: - BluetoothGattDescriptorClientImpl() - : object_manager_(NULL), weak_ptr_factory_(this) {} - - ~BluetoothGattDescriptorClientImpl() override { - object_manager_->UnregisterInterface( - bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface); - } - - // BluetoothGattDescriptorClientImpl override. - void AddObserver(BluetoothGattDescriptorClient::Observer* observer) override { - DCHECK(observer); - observers_.AddObserver(observer); - } - - // BluetoothGattDescriptorClientImpl override. - void RemoveObserver( - BluetoothGattDescriptorClient::Observer* observer) override { - DCHECK(observer); - observers_.RemoveObserver(observer); - } - - // BluetoothGattDescriptorClientImpl override. - std::vector<dbus::ObjectPath> GetDescriptors() override { - DCHECK(object_manager_); - return object_manager_->GetObjectsWithInterface( - bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface); - } - - // BluetoothGattDescriptorClientImpl override. - Properties* GetProperties(const dbus::ObjectPath& object_path) override { - DCHECK(object_manager_); - return static_cast<Properties*>(object_manager_->GetProperties( - object_path, - bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface)); - } - - // BluetoothGattDescriptorClientImpl override. - void ReadValue(const dbus::ObjectPath& object_path, - const ValueCallback& callback, - const ErrorCallback& error_callback) override { - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(object_path); - if (!object_proxy) { - error_callback.Run(kUnknownDescriptorError, ""); - return; - } - - dbus::MethodCall method_call( - bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface, - bluetooth_gatt_descriptor::kReadValue); - - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothGattDescriptorClientImpl::OnValueSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothGattDescriptorClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothGattDescriptorClientImpl override. - void WriteValue(const dbus::ObjectPath& object_path, - const std::vector<uint8>& value, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(object_path); - if (!object_proxy) { - error_callback.Run(kUnknownDescriptorError, ""); - return; - } - - dbus::MethodCall method_call( - bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface, - bluetooth_gatt_descriptor::kWriteValue); - dbus::MessageWriter writer(&method_call); - writer.AppendArrayOfBytes(value.data(), value.size()); - - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothGattDescriptorClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothGattDescriptorClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // dbus::ObjectManager::Interface override. - dbus::PropertySet* CreateProperties( - dbus::ObjectProxy* object_proxy, - const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - Properties* properties = new Properties( - object_proxy, interface_name, - base::Bind(&BluetoothGattDescriptorClientImpl::OnPropertyChanged, - weak_ptr_factory_.GetWeakPtr(), object_path)); - return static_cast<dbus::PropertySet*>(properties); - } - - // dbus::ObjectManager::Interface override. - void ObjectAdded(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - VLOG(2) << "Remote GATT descriptor added: " << object_path.value(); - FOR_EACH_OBSERVER(BluetoothGattDescriptorClient::Observer, observers_, - GattDescriptorAdded(object_path)); - } - - // dbus::ObjectManager::Interface override. - void ObjectRemoved(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - VLOG(2) << "Remote GATT descriptor removed: " << object_path.value(); - FOR_EACH_OBSERVER(BluetoothGattDescriptorClient::Observer, observers_, - GattDescriptorRemoved(object_path)); - } - - protected: - // chromeos::DBusClient override. - void Init(dbus::Bus* bus) override { - object_manager_ = bus->GetObjectManager( - bluetooth_object_manager::kBluetoothObjectManagerServiceName, - dbus::ObjectPath( - bluetooth_object_manager::kBluetoothObjectManagerServicePath)); - object_manager_->RegisterInterface( - bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface, this); - } - - private: - // Called by dbus::PropertySet when a property value is changed, either by - // result of a signal or response to a GetAll() or Get() call. Informs - // observers. - virtual void OnPropertyChanged(const dbus::ObjectPath& object_path, - const std::string& property_name) { - VLOG(2) << "Remote GATT descriptor property changed: " - << object_path.value() << ": " << property_name; - FOR_EACH_OBSERVER( - BluetoothGattDescriptorClient::Observer, observers_, - GattDescriptorPropertyChanged(object_path, property_name)); - } - - // Called when a response for a successful method call is received. - void OnSuccess(const base::Closure& callback, dbus::Response* response) { - DCHECK(response); - callback.Run(); - } - - // Called when a descriptor value response for a successful method call is - // received. - void OnValueSuccess(const ValueCallback& callback, dbus::Response* response) { - DCHECK(response); - dbus::MessageReader reader(response); - - const uint8* bytes = NULL; - size_t length = 0; - - if (!reader.PopArrayOfBytes(&bytes, &length)) - VLOG(2) << "Error reading array of bytes in ValueCallback"; - - std::vector<uint8> value; - - if (bytes) - value.assign(bytes, bytes + length); - - callback.Run(value); - } - - // Called when a response for a failed method call is received. - void OnError(const ErrorCallback& error_callback, - dbus::ErrorResponse* response) { - // Error response has optional error message argument. - std::string error_name; - std::string error_message; - if (response) { - dbus::MessageReader reader(response); - error_name = response->GetErrorName(); - reader.PopString(&error_message); - } else { - error_name = kNoResponseError; - error_message = ""; - } - error_callback.Run(error_name, error_message); - } - - dbus::ObjectManager* object_manager_; - - // List of observers interested in event notifications from us. - base::ObserverList<BluetoothGattDescriptorClient::Observer> observers_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<BluetoothGattDescriptorClientImpl> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothGattDescriptorClientImpl); -}; - -BluetoothGattDescriptorClient::BluetoothGattDescriptorClient() {} - -BluetoothGattDescriptorClient::~BluetoothGattDescriptorClient() {} - -// static -BluetoothGattDescriptorClient* BluetoothGattDescriptorClient::Create() { - return new BluetoothGattDescriptorClientImpl(); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_gatt_descriptor_client.h b/chromeos/dbus/bluetooth_gatt_descriptor_client.h deleted file mode 100644 index 15d3d9c34a..0000000 --- a/chromeos/dbus/bluetooth_gatt_descriptor_client.h +++ /dev/null
@@ -1,115 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_ -#define CHROMEOS_DBUS_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_ - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/dbus_client.h" -#include "dbus/object_path.h" -#include "dbus/property.h" - -namespace chromeos { - -// BluetoothGattDescriptorClient is used to communicate with remote GATT -// characteristic descriptor objects exposed by the Bluetooth daemon. -class CHROMEOS_EXPORT BluetoothGattDescriptorClient : public DBusClient { - public: - // Structure of properties associated with GATT descriptors. - struct Properties : public dbus::PropertySet { - // The 128-bit characteristic descriptor UUID. [read-only] - dbus::Property<std::string> uuid; - - // Object path of the GATT characteristic the descriptor belongs to. - // [read-only] - dbus::Property<dbus::ObjectPath> characteristic; - - // The cached value of the descriptor. This property gets updated only after - // a successful read request. [read-only] - dbus::Property<std::vector<uint8_t>> value; - - Properties(dbus::ObjectProxy* object_proxy, - const std::string& interface_name, - const PropertyChangedCallback& callback); - ~Properties() override; - }; - - // Interface for observing changes from a remote GATT characteristic - // descriptor. - class Observer { - public: - virtual ~Observer() {} - - // Called when the GATT descriptor with object path |object_path| is added - // to the system. - virtual void GattDescriptorAdded(const dbus::ObjectPath& object_path) {} - - // Called when the GATT descriptor with object path |object_path| is removed - // from the system. - virtual void GattDescriptorRemoved(const dbus::ObjectPath& object_path) {} - - // Called when the GATT descriptor with object path |object_path| has a - // change in the value of the property named |property_name|. - virtual void GattDescriptorPropertyChanged( - const dbus::ObjectPath& object_path, - const std::string& property_name) {} - }; - - // Callbacks used to report the result of asynchronous methods. - typedef base::Callback<void(const std::string& error_name, - const std::string& error_message)> ErrorCallback; - typedef base::Callback<void(const std::vector<uint8>& value)> ValueCallback; - - ~BluetoothGattDescriptorClient() override; - - // Adds and removes observers for events on all remote GATT descriptors. Check - // the |object_path| parameter of observer methods to determine which GATT - // descriptor is issuing the event. - virtual void AddObserver(Observer* observer) = 0; - virtual void RemoveObserver(Observer* observer) = 0; - - // Returns the list of GATT descriptor object paths known to the system. - virtual std::vector<dbus::ObjectPath> GetDescriptors() = 0; - - // Obtain the properties for the GATT descriptor with object path - // |object_path|. Values should be copied if needed. - virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; - - // Issues a request to read the value of GATT descriptor with object path - // |object_path| and returns the value in |callback| on success. On error, - // invokes |error_callback|. - virtual void ReadValue(const dbus::ObjectPath& object_path, - const ValueCallback& callback, - const ErrorCallback& error_callback) = 0; - - // Issues a request to write the value of GATT descriptor with object path - // |object_path| with value |value|. Invokes |callback| on success and - // |error_callback| on failure. - virtual void WriteValue(const dbus::ObjectPath& object_path, - const std::vector<uint8>& value, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Creates the instance. - static BluetoothGattDescriptorClient* Create(); - - // Constants used to indicate exceptional error conditions. - static const char kNoResponseError[]; - static const char kUnknownDescriptorError[]; - - protected: - BluetoothGattDescriptorClient(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothGattDescriptorClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_gatt_descriptor_service_provider.cc b/chromeos/dbus/bluetooth_gatt_descriptor_service_provider.cc deleted file mode 100644 index 1fe1657..0000000 --- a/chromeos/dbus/bluetooth_gatt_descriptor_service_provider.cc +++ /dev/null
@@ -1,457 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/bluetooth_gatt_descriptor_service_provider.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/memory/weak_ptr.h" -#include "base/strings/string_util.h" -#include "base/threading/platform_thread.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.h" -#include "dbus/exported_object.h" -#include "dbus/message.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { -namespace { -const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs"; -const char kErrorPropertyReadOnly[] = - "org.freedesktop.DBus.Error.PropertyReadOnly"; -const char kErrorFailed[] = "org.freedesktop.DBus.Error.Failed"; -} // namespace - -// The BluetoothGattDescriptorServiceProvider implementation used in production. -class BluetoothGattDescriptorServiceProviderImpl - : public BluetoothGattDescriptorServiceProvider { - public: - BluetoothGattDescriptorServiceProviderImpl( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate, - const std::string& uuid, - const std::vector<std::string>& permissions, - const dbus::ObjectPath& characteristic_path) - : origin_thread_id_(base::PlatformThread::CurrentId()), - uuid_(uuid), - bus_(bus), - delegate_(delegate), - object_path_(object_path), - characteristic_path_(characteristic_path), - weak_ptr_factory_(this) { - VLOG(1) << "Created Bluetooth GATT characteristic descriptor: " - << object_path.value() << " UUID: " << uuid; - DCHECK(bus_); - DCHECK(delegate_); - DCHECK(!uuid_.empty()); - DCHECK(object_path_.IsValid()); - DCHECK(characteristic_path_.IsValid()); - DCHECK(base::StartsWith(object_path_.value(), - characteristic_path_.value() + "/", - base::CompareCase::SENSITIVE)); - - exported_object_ = bus_->GetExportedObject(object_path_); - - exported_object_->ExportMethod( - dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet, - base::Bind(&BluetoothGattDescriptorServiceProviderImpl::Get, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesSet, - base::Bind(&BluetoothGattDescriptorServiceProviderImpl::Set, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll, - base::Bind(&BluetoothGattDescriptorServiceProviderImpl::GetAll, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - } - - ~BluetoothGattDescriptorServiceProviderImpl() override { - VLOG(1) << "Cleaning up Bluetooth GATT characteristic descriptor: " - << object_path_.value(); - bus_->UnregisterExportedObject(object_path_); - } - - // BluetoothGattDescriptorServiceProvider override. - void SendValueChanged(const std::vector<uint8>& value) override { - VLOG(2) << "Emitting a PropertiesChanged signal for descriptor value."; - dbus::Signal signal(dbus::kDBusPropertiesInterface, - dbus::kDBusPropertiesChangedSignal); - dbus::MessageWriter writer(&signal); - dbus::MessageWriter array_writer(NULL); - dbus::MessageWriter dict_entry_writer(NULL); - dbus::MessageWriter variant_writer(NULL); - - // interface_name - writer.AppendString( - bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface); - - // changed_properties - writer.OpenArray("{sv}", &array_writer); - array_writer.OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString(bluetooth_gatt_descriptor::kValueProperty); - dict_entry_writer.OpenVariant("ay", &variant_writer); - variant_writer.AppendArrayOfBytes(value.data(), value.size()); - dict_entry_writer.CloseContainer(&variant_writer); - array_writer.CloseContainer(&dict_entry_writer); - writer.CloseContainer(&array_writer); - - // invalidated_properties. - writer.OpenArray("s", &array_writer); - writer.CloseContainer(&array_writer); - - exported_object_->SendSignal(&signal); - } - - private: - // Returns true if the current thread is on the origin thread. - bool OnOriginThread() { - return base::PlatformThread::CurrentId() == origin_thread_id_; - } - - // Called by dbus:: when the Bluetooth daemon fetches a single property of - // the descriptor. - void Get(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(2) << "BluetoothGattDescriptorServiceProvider::Get: " - << object_path_.value(); - DCHECK(OnOriginThread()); - - dbus::MessageReader reader(method_call); - - std::string interface_name; - std::string property_name; - if (!reader.PopString(&interface_name) || - !reader.PopString(&property_name) || reader.HasMoreData()) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, - "Expected 'ss'."); - response_sender.Run(error_response.Pass()); - return; - } - - // Only the GATT descriptor interface is supported. - if (interface_name != - bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidArgs, - "No such interface: '" + interface_name + "'."); - response_sender.Run(error_response.Pass()); - return; - } - - // If getting the "Value" property, obtain the value from the delegate. - if (property_name == bluetooth_gatt_descriptor::kValueProperty) { - DCHECK(delegate_); - delegate_->GetDescriptorValue( - base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnGet, - weak_ptr_factory_.GetWeakPtr(), method_call, - response_sender), - base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnFailure, - weak_ptr_factory_.GetWeakPtr(), method_call, - response_sender)); - return; - } - - scoped_ptr<dbus::Response> response = - dbus::Response::FromMethodCall(method_call); - dbus::MessageWriter writer(response.get()); - dbus::MessageWriter variant_writer(NULL); - - // TODO(armansito): Process the "Permissions" property below. - if (property_name == bluetooth_gatt_descriptor::kUUIDProperty) { - writer.OpenVariant("s", &variant_writer); - variant_writer.AppendString(uuid_); - writer.CloseContainer(&variant_writer); - } else if (property_name == - bluetooth_gatt_descriptor::kCharacteristicProperty) { - writer.OpenVariant("o", &variant_writer); - variant_writer.AppendObjectPath(characteristic_path_); - writer.CloseContainer(&variant_writer); - } else { - response = dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidArgs, - "No such property: '" + property_name + "'."); - } - - response_sender.Run(response.Pass()); - } - - // Called by dbus:: when the Bluetooth daemon sets a single property of the - // descriptor. - void Set(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(2) << "BluetoothGattDescriptorServiceProvider::Set: " - << object_path_.value(); - DCHECK(OnOriginThread()); - - dbus::MessageReader reader(method_call); - - std::string interface_name; - std::string property_name; - dbus::MessageReader variant_reader(NULL); - if (!reader.PopString(&interface_name) || - !reader.PopString(&property_name) || - !reader.PopVariant(&variant_reader) || reader.HasMoreData()) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, - "Expected 'ssv'."); - response_sender.Run(error_response.Pass()); - return; - } - - // Only the GATT descriptor interface is allowed. - if (interface_name != - bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidArgs, - "No such interface: '" + interface_name + "'."); - response_sender.Run(error_response.Pass()); - return; - } - - // Only the "Value" property is writeable. - if (property_name != bluetooth_gatt_descriptor::kValueProperty) { - std::string error_name; - std::string error_message; - if (property_name == bluetooth_gatt_descriptor::kUUIDProperty || - property_name == bluetooth_gatt_descriptor::kCharacteristicProperty) { - error_name = kErrorPropertyReadOnly; - error_message = "Read-only property: '" + property_name + "'."; - } else { - error_name = kErrorInvalidArgs; - error_message = "No such property: '" + property_name + "'."; - } - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall(method_call, error_name, - error_message); - response_sender.Run(error_response.Pass()); - return; - } - - // Obtain the value. - const uint8* bytes = NULL; - size_t length = 0; - if (!variant_reader.PopArrayOfBytes(&bytes, &length)) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidArgs, - "Property '" + property_name + "' has type 'ay'."); - response_sender.Run(error_response.Pass()); - return; - } - - // Pass the set request onto the delegate. - std::vector<uint8> value(bytes, bytes + length); - DCHECK(delegate_); - delegate_->SetDescriptorValue( - value, base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnSet, - weak_ptr_factory_.GetWeakPtr(), method_call, - response_sender), - base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnFailure, - weak_ptr_factory_.GetWeakPtr(), method_call, - response_sender)); - } - - // Called by dbus:: when the Bluetooth daemon fetches all properties of the - // descriptor. - void GetAll(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(2) << "BluetoothGattDescriptorServiceProvider::GetAll: " - << object_path_.value(); - DCHECK(OnOriginThread()); - - dbus::MessageReader reader(method_call); - - std::string interface_name; - if (!reader.PopString(&interface_name) || reader.HasMoreData()) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, - "Expected 's'."); - response_sender.Run(error_response.Pass()); - return; - } - - // Only the GATT descriptor interface is supported. - if (interface_name != - bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidArgs, - "No such interface: '" + interface_name + "'."); - response_sender.Run(error_response.Pass()); - return; - } - - // Try to obtain the value from the delegate. We will construct the - // response in the success callback. - DCHECK(delegate_); - delegate_->GetDescriptorValue( - base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnGetAll, - weak_ptr_factory_.GetWeakPtr(), method_call, - response_sender), - base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnFailure, - weak_ptr_factory_.GetWeakPtr(), method_call, - response_sender)); - } - - // Called by dbus:: when a method is exported. - void OnExported(const std::string& interface_name, - const std::string& method_name, - bool success) { - LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "." - << method_name; - } - - // Called by the Delegate in response to a method to call to get all - // properties, in which the delegate has successfully returned the - // descriptor value. - void OnGetAll(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender, - const std::vector<uint8>& value) { - VLOG(2) << "Descriptor value obtained from delegate. Responding to " - << "GetAll."; - - scoped_ptr<dbus::Response> response = - dbus::Response::FromMethodCall(method_call); - dbus::MessageWriter writer(response.get()); - dbus::MessageWriter array_writer(NULL); - dbus::MessageWriter dict_entry_writer(NULL); - dbus::MessageWriter variant_writer(NULL); - - writer.OpenArray("{sv}", &array_writer); - - array_writer.OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString(bluetooth_gatt_descriptor::kUUIDProperty); - dict_entry_writer.AppendVariantOfString(uuid_); - array_writer.CloseContainer(&dict_entry_writer); - - array_writer.OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString( - bluetooth_gatt_descriptor::kCharacteristicProperty); - dict_entry_writer.AppendVariantOfObjectPath(characteristic_path_); - array_writer.CloseContainer(&dict_entry_writer); - - array_writer.OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString(bluetooth_gatt_descriptor::kValueProperty); - dict_entry_writer.OpenVariant("ay", &variant_writer); - variant_writer.AppendArrayOfBytes(value.data(), value.size()); - dict_entry_writer.CloseContainer(&variant_writer); - array_writer.CloseContainer(&dict_entry_writer); - - // TODO(armansito): Process "Permissions" property. - - writer.CloseContainer(&array_writer); - - response_sender.Run(response.Pass()); - } - - // Called by the Delegate in response to a successful method call to get the - // descriptor value. - void OnGet(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender, - const std::vector<uint8>& value) { - VLOG(2) << "Returning descriptor value obtained from delegate."; - scoped_ptr<dbus::Response> response = - dbus::Response::FromMethodCall(method_call); - dbus::MessageWriter writer(response.get()); - dbus::MessageWriter variant_writer(NULL); - - writer.OpenVariant("ay", &variant_writer); - variant_writer.AppendArrayOfBytes(value.data(), value.size()); - writer.CloseContainer(&variant_writer); - - response_sender.Run(response.Pass()); - } - - // Called by the Delegate in response to a successful method call to set the - // descriptor value. - void OnSet(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(2) << "Successfully set descriptor value. Return success."; - response_sender.Run(dbus::Response::FromMethodCall(method_call)); - } - - // Called by the Delegate in response to a failed method call to get or set - // the descriptor value. - void OnFailure(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(2) << "Failed to get/set descriptor value. Report error."; - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall( - method_call, kErrorFailed, "Failed to get/set descriptor value."); - response_sender.Run(error_response.Pass()); - } - - // Origin thread (i.e. the UI thread in production). - base::PlatformThreadId origin_thread_id_; - - // 128-bit descriptor UUID of this object. - std::string uuid_; - - // D-Bus bus object is exported on, not owned by this object and must - // outlive it. - dbus::Bus* bus_; - - // Incoming methods to get and set the "Value" property are passed on to the - // delegate and callbacks passed to generate a reply. |delegate_| is generally - // the object that owns this one and must outlive it. - Delegate* delegate_; - - // D-Bus object path of object we are exporting, kept so we can unregister - // again in our destructor. - dbus::ObjectPath object_path_; - - // Object path of the GATT characteristic that the exported descriptor belongs - // to. - dbus::ObjectPath characteristic_path_; - - // D-Bus object we are exporting, owned by this object. - scoped_refptr<dbus::ExportedObject> exported_object_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<BluetoothGattDescriptorServiceProviderImpl> - weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothGattDescriptorServiceProviderImpl); -}; - -BluetoothGattDescriptorServiceProvider:: - BluetoothGattDescriptorServiceProvider() {} - -BluetoothGattDescriptorServiceProvider:: - ~BluetoothGattDescriptorServiceProvider() {} - -// static -BluetoothGattDescriptorServiceProvider* -BluetoothGattDescriptorServiceProvider::Create( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate, - const std::string& uuid, - const std::vector<std::string>& permissions, - const dbus::ObjectPath& characteristic_path) { - if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) { - return new BluetoothGattDescriptorServiceProviderImpl( - bus, object_path, delegate, uuid, permissions, characteristic_path); - } - return new FakeBluetoothGattDescriptorServiceProvider( - object_path, delegate, uuid, permissions, characteristic_path); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_gatt_descriptor_service_provider.h b/chromeos/dbus/bluetooth_gatt_descriptor_service_provider.h deleted file mode 100644 index 4b5fef8..0000000 --- a/chromeos/dbus/bluetooth_gatt_descriptor_service_provider.h +++ /dev/null
@@ -1,109 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_ -#define CHROMEOS_DBUS_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_ - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "chromeos/chromeos_export.h" -#include "dbus/bus.h" -#include "dbus/object_path.h" - -namespace chromeos { - -// BluetoothGattDescriptorServiceProvider is used to provide a D-Bus object that -// represents a local GATT characteristic descriptor that the Bluetooth daemon -// can communicate with. -// -// Instantiate with a chosen D-Bus object path, delegate, and other fields. -// The Bluetooth daemon communicates with a GATT descriptor using the -// standard DBus.Properties interface. While most properties of the GATT -// descriptor interface are read-only and don't change throughout the -// life-time of the object, the "Value" property is both writeable and its -// value can change. Both Get and Set operations performed on the "Value" -// property are delegated to the Delegate object, an instance of which is -// mandatory during initialization. In addition, a "SendValueChanged" method is -// provided, which emits a DBus.Properties.PropertyChanged signal for the -// "Value" property. -class CHROMEOS_EXPORT BluetoothGattDescriptorServiceProvider { - public: - // Interface for reacting to GATT characteristic descriptor value requests. - class Delegate { - public: - virtual ~Delegate() {} - - // ValueCallback is used for methods that require a descriptor value - // to be returned. - typedef base::Callback<void(const std::vector<uint8>&)> ValueCallback; - - // ErrorCallback is used by methods to report failure. - typedef base::Closure ErrorCallback; - - // This method will be called when a remote device requests to read the - // value of the exported GATT descriptor. Invoke |callback| with a value - // to return that value to the requester. Invoke |error_callback| to report - // a failure to read the value. This can happen, for example, if the - // descriptor has no read permission set. Either callback should be - // invoked after a reasonable amount of time, since the request will time - // out if left pending for too long. - virtual void GetDescriptorValue(const ValueCallback& callback, - const ErrorCallback& error_callback) = 0; - - // This method will be called, when a remote device requests to write the - // value of the exported GATT descriptor. Invoke |callback| to report - // that the value was successfully written. Invoke |error_callback| to - // report a failure to write the value. This can happen, for example, if the - // descriptor has no write permission set. Either callback should be - // invoked after a reasonable amount of time, since the request will time - // out if left pending for too long. - // - // The delegate should use this method to perform any side-effects that may - // occur based on the set value and potentially send a property changed - // signal to notify the Bluetooth daemon that the value has changed. - virtual void SetDescriptorValue(const std::vector<uint8>& value, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - }; - - virtual ~BluetoothGattDescriptorServiceProvider(); - - // Send a PropertyChanged signal to notify the Bluetooth daemon that the value - // of the "Value" property has changed to |value|. - virtual void SendValueChanged(const std::vector<uint8>& value) = 0; - - // Creates the instance, where |bus| is the D-Bus bus connection to export - // the object onto, |uuid| is the 128-bit GATT descriptor UUID, |permissions| - // is the list of attribute permissions, |characteristic_path| is the object - // path of the exported GATT characteristic the descriptor belongs to, - // |object_path| is the object path that the descriptor should have, and - // |delegate| is the object that value Get/Set requests will be passed to and - // responses generated from. - // - // Object paths of GATT descriptors must be hierarchical to the path of the - // GATT characteristic they belong to. Hence, |object_path| must have - // |characteristic_path| as its prefix. Ownership of |delegate| is not taken, - // thus the delegate should outlive this instance. A delegate should handle - // only a single exported descriptor and own it. - static BluetoothGattDescriptorServiceProvider* Create( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate, - const std::string& uuid, - const std::vector<std::string>& permissions, - const dbus::ObjectPath& characteristic_path); - - protected: - BluetoothGattDescriptorServiceProvider(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothGattDescriptorServiceProvider); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/bluetooth_gatt_manager_client.cc b/chromeos/dbus/bluetooth_gatt_manager_client.cc deleted file mode 100644 index b3e98c6a..0000000 --- a/chromeos/dbus/bluetooth_gatt_manager_client.cc +++ /dev/null
@@ -1,129 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/bluetooth_gatt_manager_client.h" - -#include "base/bind.h" -#include "base/memory/weak_ptr.h" -#include "dbus/bus.h" -#include "dbus/message.h" -#include "dbus/object_proxy.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -const char BluetoothGattManagerClient::kNoResponseError[] = - "org.chromium.Error.NoResponse"; - -// The BluetoothGattManagerClient implementation used in production. -class BluetoothGattManagerClientImpl : public BluetoothGattManagerClient { - public: - BluetoothGattManagerClientImpl() - : object_proxy_(NULL), weak_ptr_factory_(this) {} - - ~BluetoothGattManagerClientImpl() override {} - - // BluetoothGattManagerClient override. - void RegisterService(const dbus::ObjectPath& service_path, - const Options& options, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call( - bluetooth_gatt_manager::kBluetoothGattManagerInterface, - bluetooth_gatt_manager::kRegisterService); - - dbus::MessageWriter writer(&method_call); - writer.AppendObjectPath(service_path); - - // TODO(armansito): The parameters of the Options dictionary are undefined - // but the method signature still requires a value dictionary. Pass an - // empty dictionary and fill in the contents later once this is defined. - dbus::MessageWriter array_writer(NULL); - writer.OpenArray("{sv}", &array_writer); - writer.CloseContainer(&array_writer); - - DCHECK(object_proxy_); - object_proxy_->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothGattManagerClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothGattManagerClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothGattManagerClient override. - void UnregisterService(const dbus::ObjectPath& service_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call( - bluetooth_gatt_manager::kBluetoothGattManagerInterface, - bluetooth_gatt_manager::kUnregisterService); - - dbus::MessageWriter writer(&method_call); - writer.AppendObjectPath(service_path); - - DCHECK(object_proxy_); - object_proxy_->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothGattManagerClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothGattManagerClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - protected: - // chromeos::DBusClient override. - void Init(dbus::Bus* bus) override { - DCHECK(bus); - object_proxy_ = bus->GetObjectProxy( - bluetooth_gatt_manager::kBluetoothGattManagerServiceName, - dbus::ObjectPath( - bluetooth_gatt_manager::kBluetoothGattManagerInterface)); - } - - private: - // Called when a response for a successful method call is received. - void OnSuccess(const base::Closure& callback, dbus::Response* response) { - DCHECK(response); - callback.Run(); - } - - // Called when a response for a failed method call is received. - void OnError(const ErrorCallback& error_callback, - dbus::ErrorResponse* response) { - // Error response has optional error message argument. - std::string error_name; - std::string error_message; - if (response) { - dbus::MessageReader reader(response); - error_name = response->GetErrorName(); - reader.PopString(&error_message); - } else { - error_name = kNoResponseError; - } - error_callback.Run(error_name, error_message); - } - - // The proxy to the remote GATT manager object. - dbus::ObjectProxy* object_proxy_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<BluetoothGattManagerClientImpl> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothGattManagerClientImpl); -}; - -BluetoothGattManagerClient::BluetoothGattManagerClient() {} - -BluetoothGattManagerClient::~BluetoothGattManagerClient() {} - -// static -BluetoothGattManagerClient* BluetoothGattManagerClient::Create() { - return new BluetoothGattManagerClientImpl(); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_gatt_manager_client.h b/chromeos/dbus/bluetooth_gatt_manager_client.h deleted file mode 100644 index 7a16a0b4..0000000 --- a/chromeos/dbus/bluetooth_gatt_manager_client.h +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_BLUETOOTH_GATT_MANAGER_CLIENT_H_ -#define CHROMEOS_DBUS_BLUETOOTH_GATT_MANAGER_CLIENT_H_ - -#include <string> - -#include "base/callback.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/dbus_client.h" -#include "dbus/object_path.h" - -namespace chromeos { - -// BluetoothGattManagerClient is used to communicate with the GATT Service -// manager object of the Bluetooth daemon. -class CHROMEOS_EXPORT BluetoothGattManagerClient : public DBusClient { - public: - // Options used to register a GATT service hierarchy. - struct CHROMEOS_EXPORT Options { - // TODO(armansito): This parameter is not yet clearly defined. Add fields - // later as we know more about how this will be used. - }; - - ~BluetoothGattManagerClient() override; - - // The ErrorCallback is used by GATT manager methods to indicate failure. It - // receives two arguments: the name of the error in |error_name| and an - // optional message in |error_message|. - typedef base::Callback<void(const std::string& error_name, - const std::string& error_message)> ErrorCallback; - - // Registers a GATT service implementation within the local process at the - // D-Bus object path |service_path| with the remote GATT manager. The local - // service must implement the GattService1 interface. Characteristic objects - // must be hierarchical to their service and must use the interface - // GattCharacteristic1. Similarly, characteristic descriptor objects must - // implement the GattDescriptor1 interface and must be hierarchical to their - // characteristic. In a successful invocation of RegisterService, the - // Bluetooth daemon will discover all objects in the registered hierarchy by - // using D-Bus Object Manager. Hence, the object paths and the interfaces in - // the registered hierarchy must comply with the BlueZ GATT D-Bus - // specification. - virtual void RegisterService(const dbus::ObjectPath& service_path, - const Options& options, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Unregisters the GATT service with the D-Bus object path |service_path| from - // the remote GATT manager. - virtual void UnregisterService(const dbus::ObjectPath& service_path, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Creates the instance. - static BluetoothGattManagerClient* Create(); - - // Constants used to indicate exceptional error conditions. - static const char kNoResponseError[]; - - protected: - BluetoothGattManagerClient(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothGattManagerClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_GATT_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_gatt_service_client.cc b/chromeos/dbus/bluetooth_gatt_service_client.cc deleted file mode 100644 index 53572f0..0000000 --- a/chromeos/dbus/bluetooth_gatt_service_client.cc +++ /dev/null
@@ -1,143 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/bluetooth_gatt_service_client.h" - -#include "base/bind.h" -#include "base/memory/weak_ptr.h" -#include "base/observer_list.h" -#include "dbus/bus.h" -#include "dbus/object_manager.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -BluetoothGattServiceClient::Properties::Properties( - dbus::ObjectProxy* object_proxy, - const std::string& interface_name, - const PropertyChangedCallback& callback) - : dbus::PropertySet(object_proxy, interface_name, callback) { - RegisterProperty(bluetooth_gatt_service::kUUIDProperty, &uuid); - RegisterProperty(bluetooth_gatt_service::kIncludesProperty, &includes); - RegisterProperty(bluetooth_gatt_service::kDeviceProperty, &device); - RegisterProperty(bluetooth_gatt_service::kPrimaryProperty, &primary); - RegisterProperty(bluetooth_gatt_service::kCharacteristicsProperty, - &characteristics); -} - -BluetoothGattServiceClient::Properties::~Properties() {} - -// The BluetoothGattServiceClient implementation used in production. -class BluetoothGattServiceClientImpl : public BluetoothGattServiceClient, - public dbus::ObjectManager::Interface { - public: - BluetoothGattServiceClientImpl() - : object_manager_(NULL), weak_ptr_factory_(this) {} - - ~BluetoothGattServiceClientImpl() override { - object_manager_->UnregisterInterface( - bluetooth_gatt_service::kBluetoothGattServiceInterface); - } - - // BluetoothGattServiceClientImpl override. - void AddObserver(BluetoothGattServiceClient::Observer* observer) override { - DCHECK(observer); - observers_.AddObserver(observer); - } - - // BluetoothGattServiceClientImpl override. - void RemoveObserver(BluetoothGattServiceClient::Observer* observer) override { - DCHECK(observer); - observers_.RemoveObserver(observer); - } - - // BluetoothGattServiceClientImpl override. - std::vector<dbus::ObjectPath> GetServices() override { - DCHECK(object_manager_); - return object_manager_->GetObjectsWithInterface( - bluetooth_gatt_service::kBluetoothGattServiceInterface); - } - - // BluetoothGattServiceClientImpl override. - Properties* GetProperties(const dbus::ObjectPath& object_path) override { - DCHECK(object_manager_); - return static_cast<Properties*>(object_manager_->GetProperties( - object_path, bluetooth_gatt_service::kBluetoothGattServiceInterface)); - } - - // dbus::ObjectManager::Interface override. - dbus::PropertySet* CreateProperties( - dbus::ObjectProxy* object_proxy, - const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - Properties* properties = new Properties( - object_proxy, interface_name, - base::Bind(&BluetoothGattServiceClientImpl::OnPropertyChanged, - weak_ptr_factory_.GetWeakPtr(), object_path)); - return static_cast<dbus::PropertySet*>(properties); - } - - // dbus::ObjectManager::Interface override. - void ObjectAdded(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - VLOG(2) << "Remote GATT service added: " << object_path.value(); - FOR_EACH_OBSERVER(BluetoothGattServiceClient::Observer, observers_, - GattServiceAdded(object_path)); - } - - // dbus::ObjectManager::Interface override. - void ObjectRemoved(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - VLOG(2) << "Remote GATT service removed: " << object_path.value(); - FOR_EACH_OBSERVER(BluetoothGattServiceClient::Observer, observers_, - GattServiceRemoved(object_path)); - } - - protected: - // chromeos::DBusClient override. - void Init(dbus::Bus* bus) override { - object_manager_ = bus->GetObjectManager( - bluetooth_object_manager::kBluetoothObjectManagerServiceName, - dbus::ObjectPath( - bluetooth_object_manager::kBluetoothObjectManagerServicePath)); - object_manager_->RegisterInterface( - bluetooth_gatt_service::kBluetoothGattServiceInterface, this); - } - - private: - // Called by dbus::PropertySet when a property value is changed, either by - // result of a signal or response to a GetAll() or Get() call. Informs - // observers. - virtual void OnPropertyChanged(const dbus::ObjectPath& object_path, - const std::string& property_name) { - VLOG(2) << "Remote GATT service property changed: " << object_path.value() - << ": " << property_name; - FOR_EACH_OBSERVER(BluetoothGattServiceClient::Observer, observers_, - GattServicePropertyChanged(object_path, property_name)); - } - - dbus::ObjectManager* object_manager_; - - // List of observers interested in event notifications from us. - base::ObserverList<BluetoothGattServiceClient::Observer> observers_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<BluetoothGattServiceClientImpl> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothGattServiceClientImpl); -}; - -BluetoothGattServiceClient::BluetoothGattServiceClient() {} - -BluetoothGattServiceClient::~BluetoothGattServiceClient() {} - -// static -BluetoothGattServiceClient* BluetoothGattServiceClient::Create() { - return new BluetoothGattServiceClientImpl(); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_gatt_service_client.h b/chromeos/dbus/bluetooth_gatt_service_client.h deleted file mode 100644 index 9c96bb8..0000000 --- a/chromeos/dbus/bluetooth_gatt_service_client.h +++ /dev/null
@@ -1,93 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_BLUETOOTH_GATT_SERVICE_CLIENT_H_ -#define CHROMEOS_DBUS_BLUETOOTH_GATT_SERVICE_CLIENT_H_ - -#include <string> -#include <vector> - -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/dbus_client.h" -#include "dbus/object_path.h" -#include "dbus/property.h" - -namespace chromeos { - -// BluetoothGattServiceClient is used to communicate with remote GATT service -// objects exposed by the Bluetooth daemon. -class CHROMEOS_EXPORT BluetoothGattServiceClient : public DBusClient { - public: - // Structure of properties associated with GATT services. - struct Properties : public dbus::PropertySet { - // The 128-bit service UUID. [read-only] - dbus::Property<std::string> uuid; - - // Object path of the Bluetooth device that the GATT service belongs to. - dbus::Property<dbus::ObjectPath> device; - - // Whether or not this service is a primary service. - dbus::Property<bool> primary; - - // Array of object paths representing the characteristics of this service. - // [read-only] - dbus::Property<std::vector<dbus::ObjectPath>> characteristics; - - // Array of object paths representing the included services of this service. - // [read-only] - dbus::Property<std::vector<dbus::ObjectPath>> includes; - - Properties(dbus::ObjectProxy* object_proxy, - const std::string& interface_name, - const PropertyChangedCallback& callback); - ~Properties() override; - }; - - // Interface for observing changes from a remote GATT service. - class Observer { - public: - virtual ~Observer() {} - - // Called when the GATT service with object path |object_path| is added to - // the system. - virtual void GattServiceAdded(const dbus::ObjectPath& object_path) {} - - // Called when the GATT service with object path |object_path| is removed - // from the system. - virtual void GattServiceRemoved(const dbus::ObjectPath& object_path) {} - - // Called when the GATT service with object path |object_path| has a change - // in the value of the property named |property_name|. - virtual void GattServicePropertyChanged(const dbus::ObjectPath& object_path, - const std::string& property_name) {} - }; - - ~BluetoothGattServiceClient() override; - - // Adds and removes observers for events on all remote GATT services. Check - // the |object_path| parameter of observer methods to determine which GATT - // service is issuing the event. - virtual void AddObserver(Observer* observer) = 0; - virtual void RemoveObserver(Observer* observer) = 0; - - // Returns the list of GATT service object paths known to the system. - virtual std::vector<dbus::ObjectPath> GetServices() = 0; - - // Obtain the properties for the GATT service with object path |object_path|. - // Values should be copied if needed. - virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; - - // Creates the instance. - static BluetoothGattServiceClient* Create(); - - protected: - BluetoothGattServiceClient(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothGattServiceClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_GATT_SERVICE_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_gatt_service_service_provider.cc b/chromeos/dbus/bluetooth_gatt_service_service_provider.cc deleted file mode 100644 index 9de86d41..0000000 --- a/chromeos/dbus/bluetooth_gatt_service_service_provider.cc +++ /dev/null
@@ -1,272 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/bluetooth_gatt_service_service_provider.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/threading/platform_thread.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_gatt_service_service_provider.h" -#include "dbus/exported_object.h" -#include "dbus/message.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { -namespace { -const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs"; -const char kErrorPropertyReadOnly[] = - "org.freedesktop.DBus.Error.PropertyReadOnly"; -} // namespace - -// The BluetoothGattServiceServiceProvider implementation used in production. -class BluetoothGattServiceServiceProviderImpl - : public BluetoothGattServiceServiceProvider { - public: - BluetoothGattServiceServiceProviderImpl( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - const std::string& uuid, - const std::vector<dbus::ObjectPath>& includes) - : origin_thread_id_(base::PlatformThread::CurrentId()), - uuid_(uuid), - includes_(includes), - bus_(bus), - object_path_(object_path), - weak_ptr_factory_(this) { - VLOG(1) << "Creating Bluetooth GATT service: " << object_path_.value() - << " UUID: " << uuid; - DCHECK(!uuid_.empty()); - DCHECK(object_path_.IsValid()); - DCHECK(bus_); - - exported_object_ = bus_->GetExportedObject(object_path_); - - exported_object_->ExportMethod( - dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet, - base::Bind(&BluetoothGattServiceServiceProviderImpl::Get, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesSet, - base::Bind(&BluetoothGattServiceServiceProviderImpl::Set, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll, - base::Bind(&BluetoothGattServiceServiceProviderImpl::GetAll, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - } - - ~BluetoothGattServiceServiceProviderImpl() override { - VLOG(1) << "Cleaning up Bluetooth GATT service: " << object_path_.value(); - bus_->UnregisterExportedObject(object_path_); - } - - private: - // Returns true if the current thread is on the origin thread. - bool OnOriginThread() { - return base::PlatformThread::CurrentId() == origin_thread_id_; - } - - // Called by dbus:: when the Bluetooth daemon fetches a single property of - // the service. - void Get(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(2) << "BluetoothGattServiceServiceProvider::Get: " - << object_path_.value(); - DCHECK(OnOriginThread()); - - dbus::MessageReader reader(method_call); - - std::string interface_name; - std::string property_name; - if (!reader.PopString(&interface_name) || - !reader.PopString(&property_name) || reader.HasMoreData()) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, - "Expected 'ss'."); - response_sender.Run(error_response.Pass()); - return; - } - - // Only the GATT service interface is allowed. - if (interface_name != - bluetooth_gatt_service::kBluetoothGattServiceInterface) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidArgs, - "No such interface: '" + interface_name + "'."); - response_sender.Run(error_response.Pass()); - return; - } - - // Return error if |property_name| is unknown. - if (property_name != bluetooth_gatt_service::kUUIDProperty && - property_name != bluetooth_gatt_service::kIncludesProperty) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidArgs, - "No such property: '" + property_name + "'."); - response_sender.Run(error_response.Pass()); - return; - } - - scoped_ptr<dbus::Response> response = - dbus::Response::FromMethodCall(method_call); - dbus::MessageWriter writer(response.get()); - dbus::MessageWriter variant_writer(NULL); - - if (property_name == bluetooth_gatt_service::kUUIDProperty) { - writer.OpenVariant("s", &variant_writer); - variant_writer.AppendString(uuid_); - writer.CloseContainer(&variant_writer); - } else { - writer.OpenVariant("ao", &variant_writer); - variant_writer.AppendArrayOfObjectPaths(includes_); - writer.CloseContainer(&variant_writer); - } - - response_sender.Run(response.Pass()); - } - - // Called by dbus:: when the Bluetooth daemon sets a single property of the - // service. - void Set(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(2) << "BluetoothGattServiceServiceProvider::Set: " - << object_path_.value(); - DCHECK(OnOriginThread()); - - // All of the properties on this interface are read-only, so just return - // error. - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall(method_call, kErrorPropertyReadOnly, - "All properties are read-only."); - response_sender.Run(error_response.Pass()); - } - - // Called by dbus:: when the Bluetooth daemon fetches all properties of the - // service. - void GetAll(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(2) << "BluetoothGattServiceServiceProvider::GetAll: " - << object_path_.value(); - DCHECK(OnOriginThread()); - - dbus::MessageReader reader(method_call); - - std::string interface_name; - if (!reader.PopString(&interface_name) || reader.HasMoreData()) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, - "Expected 's'."); - response_sender.Run(error_response.Pass()); - return; - } - - // Only the GATT service interface is allowed. - if (interface_name != - bluetooth_gatt_service::kBluetoothGattServiceInterface) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidArgs, - "No such interface: '" + interface_name + "'."); - response_sender.Run(error_response.Pass()); - return; - } - - scoped_ptr<dbus::Response> response = - dbus::Response::FromMethodCall(method_call); - dbus::MessageWriter writer(response.get()); - dbus::MessageWriter array_writer(NULL); - dbus::MessageWriter dict_entry_writer(NULL); - dbus::MessageWriter variant_writer(NULL); - - writer.OpenArray("{sv}", &array_writer); - - array_writer.OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString(bluetooth_gatt_service::kUUIDProperty); - dict_entry_writer.AppendVariantOfString(uuid_); - array_writer.CloseContainer(&dict_entry_writer); - - array_writer.OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString(bluetooth_gatt_service::kIncludesProperty); - dict_entry_writer.OpenVariant("ao", &variant_writer); - variant_writer.AppendArrayOfObjectPaths(includes_); - dict_entry_writer.CloseContainer(&variant_writer); - array_writer.CloseContainer(&dict_entry_writer); - - writer.CloseContainer(&array_writer); - - response_sender.Run(response.Pass()); - } - - // Called by dbus:: when a method is exported. - void OnExported(const std::string& interface_name, - const std::string& method_name, - bool success) { - LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "." - << method_name; - } - - // Origin thread (i.e. the UI thread in production). - base::PlatformThreadId origin_thread_id_; - - // 128-bit service UUID of this object. - std::string uuid_; - - // List of object paths that represent other exported GATT services that are - // included from this service. - std::vector<dbus::ObjectPath> includes_; - - // D-Bus bus object is exported on, not owned by this object and must - // outlive it. - dbus::Bus* bus_; - - // D-Bus object path of object we are exporting, kept so we can unregister - // again in our destructor. - dbus::ObjectPath object_path_; - - // D-Bus object we are exporting, owned by this object. - scoped_refptr<dbus::ExportedObject> exported_object_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<BluetoothGattServiceServiceProviderImpl> - weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothGattServiceServiceProviderImpl); -}; - -BluetoothGattServiceServiceProvider::BluetoothGattServiceServiceProvider() {} - -BluetoothGattServiceServiceProvider::~BluetoothGattServiceServiceProvider() {} - -// static -BluetoothGattServiceServiceProvider* -BluetoothGattServiceServiceProvider::Create( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - const std::string& uuid, - const std::vector<dbus::ObjectPath>& includes) { - if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) { - return new BluetoothGattServiceServiceProviderImpl(bus, object_path, uuid, - includes); - } - return new FakeBluetoothGattServiceServiceProvider(object_path, uuid, - includes); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_gatt_service_service_provider.h b/chromeos/dbus/bluetooth_gatt_service_service_provider.h deleted file mode 100644 index 258c4b4..0000000 --- a/chromeos/dbus/bluetooth_gatt_service_service_provider.h +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_ -#define CHROMEOS_DBUS_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_ - -#include <string> -#include <vector> - -#include "chromeos/chromeos_export.h" -#include "dbus/bus.h" -#include "dbus/object_path.h" - -namespace chromeos { - -// BluetoothGattServiceServiceProvider is used to provide a D-Bus object that -// the Bluetooth daemon can communicate with to register GATT service -// hierarchies. -// -// Instantiate with a chosen D-Bus object path (that conforms to the BlueZ GATT -// service specification), service UUID, and the list of included services, and -// pass the D-Bus object path as the |service_path| argument to the -// chromeos::BluetoothGattManagerClient::RegisterService method. Make sure to -// create characteristic and descriptor objects using the appropriate service -// providers before registering a GATT service with the Bluetooth daemon. -class CHROMEOS_EXPORT BluetoothGattServiceServiceProvider { - public: - virtual ~BluetoothGattServiceServiceProvider(); - - // Creates the instance where |bus| is the D-Bus bus connection to export the - // object onto, |object_path| is the object path that it should have, |uuid| - // is the 128-bit GATT service UUID, and |includes| are a list of object paths - // belonging to other exported GATT services that are included by the GATT - // service being created. Make sure that all included services have been - // exported before registering a GATT services with the GATT manager. - static BluetoothGattServiceServiceProvider* Create( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - const std::string& uuid, - const std::vector<dbus::ObjectPath>& includes); - - protected: - BluetoothGattServiceServiceProvider(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothGattServiceServiceProvider); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/bluetooth_input_client.cc b/chromeos/dbus/bluetooth_input_client.cc deleted file mode 100644 index e8b1c8d..0000000 --- a/chromeos/dbus/bluetooth_input_client.cc +++ /dev/null
@@ -1,128 +0,0 @@ -// Copyright 2013 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 "chromeos/dbus/bluetooth_input_client.h" - -#include <map> - -#include "base/logging.h" -#include "base/stl_util.h" -#include "dbus/bus.h" -#include "dbus/message.h" -#include "dbus/object_manager.h" -#include "dbus/object_proxy.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -BluetoothInputClient::Properties::Properties( - dbus::ObjectProxy* object_proxy, - const std::string& interface_name, - const PropertyChangedCallback& callback) - : dbus::PropertySet(object_proxy, interface_name, callback) { - RegisterProperty(bluetooth_input::kReconnectModeProperty, &reconnect_mode); -} - -BluetoothInputClient::Properties::~Properties() {} - -// The BluetoothInputClient implementation used in production. -class BluetoothInputClientImpl : public BluetoothInputClient, - public dbus::ObjectManager::Interface { - public: - BluetoothInputClientImpl() : object_manager_(NULL), weak_ptr_factory_(this) {} - - ~BluetoothInputClientImpl() override { - object_manager_->UnregisterInterface( - bluetooth_input::kBluetoothInputInterface); - } - - // BluetoothInputClient override. - void AddObserver(BluetoothInputClient::Observer* observer) override { - DCHECK(observer); - observers_.AddObserver(observer); - } - - // BluetoothInputClient override. - void RemoveObserver(BluetoothInputClient::Observer* observer) override { - DCHECK(observer); - observers_.RemoveObserver(observer); - } - - // dbus::ObjectManager::Interface override. - dbus::PropertySet* CreateProperties( - dbus::ObjectProxy* object_proxy, - const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - Properties* properties = - new Properties(object_proxy, interface_name, - base::Bind(&BluetoothInputClientImpl::OnPropertyChanged, - weak_ptr_factory_.GetWeakPtr(), object_path)); - return static_cast<dbus::PropertySet*>(properties); - } - - // BluetoothInputClient override. - Properties* GetProperties(const dbus::ObjectPath& object_path) override { - return static_cast<Properties*>(object_manager_->GetProperties( - object_path, bluetooth_input::kBluetoothInputInterface)); - } - - protected: - void Init(dbus::Bus* bus) override { - object_manager_ = bus->GetObjectManager( - bluetooth_object_manager::kBluetoothObjectManagerServiceName, - dbus::ObjectPath( - bluetooth_object_manager::kBluetoothObjectManagerServicePath)); - object_manager_->RegisterInterface( - bluetooth_input::kBluetoothInputInterface, this); - } - - private: - // Called by dbus::ObjectManager when an object with the input interface - // is created. Informs observers. - void ObjectAdded(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - FOR_EACH_OBSERVER(BluetoothInputClient::Observer, observers_, - InputAdded(object_path)); - } - - // Called by dbus::ObjectManager when an object with the input interface - // is removed. Informs observers. - void ObjectRemoved(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - FOR_EACH_OBSERVER(BluetoothInputClient::Observer, observers_, - InputRemoved(object_path)); - } - - // Called by BluetoothPropertySet when a property value is changed, - // either by result of a signal or response to a GetAll() or Get() - // call. Informs observers. - void OnPropertyChanged(const dbus::ObjectPath& object_path, - const std::string& property_name) { - FOR_EACH_OBSERVER(BluetoothInputClient::Observer, observers_, - InputPropertyChanged(object_path, property_name)); - } - - dbus::ObjectManager* object_manager_; - - // List of observers interested in event notifications from us. - base::ObserverList<BluetoothInputClient::Observer> observers_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<BluetoothInputClientImpl> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothInputClientImpl); -}; - -BluetoothInputClient::BluetoothInputClient() {} - -BluetoothInputClient::~BluetoothInputClient() {} - -BluetoothInputClient* BluetoothInputClient::Create() { - return new BluetoothInputClientImpl(); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_input_client.h b/chromeos/dbus/bluetooth_input_client.h deleted file mode 100644 index 02abf99..0000000 --- a/chromeos/dbus/bluetooth_input_client.h +++ /dev/null
@@ -1,81 +0,0 @@ -// Copyright 2013 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 CHROMEOS_DBUS_BLUETOOTH_INPUT_CLIENT_H_ -#define CHROMEOS_DBUS_BLUETOOTH_INPUT_CLIENT_H_ - -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/observer_list.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/dbus_client.h" -#include "dbus/object_path.h" -#include "dbus/property.h" - -namespace chromeos { - -// BluetoothInputClient is used to communicate with objects representing -// Bluetooth Input (HID) devices. -class CHROMEOS_EXPORT BluetoothInputClient : public DBusClient { - public: - // Structure of properties associated with bluetooth input devices. - struct Properties : public dbus::PropertySet { - // The Bluetooth input device reconnect mode. Read-only. - dbus::Property<std::string> reconnect_mode; - - Properties(dbus::ObjectProxy* object_proxy, - const std::string& interface_name, - const PropertyChangedCallback& callback); - ~Properties() override; - }; - - // Interface for observing changes from a remote bluetooth input device. - class Observer { - public: - virtual ~Observer() {} - - // Called when the remote device with object path |object_path| implementing - // the Input interface is added to the set of known devices or an already - // known device implements the Input interface. - virtual void InputAdded(const dbus::ObjectPath& object_path) {} - - // Called when the remote device with object path |object_path| is removed - // from the set of known devices or does not implement the Input interface - // anymore. - virtual void InputRemoved(const dbus::ObjectPath& object_path) {} - - // Called when the device with object path |object_path| has a - // change in value of the property named |property_name| of its Input - // interface. - virtual void InputPropertyChanged(const dbus::ObjectPath& object_path, - const std::string& property_name) {} - }; - - ~BluetoothInputClient() override; - - // Adds and removes observers for events on all remote bluetooth input - // devices. Check the |object_path| parameter of observer methods to - // determine which device is issuing the event. - virtual void AddObserver(Observer* observer) = 0; - virtual void RemoveObserver(Observer* observer) = 0; - - // Obtain the properties for the device with object path |object_path|, - // any values should be copied if needed. - virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; - - // Creates the instance. - static BluetoothInputClient* Create(); - - protected: - BluetoothInputClient(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothInputClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_INPUT_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_le_advertisement_service_provider.cc b/chromeos/dbus/bluetooth_le_advertisement_service_provider.cc deleted file mode 100644 index dfaeb5ef..0000000 --- a/chromeos/dbus/bluetooth_le_advertisement_service_provider.cc +++ /dev/null
@@ -1,426 +0,0 @@ -// Copyright 2015 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 "chromeos/dbus/bluetooth_le_advertisement_service_provider.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/stl_util.h" -#include "base/threading/platform_thread.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.h" -#include "dbus/exported_object.h" -#include "dbus/message.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -namespace { -const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs"; -} // namespace - -// The BluetoothAdvertisementServiceProvider implementation used in production. -class BluetoothAdvertisementServiceProviderImpl - : public BluetoothLEAdvertisementServiceProvider { - public: - BluetoothAdvertisementServiceProviderImpl( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate, - AdvertisementType type, - scoped_ptr<UUIDList> service_uuids, - scoped_ptr<ManufacturerData> manufacturer_data, - scoped_ptr<UUIDList> solicit_uuids, - scoped_ptr<ServiceData> service_data) - : origin_thread_id_(base::PlatformThread::CurrentId()), - bus_(bus), - delegate_(delegate), - type_(type), - service_uuids_(service_uuids.Pass()), - manufacturer_data_(manufacturer_data.Pass()), - solicit_uuids_(solicit_uuids.Pass()), - service_data_(service_data.Pass()), - weak_ptr_factory_(this) { - DCHECK(bus); - DCHECK(delegate); - - VLOG(1) << "Creating Bluetooth Advertisement: " << object_path_.value(); - - object_path_ = object_path; - exported_object_ = bus_->GetExportedObject(object_path_); - - // Export Bluetooth Advertisement interface methods. - exported_object_->ExportMethod( - bluetooth_advertisement::kBluetoothAdvertisementInterface, - bluetooth_advertisement::kRelease, - base::Bind(&BluetoothAdvertisementServiceProviderImpl::Release, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothAdvertisementServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - // Export dbus property methods. - exported_object_->ExportMethod( - dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet, - base::Bind(&BluetoothAdvertisementServiceProviderImpl::Get, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothAdvertisementServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll, - base::Bind(&BluetoothAdvertisementServiceProviderImpl::GetAll, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothAdvertisementServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - } - - ~BluetoothAdvertisementServiceProviderImpl() override { - VLOG(1) << "Cleaning up Bluetooth Advertisement: " << object_path_.value(); - - // Unregister the object path so we can reuse with a new agent. - bus_->UnregisterExportedObject(object_path_); - } - - private: - // Returns true if the current thread is on the origin thread. - bool OnOriginThread() { - return base::PlatformThread::CurrentId() == origin_thread_id_; - } - - // Called by dbus:: when this advertisement is unregistered from the Bluetooth - // daemon, generally by our request. - void Release(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - delegate_->Released(); - } - - // Called by dbus:: when the Bluetooth daemon fetches a single property of - // the descriptor. - void Get(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(2) << "BluetoothAdvertisementServiceProvider::Get: " - << object_path_.value(); - DCHECK(OnOriginThread()); - - dbus::MessageReader reader(method_call); - - std::string interface_name; - std::string property_name; - if (!reader.PopString(&interface_name) || - !reader.PopString(&property_name) || reader.HasMoreData()) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, - "Expected 'ss'."); - response_sender.Run(error_response.Pass()); - return; - } - - // Only the advertisement interface is supported. - if (interface_name != - bluetooth_advertisement::kBluetoothAdvertisementInterface) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidArgs, - "No such interface: '" + interface_name + "'."); - response_sender.Run(error_response.Pass()); - return; - } - - scoped_ptr<dbus::Response> response = - dbus::Response::FromMethodCall(method_call); - dbus::MessageWriter writer(response.get()); - dbus::MessageWriter variant_writer(NULL); - - if (property_name == bluetooth_advertisement::kTypeProperty) { - writer.OpenVariant("s", &variant_writer); - if (type_ == ADVERTISEMENT_TYPE_BROADCAST) { - variant_writer.AppendString("broadcast"); - } else { - variant_writer.AppendString("peripheral"); - } - } else if ((property_name == - bluetooth_advertisement::kServiceUUIDsProperty) && - service_uuids_) { - writer.OpenVariant("as", &variant_writer); - variant_writer.AppendArrayOfStrings(*service_uuids_); - } else if ((property_name == - bluetooth_advertisement::kSolicitUUIDsProperty) && - solicit_uuids_) { - writer.OpenVariant("as", &variant_writer); - variant_writer.AppendArrayOfStrings(*solicit_uuids_); - } else if ((property_name == - bluetooth_advertisement::kManufacturerDataProperty) && - manufacturer_data_) { - writer.OpenVariant("o", &variant_writer); - AppendManufacturerDataVariant(&variant_writer); - } else if ((property_name == - bluetooth_advertisement::kServiceDataProperty) && - service_data_) { - writer.OpenVariant("o", &variant_writer); - AppendServiceDataVariant(&variant_writer); - } else { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidArgs, - "No such property: '" + property_name + "'."); - response_sender.Run(error_response.Pass()); - } - - writer.CloseContainer(&variant_writer); - response_sender.Run(response.Pass()); - } - - // Called by dbus:: when the Bluetooth daemon fetches all properties of the - // descriptor. - void GetAll(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(2) << "BluetoothAdvertisementServiceProvider::GetAll: " - << object_path_.value(); - DCHECK(OnOriginThread()); - - dbus::MessageReader reader(method_call); - - std::string interface_name; - if (!reader.PopString(&interface_name) || reader.HasMoreData()) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, - "Expected 's'."); - response_sender.Run(error_response.Pass()); - return; - } - - // Only the advertisement interface is supported. - if (interface_name != - bluetooth_advertisement::kBluetoothAdvertisementInterface) { - scoped_ptr<dbus::ErrorResponse> error_response = - dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidArgs, - "No such interface: '" + interface_name + "'."); - response_sender.Run(error_response.Pass()); - return; - } - - response_sender.Run(CreateGetAllResponse(method_call).Pass()); - } - - // Called by dbus:: when a method is exported. - void OnExported(const std::string& interface_name, - const std::string& method_name, - bool success) { - LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "." - << method_name; - } - - // Helper for populating the DBus response with the advertisement data. - scoped_ptr<dbus::Response> CreateGetAllResponse( - dbus::MethodCall* method_call) { - VLOG(2) << "Descriptor value obtained from delegate. Responding to " - << "GetAll."; - - scoped_ptr<dbus::Response> response = - dbus::Response::FromMethodCall(method_call); - - dbus::MessageWriter writer(response.get()); - dbus::MessageWriter array_writer(NULL); - - writer.OpenArray("{sv}", &array_writer); - - AppendType(&array_writer); - AppendServiceUUIDs(&array_writer); - AppendManufacturerData(&array_writer); - AppendSolicitUUIDs(&array_writer); - AppendServiceData(&array_writer); - - writer.CloseContainer(&array_writer); - return response; - } - - // Called by the Delegate in response to a successful method call to get the - // descriptor value. - void OnGet(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender, - const std::vector<uint8>& value) { - VLOG(2) << "Returning descriptor value obtained from delegate."; - scoped_ptr<dbus::Response> response = - dbus::Response::FromMethodCall(method_call); - dbus::MessageWriter writer(response.get()); - dbus::MessageWriter variant_writer(NULL); - - writer.OpenVariant("ay", &variant_writer); - variant_writer.AppendArrayOfBytes(value.data(), value.size()); - writer.CloseContainer(&variant_writer); - - response_sender.Run(response.Pass()); - } - - void AppendArrayVariantOfStrings(dbus::MessageWriter* dict_writer, - const UUIDList& strings) { - dbus::MessageWriter strings_array_variant(nullptr); - dict_writer->OpenVariant("as", &strings_array_variant); - strings_array_variant.AppendArrayOfStrings(strings); - dict_writer->CloseContainer(&strings_array_variant); - } - - void AppendType(dbus::MessageWriter* array_writer) { - dbus::MessageWriter dict_entry_writer(NULL); - array_writer->OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString(bluetooth_advertisement::kTypeProperty); - if (type_ == ADVERTISEMENT_TYPE_BROADCAST) { - dict_entry_writer.AppendVariantOfString("broadcast"); - } else { - dict_entry_writer.AppendVariantOfString("peripheral"); - } - array_writer->CloseContainer(&dict_entry_writer); - } - - void AppendServiceUUIDs(dbus::MessageWriter* array_writer) { - if (!service_uuids_) - return; - dbus::MessageWriter dict_entry_writer(NULL); - array_writer->OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString( - bluetooth_advertisement::kServiceUUIDsProperty); - AppendArrayVariantOfStrings(&dict_entry_writer, *service_uuids_); - array_writer->CloseContainer(&dict_entry_writer); - } - - void AppendManufacturerData(dbus::MessageWriter* array_writer) { - if (!manufacturer_data_) - return; - dbus::MessageWriter dict_entry_writer(NULL); - array_writer->OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString( - bluetooth_advertisement::kManufacturerDataProperty); - dbus::MessageWriter variant_writer(NULL); - dict_entry_writer.OpenVariant("a{qay}", &variant_writer); - AppendManufacturerDataVariant(&variant_writer); - dict_entry_writer.CloseContainer(&variant_writer); - array_writer->CloseContainer(&dict_entry_writer); - } - - void AppendSolicitUUIDs(dbus::MessageWriter* array_writer) { - if (!solicit_uuids_) - return; - dbus::MessageWriter dict_entry_writer(NULL); - array_writer->OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString( - bluetooth_advertisement::kSolicitUUIDsProperty); - AppendArrayVariantOfStrings(&dict_entry_writer, *solicit_uuids_); - array_writer->CloseContainer(&dict_entry_writer); - } - - void AppendServiceData(dbus::MessageWriter* array_writer) { - if (!service_data_) - return; - dbus::MessageWriter dict_entry_writer(NULL); - array_writer->OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString( - bluetooth_advertisement::kServiceDataProperty); - dbus::MessageWriter variant_writer(NULL); - dict_entry_writer.OpenVariant("a{say}", &variant_writer); - AppendServiceDataVariant(&variant_writer); - dict_entry_writer.CloseContainer(&variant_writer); - array_writer->CloseContainer(&dict_entry_writer); - } - - void AppendManufacturerDataVariant(dbus::MessageWriter* writer) { - DCHECK(manufacturer_data_); - dbus::MessageWriter array_writer(NULL); - writer->OpenArray("{qay}", &array_writer); - for (const auto& m : *manufacturer_data_) { - dbus::MessageWriter entry_writer(NULL); - - array_writer.OpenDictEntry(&entry_writer); - - entry_writer.AppendUint32(m.first); - entry_writer.AppendArrayOfBytes(vector_as_array(&m.second), - m.second.size()); - - array_writer.CloseContainer(&entry_writer); - } - writer->CloseContainer(&array_writer); - } - - void AppendServiceDataVariant(dbus::MessageWriter* writer) { - DCHECK(service_data_); - dbus::MessageWriter array_writer(NULL); - writer->OpenArray("{say}", &array_writer); - for (const auto& m : *service_data_) { - dbus::MessageWriter entry_writer(NULL); - - array_writer.OpenDictEntry(&entry_writer); - - entry_writer.AppendString(m.first); - entry_writer.AppendArrayOfBytes(vector_as_array(&m.second), - m.second.size()); - - array_writer.CloseContainer(&entry_writer); - } - writer->CloseContainer(&array_writer); - } - - // Origin thread (i.e. the UI thread in production). - base::PlatformThreadId origin_thread_id_; - - // D-Bus bus object is exported on, not owned by this object and must - // outlive it. - dbus::Bus* bus_; - - // All incoming method calls are passed on to the Delegate and a callback - // passed to generate the reply. |delegate_| is generally the object that - // owns this one, and must outlive it. - Delegate* delegate_; - - // Advertisement data that needs to be provided to BlueZ when requested. - AdvertisementType type_; - scoped_ptr<UUIDList> service_uuids_; - scoped_ptr<ManufacturerData> manufacturer_data_; - scoped_ptr<UUIDList> solicit_uuids_; - scoped_ptr<ServiceData> service_data_; - - // D-Bus object we are exporting, owned by this object. - scoped_refptr<dbus::ExportedObject> exported_object_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<BluetoothAdvertisementServiceProviderImpl> - weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothAdvertisementServiceProviderImpl); -}; - -BluetoothLEAdvertisementServiceProvider:: - BluetoothLEAdvertisementServiceProvider() {} - -BluetoothLEAdvertisementServiceProvider:: - ~BluetoothLEAdvertisementServiceProvider() {} - -// static -scoped_ptr<BluetoothLEAdvertisementServiceProvider> -BluetoothLEAdvertisementServiceProvider::Create( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate, - AdvertisementType type, - scoped_ptr<UUIDList> service_uuids, - scoped_ptr<ManufacturerData> manufacturer_data, - scoped_ptr<UUIDList> solicit_uuids, - scoped_ptr<ServiceData> service_data) { - if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) { - return make_scoped_ptr(new BluetoothAdvertisementServiceProviderImpl( - bus, object_path, delegate, type, service_uuids.Pass(), - manufacturer_data.Pass(), solicit_uuids.Pass(), service_data.Pass())); - } else { - return make_scoped_ptr( - new FakeBluetoothLEAdvertisementServiceProvider(object_path, delegate)); - } -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_le_advertisement_service_provider.h b/chromeos/dbus/bluetooth_le_advertisement_service_provider.h deleted file mode 100644 index 98622a2a..0000000 --- a/chromeos/dbus/bluetooth_le_advertisement_service_provider.h +++ /dev/null
@@ -1,82 +0,0 @@ -// Copyright 2015 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 CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_ -#define CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_ - -#include <stdint.h> - -#include <map> -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "chromeos/chromeos_export.h" -#include "dbus/bus.h" -#include "dbus/file_descriptor.h" -#include "dbus/object_path.h" - -namespace chromeos { - -// BluetoothAdvertisementServiceProvider is used to provide a D-Bus object that -// the Bluetooth daemon can communicate with to advertise data. -class CHROMEOS_EXPORT BluetoothLEAdvertisementServiceProvider { - public: - using UUIDList = std::vector<std::string>; - using ManufacturerData = std::map<uint16_t, std::vector<uint8_t>>; - using ServiceData = std::map<std::string, std::vector<uint8_t>>; - - // Type of advertisement. - enum AdvertisementType { - ADVERTISEMENT_TYPE_BROADCAST, - ADVERTISEMENT_TYPE_PERIPHERAL - }; - - // Interface for reacting to advertisement changes. - class Delegate { - public: - virtual ~Delegate() {} - - // This method will be called when the advertisement is unregistered from - // the Bluetooth daemon, generally at shutdown or if the adapter goes away. - // It may be used to perform cleanup tasks. This corresponds to the - // org.bluez.LEAdvertisement1.Release method and is renamed to avoid a - // conflict with base::Refcounted<T>. - virtual void Released() = 0; - }; - - virtual ~BluetoothLEAdvertisementServiceProvider(); - - const dbus::ObjectPath& object_path() { return object_path_; } - - // Creates the instance where |bus| is the D-Bus bus connection to export - // the object onto, |object_path| is the object path that it should have - // and |delegate| is the object to which all method calls will be passed - // and responses generated from. - static scoped_ptr<BluetoothLEAdvertisementServiceProvider> Create( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate, - AdvertisementType type, - scoped_ptr<UUIDList> service_uuids, - scoped_ptr<ManufacturerData> manufacturer_data, - scoped_ptr<UUIDList> solicit_uuids, - scoped_ptr<ServiceData> service_data); - - protected: - BluetoothLEAdvertisementServiceProvider(); - - // D-Bus object path of object we are exporting, kept so we can unregister - // again in our destructor. - dbus::ObjectPath object_path_; - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothLEAdvertisementServiceProvider); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/bluetooth_le_advertising_manager_client.cc b/chromeos/dbus/bluetooth_le_advertising_manager_client.cc deleted file mode 100644 index ca2c9e20f..0000000 --- a/chromeos/dbus/bluetooth_le_advertising_manager_client.cc +++ /dev/null
@@ -1,187 +0,0 @@ -// Copyright 2015 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 "chromeos/dbus/bluetooth_le_advertising_manager_client.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/observer_list.h" -#include "dbus/bus.h" -#include "dbus/message.h" -#include "dbus/object_manager.h" -#include "dbus/object_proxy.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -const char BluetoothLEAdvertisingManagerClient::kNoResponseError[] = - "org.chromium.Error.NoResponse"; - -// The BluetoothAdvertisementManagerClient implementation used in production. -class BluetoothAdvertisementManagerClientImpl - : public BluetoothLEAdvertisingManagerClient, - public dbus::ObjectManager::Interface { - public: - BluetoothAdvertisementManagerClientImpl() - : object_manager_(NULL), weak_ptr_factory_(this) {} - - ~BluetoothAdvertisementManagerClientImpl() override { - if (object_manager_) { - object_manager_->UnregisterInterface( - bluetooth_advertising_manager::kBluetoothAdvertisingManagerInterface); - } - } - - // BluetoothAdapterClient override. - void AddObserver( - BluetoothLEAdvertisingManagerClient::Observer* observer) override { - DCHECK(observer); - observers_.AddObserver(observer); - } - - // BluetoothAdapterClient override. - void RemoveObserver( - BluetoothLEAdvertisingManagerClient::Observer* observer) override { - DCHECK(observer); - observers_.RemoveObserver(observer); - } - - // dbus::ObjectManager::Interface override. - dbus::PropertySet* CreateProperties( - dbus::ObjectProxy* object_proxy, - const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - return new dbus::PropertySet(object_proxy, interface_name, - dbus::PropertySet::PropertyChangedCallback()); - } - - // BluetoothAdvertisementManagerClient override. - void RegisterAdvertisement(const dbus::ObjectPath& manager_object_path, - const dbus::ObjectPath& advertisement_object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call( - bluetooth_advertising_manager::kBluetoothAdvertisingManagerInterface, - bluetooth_advertising_manager::kRegisterAdvertisement); - - dbus::MessageWriter writer(&method_call); - writer.AppendObjectPath(advertisement_object_path); - - // Empty dictionary for options. - dbus::MessageWriter array_writer(NULL); - writer.OpenArray("{sv}", &array_writer); - writer.CloseContainer(&array_writer); - - DCHECK(object_manager_); - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(manager_object_path); - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothAdvertisementManagerClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothAdvertisementManagerClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothAdvertisementManagerClient override. - void UnregisterAdvertisement( - const dbus::ObjectPath& manager_object_path, - const dbus::ObjectPath& advertisement_object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call( - bluetooth_advertising_manager::kBluetoothAdvertisingManagerInterface, - bluetooth_advertising_manager::kUnregisterAdvertisement); - - dbus::MessageWriter writer(&method_call); - writer.AppendObjectPath(advertisement_object_path); - - DCHECK(object_manager_); - dbus::ObjectProxy* object_proxy = - object_manager_->GetObjectProxy(manager_object_path); - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothAdvertisementManagerClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothAdvertisementManagerClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - protected: - void Init(dbus::Bus* bus) override { - DCHECK(bus); - object_manager_ = bus->GetObjectManager( - bluetooth_object_manager::kBluetoothObjectManagerServiceName, - dbus::ObjectPath( - bluetooth_object_manager::kBluetoothObjectManagerServicePath)); - object_manager_->RegisterInterface( - bluetooth_advertising_manager::kBluetoothAdvertisingManagerInterface, - this); - } - - private: - // Called by dbus::ObjectManager when an object with the advertising manager - // interface is created. Informs observers. - void ObjectAdded(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - FOR_EACH_OBSERVER(BluetoothLEAdvertisingManagerClient::Observer, observers_, - AdvertisingManagerAdded(object_path)); - } - - // Called by dbus::ObjectManager when an object with the advertising manager - // interface is removed. Informs observers. - void ObjectRemoved(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - FOR_EACH_OBSERVER(BluetoothLEAdvertisingManagerClient::Observer, observers_, - AdvertisingManagerRemoved(object_path)); - } - - // Called when a response for successful method call is received. - void OnSuccess(const base::Closure& callback, dbus::Response* response) { - DCHECK(response); - callback.Run(); - } - - // Called when a response for a failed method call is received. - void OnError(const ErrorCallback& error_callback, - dbus::ErrorResponse* response) { - // Error response has optional error message argument. - std::string error_name; - std::string error_message; - if (response) { - dbus::MessageReader reader(response); - error_name = response->GetErrorName(); - reader.PopString(&error_message); - } else { - error_name = kNoResponseError; - error_message = ""; - } - error_callback.Run(error_name, error_message); - } - - dbus::ObjectManager* object_manager_; - - // List of observers interested in event notifications from us. - base::ObserverList<BluetoothLEAdvertisingManagerClient::Observer> observers_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<BluetoothAdvertisementManagerClientImpl> - weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothAdvertisementManagerClientImpl); -}; - -BluetoothLEAdvertisingManagerClient::BluetoothLEAdvertisingManagerClient() {} - -BluetoothLEAdvertisingManagerClient::~BluetoothLEAdvertisingManagerClient() {} - -BluetoothLEAdvertisingManagerClient* -BluetoothLEAdvertisingManagerClient::Create() { - return new BluetoothAdvertisementManagerClientImpl(); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_le_advertising_manager_client.h b/chromeos/dbus/bluetooth_le_advertising_manager_client.h deleted file mode 100644 index 5160a9f5..0000000 --- a/chromeos/dbus/bluetooth_le_advertising_manager_client.h +++ /dev/null
@@ -1,83 +0,0 @@ -// Copyright 2015 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 CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_ -#define CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_ - -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "base/values.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/dbus_client.h" -#include "dbus/object_path.h" - -namespace chromeos { - -// BluetoothAdvertisingManagerClient is used to communicate with the advertising -// manager object of the BlueZ daemon. -class CHROMEOS_EXPORT BluetoothLEAdvertisingManagerClient : public DBusClient { - public: - // Interface for observing changes to advertising managers. - class Observer { - public: - virtual ~Observer() {} - - // Called when an advertising manager with object path |object_path| is - // added to the system. - virtual void AdvertisingManagerAdded(const dbus::ObjectPath& object_path) {} - - // Called when an advertising manager with object path |object_path| is - // removed from the system. - virtual void AdvertisingManagerRemoved( - const dbus::ObjectPath& object_path) {} - }; - - ~BluetoothLEAdvertisingManagerClient() override; - - // Adds and removes observers for events which change the advertising - // managers on the system. - virtual void AddObserver(Observer* observer) = 0; - virtual void RemoveObserver(Observer* observer) = 0; - - // The ErrorCallback is used by advertising manager methods to indicate - // failure. It receives two arguments: the name of the error in |error_name| - // and an optional message in |error_message|. - using ErrorCallback = base::Callback<void(const std::string& error_name, - const std::string& error_message)>; - - // Registers an advertisement with the DBus object path - // |advertisement_object_path| with BlueZ's advertising manager. - virtual void RegisterAdvertisement( - const dbus::ObjectPath& manager_object_path, - const dbus::ObjectPath& advertisement_object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Unregisters an advertisement with the DBus object path - // |advertisement_object_path| with BlueZ's advertising manager. - virtual void UnregisterAdvertisement( - const dbus::ObjectPath& manager_object_path, - const dbus::ObjectPath& advertisement_object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Creates the instance. - static BluetoothLEAdvertisingManagerClient* Create(); - - // Constants used to indicate exceptional error conditions. - static const char kNoResponseError[]; - - protected: - BluetoothLEAdvertisingManagerClient(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothLEAdvertisingManagerClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_media_client.cc b/chromeos/dbus/bluetooth_media_client.cc deleted file mode 100644 index 301f765..0000000 --- a/chromeos/dbus/bluetooth_media_client.cc +++ /dev/null
@@ -1,227 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/bluetooth_media_client.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/observer_list.h" -#include "dbus/bus.h" -#include "dbus/message.h" -#include "dbus/object_manager.h" -#include "dbus/object_proxy.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace { - -// Since there is no property associated with Media objects, an empty callback -// is used. -void DoNothing(const std::string& property_name) {} - -// TODO(mcchou): Add these service constants into dbus/service_constants.h -// later. -const char kBluetoothMediaInterface[] = "org.bluez.Media1"; - -// Method names supported by Media Interface. -const char kRegisterEndpoint[] = "RegisterEndpoint"; -const char kUnregisterEndpoint[] = "UnregisterEndpoint"; - -// The set of properties which are used to register a media endpoint. -const char kUUIDEndpointProperty[] = "UUID"; -const char kCodecEndpointProperty[] = "Codec"; -const char kCapabilitiesEndpointProperty[] = "Capabilities"; - -} // namespace - -namespace chromeos { - -// static -const char BluetoothMediaClient::kNoResponseError[] = - "org.chromium.Error.NoResponse"; - -// static -const char BluetoothMediaClient::kBluetoothAudioSinkUUID[] = - "0000110b-0000-1000-8000-00805f9b34fb"; - -BluetoothMediaClient::EndpointProperties::EndpointProperties() : codec(0x00) {} - -BluetoothMediaClient::EndpointProperties::~EndpointProperties() {} - -class BluetoothMediaClientImpl : public BluetoothMediaClient, - dbus::ObjectManager::Interface { - public: - BluetoothMediaClientImpl() - : object_manager_(nullptr), weak_ptr_factory_(this) {} - - ~BluetoothMediaClientImpl() override { - object_manager_->UnregisterInterface(kBluetoothMediaInterface); - } - - // dbus::ObjectManager::Interface overrides. - - dbus::PropertySet* CreateProperties( - dbus::ObjectProxy* object_proxy, - const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - return new dbus::PropertySet(object_proxy, interface_name, - base::Bind(&DoNothing)); - } - - void ObjectAdded(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - VLOG(1) << "Remote Media added: " << object_path.value(); - FOR_EACH_OBSERVER(BluetoothMediaClient::Observer, observers_, - MediaAdded(object_path)); - } - - void ObjectRemoved(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - VLOG(1) << "Remote Media removed: " << object_path.value(); - FOR_EACH_OBSERVER(BluetoothMediaClient::Observer, observers_, - MediaRemoved(object_path)); - } - - // BluetoothMediaClient overrides. - - void AddObserver(BluetoothMediaClient::Observer* observer) override { - DCHECK(observer); - observers_.AddObserver(observer); - } - - void RemoveObserver(BluetoothMediaClient::Observer* observer) override { - DCHECK(observer); - observers_.RemoveObserver(observer); - } - - void RegisterEndpoint(const dbus::ObjectPath& object_path, - const dbus::ObjectPath& endpoint_path, - const EndpointProperties& properties, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - VLOG(1) << "RegisterEndpoint - endpoint: " << endpoint_path.value(); - - dbus::MethodCall method_call(kBluetoothMediaInterface, kRegisterEndpoint); - - dbus::MessageWriter writer(&method_call); - dbus::MessageWriter array_writer(nullptr); - dbus::MessageWriter dict_entry_writer(nullptr); - - // Send the path to the endpoint. - writer.AppendObjectPath(endpoint_path); - - writer.OpenArray("{sv}", &array_writer); - - // Send UUID. - array_writer.OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString(kUUIDEndpointProperty); - dict_entry_writer.AppendVariantOfString(properties.uuid); - array_writer.CloseContainer(&dict_entry_writer); - - // Send Codec. - array_writer.OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString(kCodecEndpointProperty); - dict_entry_writer.AppendVariantOfByte(properties.codec); - array_writer.CloseContainer(&dict_entry_writer); - - // Send Capabilities. - dbus::MessageWriter variant_writer(nullptr); - array_writer.OpenDictEntry(&dict_entry_writer); - dict_entry_writer.AppendString(kCapabilitiesEndpointProperty); - dict_entry_writer.OpenVariant("ay", &variant_writer); - variant_writer.AppendArrayOfBytes(properties.capabilities.data(), - properties.capabilities.size()); - dict_entry_writer.CloseContainer(&variant_writer); - array_writer.CloseContainer(&dict_entry_writer); - - writer.CloseContainer(&array_writer); - - // Get Object Proxy based on the service name and the service path and call - // RegisterEndpoint medthod. - scoped_refptr<dbus::ObjectProxy> object_proxy( - object_manager_->GetObjectProxy(object_path)); - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothMediaClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothMediaClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - void UnregisterEndpoint(const dbus::ObjectPath& object_path, - const dbus::ObjectPath& endpoint_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - VLOG(1) << "UnregisterEndpoint - endpoint: " << endpoint_path.value(); - - dbus::MethodCall method_call(kBluetoothMediaInterface, kUnregisterEndpoint); - - // Send the path to the endpoint. - dbus::MessageWriter writer(&method_call); - writer.AppendObjectPath(endpoint_path); - - // Get Object Proxy based on the service name and the service path and call - // RegisterEndpoint medthod. - scoped_refptr<dbus::ObjectProxy> object_proxy( - object_manager_->GetObjectProxy(object_path)); - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothMediaClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothMediaClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - protected: - void Init(dbus::Bus* bus) override { - DCHECK(bus); - object_manager_ = bus->GetObjectManager( - bluetooth_object_manager::kBluetoothObjectManagerServiceName, - dbus::ObjectPath( - bluetooth_object_manager::kBluetoothObjectManagerServicePath)); - object_manager_->RegisterInterface(kBluetoothMediaInterface, this); - } - - private: - // Called when a response for successful method call is received. - void OnSuccess(const base::Closure& callback, dbus::Response* response) { - DCHECK(response); - callback.Run(); - } - - // Called when a response for a failed method call is received. - void OnError(const ErrorCallback& error_callback, - dbus::ErrorResponse* response) { - // Error response has an optional error message argument. - std::string error_name; - std::string error_message; - if (response) { - dbus::MessageReader reader(response); - error_name = response->GetErrorName(); - reader.PopString(&error_message); - } else { - error_name = kNoResponseError; - } - error_callback.Run(error_name, error_message); - } - - dbus::ObjectManager* object_manager_; - - // List of observers interested in event notifications from us. - base::ObserverList<BluetoothMediaClient::Observer> observers_; - - base::WeakPtrFactory<BluetoothMediaClientImpl> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothMediaClientImpl); -}; - -BluetoothMediaClient::BluetoothMediaClient() {} - -BluetoothMediaClient::~BluetoothMediaClient() {} - -BluetoothMediaClient* BluetoothMediaClient::Create() { - return new BluetoothMediaClientImpl(); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_media_client.h b/chromeos/dbus/bluetooth_media_client.h deleted file mode 100644 index 1bb55478..0000000 --- a/chromeos/dbus/bluetooth_media_client.h +++ /dev/null
@@ -1,107 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_BLUETOOTH_MEDIA_CLIENT_H_ -#define CHROMEOS_DBUS_BLUETOOTH_MEDIA_CLIENT_H_ - -#include <memory> -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/values.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/dbus_client.h" -#include "dbus/object_path.h" -#include "dbus/property.h" - -namespace chromeos { - -// BluetoothMediaClient is used to communicate with the Media interface of a -// local Bluetooth adapter. -class CHROMEOS_EXPORT BluetoothMediaClient : public DBusClient { - public: - // Properties used to register a Media Endpoint. - struct CHROMEOS_EXPORT EndpointProperties { - EndpointProperties(); - ~EndpointProperties(); - - // UUID of the profile implemented by the endpoint. - std::string uuid; - - // Assigned codec value supported by the endpoint. The byte should match the - // codec specification indicated by the UUID. - // Since SBC codec is mandatory for A2DP, the default value of codec should - // be 0x00. - uint8_t codec; - - // Capabilities of the endpoints. The order of bytes should match the bit - // arrangement in the specification indicated by the UUID. - std::vector<uint8_t> capabilities; - }; - - class Observer { - public: - virtual ~Observer() {} - - // Called when the Media object with object path |object_path| is added to - // the system. - virtual void MediaAdded(const dbus::ObjectPath& object_path) {} - - // Called when the Media object with object path |object_path| is removed - // from the system. - virtual void MediaRemoved(const dbus::ObjectPath& object_path) {} - }; - - // Constants used to indicate exceptional error conditions. - static const char kNoResponseError[]; - - // The string representation for the 128-bit UUID for A2DP Sink. - static const char kBluetoothAudioSinkUUID[]; - - ~BluetoothMediaClient() override; - - // The ErrorCallback is used by media API methods to indicate failure. - // It receives two arguments: the name of the error in |error_name| and - // an optional message in |error_message|. - typedef base::Callback<void(const std::string& error_name, - const std::string& error_message)> ErrorCallback; - - // Adds and removes observers for events on all Media objects. Check the - // |object_path| parameter of observer methods to determine which Media object - // is issuing the event. - virtual void AddObserver(Observer* observer) = 0; - virtual void RemoveObserver(Observer* observer) = 0; - - // Registers a media endpoint to sender at the D-Bus object path - // |endpoint_path|. |properties| specifies profile UUID which the endpoint is - // for, Codec implemented by the endpoint and the Capabilities of the - // endpoint. - virtual void RegisterEndpoint(const dbus::ObjectPath& object_path, - const dbus::ObjectPath& endpoint_path, - const EndpointProperties& properties, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Unregisters the media endpoint with the D-Bus object path |endpoint_path|. - virtual void UnregisterEndpoint(const dbus::ObjectPath& object_path, - const dbus::ObjectPath& endpoint_path, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // TODO(mcchou): The RegisterPlayer and UnregisterPlayer methods are not - // included, since they are not used. These two methods may be added later. - - static BluetoothMediaClient* Create(); - - protected: - BluetoothMediaClient(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothMediaClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_MEDIA_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_media_endpoint_service_provider.cc b/chromeos/dbus/bluetooth_media_endpoint_service_provider.cc deleted file mode 100644 index 9dd77200..0000000 --- a/chromeos/dbus/bluetooth_media_endpoint_service_provider.cc +++ /dev/null
@@ -1,313 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/bluetooth_media_endpoint_service_provider.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/threading/platform_thread.h" -#include "chromeos/dbus/bluetooth_media_transport_client.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h" -#include "dbus/exported_object.h" - -namespace { - -// TODO(mcchou): Move these constants to dbus/service_constants.h. -// Bluetooth Media Endpoint service identifier. -const char kBluetoothMediaEndpointInterface[] = "org.bluez.MediaEndpoint1"; - -// Method names in Bluetooth Media Endpoint interface. -const char kSetConfiguration[] = "SetConfiguration"; -const char kSelectConfiguration[] = "SelectConfiguration"; -const char kClearConfiguration[] = "ClearConfiguration"; -const char kRelease[] = "Release"; - -const uint8_t kInvalidCodec = 0xff; -const char kInvalidState[] = "unknown"; - -} // namespace - -namespace chromeos { - -// The BluetoothMediaEndopintServiceProvider implementation used in production. -class CHROMEOS_EXPORT BluetoothMediaEndpointServiceProviderImpl - : public BluetoothMediaEndpointServiceProvider { - public: - BluetoothMediaEndpointServiceProviderImpl(dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate) - : origin_thread_id_(base::PlatformThread::CurrentId()), - bus_(bus), - delegate_(delegate), - object_path_(object_path), - weak_ptr_factory_(this) { - VLOG(1) << "Creating Bluetooth Media Endpoint: " << object_path_.value(); - DCHECK(bus_); - DCHECK(delegate_); - DCHECK(object_path_.IsValid()); - - exported_object_ = bus_->GetExportedObject(object_path_); - - exported_object_->ExportMethod( - kBluetoothMediaEndpointInterface, kSetConfiguration, - base::Bind(&BluetoothMediaEndpointServiceProviderImpl::SetConfiguration, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - kBluetoothMediaEndpointInterface, kSelectConfiguration, - base::Bind( - &BluetoothMediaEndpointServiceProviderImpl::SelectConfiguration, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - kBluetoothMediaEndpointInterface, kClearConfiguration, - base::Bind( - &BluetoothMediaEndpointServiceProviderImpl::ClearConfiguration, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - kBluetoothMediaEndpointInterface, kRelease, - base::Bind(&BluetoothMediaEndpointServiceProviderImpl::Release, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - } - - ~BluetoothMediaEndpointServiceProviderImpl() override { - VLOG(1) << "Cleaning up Bluetooth Media Endpoint: " << object_path_.value(); - - bus_->UnregisterExportedObject(object_path_); - } - - private: - // Returns true if the current thread is on the origin thread, false - // otherwise. - bool OnOriginThread() const { - return base::PlatformThread::CurrentId() == origin_thread_id_; - } - - // Called by dbus:: when a method is exported. - void OnExported(const std::string& interface_name, - const std::string& method_name, - bool success) { - LOG_IF(ERROR, !success) << "Failed to export " << interface_name << "." - << method_name; - } - - // Called by dbus:: when the remote device connects to the Media Endpoint. - void SetConfiguration(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(1) << "SetConfiguration"; - - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - dbus::MessageReader reader(method_call); - dbus::ObjectPath transport_path; - dbus::MessageReader property_reader(method_call); - if (!reader.PopObjectPath(&transport_path) || - !reader.PopArray(&property_reader)) { - LOG(ERROR) << "SetConfiguration called with incorrect parameters: " - << method_call->ToString(); - return; - } - - // Parses |properties| and passes the property set as a - // Delegate::TransportProperties structure to |delegate_|. - Delegate::TransportProperties properties; - while (property_reader.HasMoreData()) { - dbus::MessageReader dict_entry_reader(nullptr); - std::string key; - if (!property_reader.PopDictEntry(&dict_entry_reader) || - !dict_entry_reader.PopString(&key)) { - LOG(ERROR) << "SetConfiguration called with incorrect parameters: " - << method_call->ToString(); - } else if (key == BluetoothMediaTransportClient::kDeviceProperty) { - dict_entry_reader.PopVariantOfObjectPath(&properties.device); - } else if (key == BluetoothMediaTransportClient::kUUIDProperty) { - dict_entry_reader.PopVariantOfString(&properties.uuid); - } else if (key == BluetoothMediaTransportClient::kCodecProperty) { - dict_entry_reader.PopVariantOfByte(&properties.codec); - } else if (key == BluetoothMediaTransportClient::kConfigurationProperty) { - dbus::MessageReader variant_reader(nullptr); - const uint8_t* bytes = nullptr; - size_t length = 0; - dict_entry_reader.PopVariant(&variant_reader); - variant_reader.PopArrayOfBytes(&bytes, &length); - properties.configuration.assign(bytes, bytes + length); - } else if (key == BluetoothMediaTransportClient::kStateProperty) { - dict_entry_reader.PopVariantOfString(&properties.state); - } else if (key == BluetoothMediaTransportClient::kDelayProperty) { - properties.delay.reset(new uint16_t()); - dict_entry_reader.PopVariantOfUint16(properties.delay.get()); - } else if (key == BluetoothMediaTransportClient::kVolumeProperty) { - properties.volume.reset(new uint16_t()); - dict_entry_reader.PopVariantOfUint16(properties.volume.get()); - } - } - - if (properties.codec != kInvalidCodec && - properties.state != kInvalidState) { - delegate_->SetConfiguration(transport_path, properties); - } else { - LOG(ERROR) << "SetConfiguration called with incorrect parameters: " - << method_call->ToString(); - } - - response_sender.Run(dbus::Response::FromMethodCall(method_call)); - } - - // Called by dbus:: when the remote device receives the configuration for - // media transport. - void SelectConfiguration( - dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(1) << "SelectConfiguration"; - - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - dbus::MessageReader reader(method_call); - const uint8_t* capabilities = nullptr; - size_t length = 0; - if (!reader.PopArrayOfBytes(&capabilities, &length)) { - LOG(ERROR) << "SelectConfiguration called with incorrect parameters: " - << method_call->ToString(); - return; - } - - std::vector<uint8_t> configuration(capabilities, capabilities + length); - - // |delegate_| generates the response to |SelectConfiguration| and sends it - // back via |callback|. - Delegate::SelectConfigurationCallback callback = base::Bind( - &BluetoothMediaEndpointServiceProviderImpl::OnConfiguration, - weak_ptr_factory_.GetWeakPtr(), method_call, response_sender); - - delegate_->SelectConfiguration(configuration, callback); - } - - // Called by dbus:: when the remote device is about to close the connection. - void ClearConfiguration( - dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(1) << "ClearConfiguration"; - - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - dbus::MessageReader reader(method_call); - dbus::ObjectPath transport_path; - if (!reader.PopObjectPath(&transport_path)) { - LOG(ERROR) << "ClearConfiguration called with incorrect parameters: " - << method_call->ToString(); - return; - } - - delegate_->ClearConfiguration(transport_path); - - response_sender.Run(dbus::Response::FromMethodCall(method_call)); - } - - // Called by Bluetooth daemon to do the clean up after unregistering the Media - // Endpoint. - void Release(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - VLOG(1) << "Release"; - - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - delegate_->Released(); - - response_sender.Run(dbus::Response::FromMethodCall(method_call)); - } - - // Called by Delegate to response to a method requiring transport - // configuration. - void OnConfiguration(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender, - const std::vector<uint8_t>& configuration) { - VLOG(1) << "OnConfiguration"; - - DCHECK(OnOriginThread()); - - // Generates the response to the method call. - scoped_ptr<dbus::Response> response( - dbus::Response::FromMethodCall(method_call)); - dbus::MessageWriter writer(response.get()); - if (configuration.empty()) { - LOG(ERROR) << "OnConfiguration called with empty configuration."; - writer.AppendArrayOfBytes(nullptr, 0); - } else { - writer.AppendArrayOfBytes(&configuration[0], configuration.size()); - } - response_sender.Run(response.Pass()); - } - - // Origin thread (i.e. the UI thread in production). - base::PlatformThreadId origin_thread_id_; - - // D-Bus Bus object is exported on. - dbus::Bus* bus_; - - // All incoming method calls are passed on to |delegate_|. |callback| passed - // to |delegate+| will generate the response for those methods whose returns - // are non-void. - Delegate* delegate_; - - // D-Bus object path of the object we are exporting, kept so we can unregister - // again in you destructor. - dbus::ObjectPath object_path_; - - // D-Bus object we are exporting, owned by this object. - scoped_refptr<dbus::ExportedObject> exported_object_; - - // Weak pointer factory for generating 'this' printers that might live longer - // than we do. - // Note This should remain the last member so it'll be destroyed and - // invalidate it's weak pointers before any other members are destroyed. - base::WeakPtrFactory<BluetoothMediaEndpointServiceProviderImpl> - weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothMediaEndpointServiceProviderImpl); -}; - -BluetoothMediaEndpointServiceProvider::Delegate::TransportProperties:: - TransportProperties() - : codec(kInvalidCodec), state(kInvalidState) {} - -BluetoothMediaEndpointServiceProvider::Delegate::TransportProperties:: - ~TransportProperties() {} - -BluetoothMediaEndpointServiceProvider::BluetoothMediaEndpointServiceProvider() { -} - -BluetoothMediaEndpointServiceProvider:: - ~BluetoothMediaEndpointServiceProvider() {} - -BluetoothMediaEndpointServiceProvider* -BluetoothMediaEndpointServiceProvider::Create( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate) { - // Returns a real implementation. - if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) { - return new BluetoothMediaEndpointServiceProviderImpl(bus, object_path, - delegate); - } - // Returns a fake implementation. - return new FakeBluetoothMediaEndpointServiceProvider(object_path, delegate); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_media_endpoint_service_provider.h b/chromeos/dbus/bluetooth_media_endpoint_service_provider.h deleted file mode 100644 index fffaa533..0000000 --- a/chromeos/dbus/bluetooth_media_endpoint_service_provider.h +++ /dev/null
@@ -1,133 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_ -#define CHROMEOS_DBUS_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_ - -#include <string> -#include <vector> - -#include "base/callback.h" -#include "chromeos/chromeos_export.h" -#include "dbus/bus.h" -#include "dbus/message.h" -#include "dbus/object_path.h" - -namespace chromeos { - -// BluetoothMediaEndpointServiceProvider is used to provide a D-Bus object that -// the Bluetooth daemon can commuicate with to serve as a media source/sink. -// -// Instantiate with a chosen D-Bus object path and a delegate object, and pass -// the D-Bus object path as |endpoint_path| argument to the -// chromeos::BluetoothMediaClient::RegisterEndoint() method. -// -// After initiating a connection between an audio source and an audio sink, the -// Bluetooth daemon will make calls to this endpoint object and they will be -// passed to user's Delegate object for handling. For SelectConfiguration method -// the response is returned using the SelectConfiguration callback. -class CHROMEOS_EXPORT BluetoothMediaEndpointServiceProvider { - public: - // Delegate is the interface for reacting to endpoint requests. User - // applications will implement this interface to handle either A2DP Sink or - // Source. - class Delegate { - public: - // Transport-specific properties. - struct CHROMEOS_EXPORT TransportProperties { - TransportProperties(); - ~TransportProperties(); - - // The path to the device object which the transport is connected to. - dbus::ObjectPath device; - - // The UUID of the profile which the transport is for. - std::string uuid; - - // The Codec value agreed by the remote device and used by the media - // transport. - uint8_t codec; - - // The configuration used by the media transport. - std::vector<uint8_t> configuration; - - // The state of the transport. The values can be one of the following: - // "idle": not streaming - // "pending": streaming but not acquired - // "active": streaming and acquired - std::string state; - - // The unit of transport is in 1/10 millisecond. Optional. - scoped_ptr<uint16_t> delay; - - // The volume level of the transport. Optional. - scoped_ptr<uint16_t> volume; - - private: - DISALLOW_COPY_AND_ASSIGN(TransportProperties); - }; - - virtual ~Delegate() {} - - // SelectConfigurationCallback is used for the SelectConfiguration() method, - // it should be called with two arguements, the |configuration| which is - // agreed by the application and the |length| of |configuration|. - typedef base::Callback<void(const std::vector<uint8_t>&)> - SelectConfigurationCallback; - - // This method will be called after an Audio Source receives the agreed - // capabilities from the Audio Sink to set the configuration for the - // media transport object. |transport_path| is the path to the - // MediaTransport object, and |properties| are the properties for that - // MediaTransport object. - virtual void SetConfiguration(const dbus::ObjectPath& transport_path, - const TransportProperties& properties) = 0; - - // This method will be called when an Audio Source connects to an Audio Sink - // and asks it to decide the configuration to be used during the oncoming - // streaming. Audio Sources provide |capabilities| as a reference, where - // a user application can use these |capabilities| to figure out - // a well-matched configuration and return it to the Audio Source via - // |callback|. - virtual void SelectConfiguration( - const std::vector<uint8_t>& capabilities, - const SelectConfigurationCallback& callback) = 0; - - // This method will be called when an Audio Source disconnects from an Audio - // Sink. A user application is supposed to clear any of its resources which - // it keeps for that particular connection. |transport_path| is the Media - // Transport object which has been kept by an endpoint during the - // connection. - virtual void ClearConfiguration(const dbus::ObjectPath& transport_path) = 0; - - // This method will be called when the Bluetooth daemon unregisters the - // Media Endpoint. Media Endpoint objects can use this method to clean up - // tasks. There is no need to unregister the endpoint, since when this - // method gets called, that endpoint has been unregistered. This corresponds - // to the org.bluez.MediaEndpoint1.Release and is renamed to avoid - // a conflict with base::RefCounted<T>. - virtual void Released() = 0; - }; - - virtual ~BluetoothMediaEndpointServiceProvider(); - - // Creates the instance where |bus| is the D-Bus bus connection to export the - // object onto, |object_path| is the object path that it should have and - // |delegate| is the object to which all method calls will be passed and - // responses generated from. - static BluetoothMediaEndpointServiceProvider* Create( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate); - - protected: - BluetoothMediaEndpointServiceProvider(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothMediaEndpointServiceProvider); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/bluetooth_media_transport_client.cc b/chromeos/dbus/bluetooth_media_transport_client.cc deleted file mode 100644 index 3117de2..0000000 --- a/chromeos/dbus/bluetooth_media_transport_client.cc +++ /dev/null
@@ -1,286 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/bluetooth_media_transport_client.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/observer_list.h" -#include "dbus/bus.h" -#include "dbus/message.h" -#include "dbus/object_manager.h" -#include "dbus/object_proxy.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace { - -// TODO(mcchou): Add these service constants into dbus/service_constants.h -// later. -const char kBluetoothMediaTransportInterface[] = "org.bluez.MediaTransport1"; - -// Constants used to indicate exceptional error conditions. -const char kNoResponseError[] = "org.chromium.Error.NoResponse"; -const char kUnexpectedResponse[] = "org.chromium.Error.UnexpectedResponse"; - -// Method names of Media Transport interface. -const char kAcquire[] = "Acquire"; -const char kTryAcquire[] = "TryAcquire"; -const char kRelease[] = "Release"; - -} // namespace - -namespace chromeos { - -// static -const char BluetoothMediaTransportClient::kDeviceProperty[] = "Device"; -const char BluetoothMediaTransportClient::kUUIDProperty[] = "UUID"; -const char BluetoothMediaTransportClient::kCodecProperty[] = "Codec"; -const char BluetoothMediaTransportClient::kConfigurationProperty[] = - "Configuration"; -const char BluetoothMediaTransportClient::kStateProperty[] = "State"; -const char BluetoothMediaTransportClient::kDelayProperty[] = "Delay"; -const char BluetoothMediaTransportClient::kVolumeProperty[] = "Volume"; - -// static -const char BluetoothMediaTransportClient::kStateIdle[] = "idle"; -const char BluetoothMediaTransportClient::kStatePending[] = "pending"; -const char BluetoothMediaTransportClient::kStateActive[] = "active"; - -BluetoothMediaTransportClient::Properties::Properties( - dbus::ObjectProxy* object_proxy, - const std::string& interface_name, - const PropertyChangedCallback& callback) - : dbus::PropertySet(object_proxy, interface_name, callback) { - RegisterProperty(kDeviceProperty, &device); - RegisterProperty(kUUIDProperty, &uuid); - RegisterProperty(kCodecProperty, &codec); - RegisterProperty(kConfigurationProperty, &configuration); - RegisterProperty(kStateProperty, &state); - RegisterProperty(kDelayProperty, &delay); - RegisterProperty(kVolumeProperty, &volume); -} - -BluetoothMediaTransportClient::Properties::~Properties() {} - -class BluetoothMediaTransportClientImpl - : public BluetoothMediaTransportClient, - public dbus::ObjectManager::Interface { - public: - BluetoothMediaTransportClientImpl() - : object_manager_(nullptr), weak_ptr_factory_(this) {} - - ~BluetoothMediaTransportClientImpl() override { - object_manager_->UnregisterInterface(kBluetoothMediaTransportInterface); - } - - // dbus::ObjectManager::Interface overrides. - - dbus::PropertySet* CreateProperties( - dbus::ObjectProxy* object_proxy, - const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - Properties* properties = new Properties( - object_proxy, interface_name, - base::Bind(&BluetoothMediaTransportClientImpl::OnPropertyChanged, - weak_ptr_factory_.GetWeakPtr(), object_path)); - return properties; - } - - void ObjectAdded(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - VLOG(1) << "Remote Media Transport added: " << object_path.value(); - FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, - MediaTransportAdded(object_path)); - } - - void ObjectRemoved(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - VLOG(1) << "Remote Media Transport removed: " << object_path.value(); - FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, - MediaTransportRemoved(object_path)); - } - - // BluetoothMediaTransportClient overrides. - - void AddObserver(BluetoothMediaTransportClient::Observer* observer) override { - DCHECK(observer); - observers_.AddObserver(observer); - } - - void RemoveObserver( - BluetoothMediaTransportClient::Observer* observer) override { - DCHECK(observer); - observers_.RemoveObserver(observer); - } - - Properties* GetProperties(const dbus::ObjectPath& object_path) override { - DCHECK(object_manager_); - return static_cast<Properties*>(object_manager_->GetProperties( - object_path, kBluetoothMediaTransportInterface)); - } - - void Acquire(const dbus::ObjectPath& object_path, - const AcquireCallback& callback, - const ErrorCallback& error_callback) override { - VLOG(1) << "Acquire - transport: " << object_path.value(); - - DCHECK(object_manager_); - - dbus::MethodCall method_call(kBluetoothMediaTransportInterface, kAcquire); - - // Get object proxy. - scoped_refptr<dbus::ObjectProxy> object_proxy( - object_manager_->GetObjectProxy(object_path)); - - // Call Acquire method of Media Transport interface. - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothMediaTransportClientImpl::OnAcquireSuccess, - weak_ptr_factory_.GetWeakPtr(), callback, error_callback), - base::Bind(&BluetoothMediaTransportClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - void TryAcquire(const dbus::ObjectPath& object_path, - const AcquireCallback& callback, - const ErrorCallback& error_callback) override { - VLOG(1) << "TryAcquire - transport: " << object_path.value(); - - DCHECK(object_manager_); - - dbus::MethodCall method_call(kBluetoothMediaTransportInterface, - kTryAcquire); - - // Get object proxy. - scoped_refptr<dbus::ObjectProxy> object_proxy( - object_manager_->GetObjectProxy(object_path)); - - // Call TryAcquire method of Media Transport interface. - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothMediaTransportClientImpl::OnAcquireSuccess, - weak_ptr_factory_.GetWeakPtr(), callback, error_callback), - base::Bind(&BluetoothMediaTransportClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - void Release(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - VLOG(1) << "Release - transport: " << object_path.value(); - - DCHECK(object_manager_); - - dbus::MethodCall method_call(kBluetoothMediaTransportInterface, kRelease); - - // Get object proxy. - scoped_refptr<dbus::ObjectProxy> object_proxy( - object_manager_->GetObjectProxy(object_path)); - - // Call TryAcquire method of Media Transport interface. - object_proxy->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothMediaTransportClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothMediaTransportClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - protected: - void Init(dbus::Bus* bus) override { - DCHECK(bus); - object_manager_ = bus->GetObjectManager( - bluetooth_object_manager::kBluetoothObjectManagerServiceName, - dbus::ObjectPath( - bluetooth_object_manager::kBluetoothObjectManagerServicePath)); - object_manager_->RegisterInterface(kBluetoothMediaTransportInterface, this); - } - - private: - // Called by dbus::PropertySet when a property value is changed. - void OnPropertyChanged(const dbus::ObjectPath& object_path, - const std::string& property_name) { - VLOG(1) << "Name of the changed property: " << property_name; - - // Dispatches the change to the corresponding property-changed handler. - FOR_EACH_OBSERVER( - BluetoothMediaTransportClient::Observer, observers_, - MediaTransportPropertyChanged(object_path, property_name)); - } - - // Called when a response for successful method call is received. - void OnSuccess(const base::Closure& callback, dbus::Response* response) { - DCHECK(response); - callback.Run(); - } - - // Called when a response for |Acquire|/|TryAcquire| method call is received. - void OnAcquireSuccess(const AcquireCallback& callback, - const ErrorCallback& error_callback, - dbus::Response* response) { - DCHECK(response); - - dbus::FileDescriptor fd; - uint16_t read_mtu; - uint16_t write_mtu; - - // Parse the response. - dbus::MessageReader reader(response); - if (reader.PopFileDescriptor(&fd) && reader.PopUint16(&read_mtu) && - reader.PopUint16(&write_mtu)) { - fd.CheckValidity(); - DCHECK(fd.is_valid()); - - VLOG(1) << "OnAcquireSuccess - fd: " << fd.value() - << ", read MTU: " << read_mtu << ", write MTU: " << write_mtu; - - // The ownership of the file descriptor is transferred to the user - // application. - callback.Run(&fd, read_mtu, write_mtu); - return; - } - - error_callback.Run( - kUnexpectedResponse, - "Failed to retrieve file descriptor, read MTU and write MTU."); - } - - // Called when a response for a failed method call is received. - void OnError(const ErrorCallback& error_callback, - dbus::ErrorResponse* response) { - DCHECK(response); - - // Error response has optional error message argument. - std::string error_name; - std::string error_message; - if (response) { - dbus::MessageReader reader(response); - error_name = response->GetErrorName(); - reader.PopString(&error_message); - } else { - error_name = kNoResponseError; - } - error_callback.Run(error_name, error_message); - } - - dbus::ObjectManager* object_manager_; - - // List of observers interested in event notifications from us. - base::ObserverList<BluetoothMediaTransportClient::Observer> observers_; - - base::WeakPtrFactory<BluetoothMediaTransportClientImpl> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothMediaTransportClientImpl); -}; - -BluetoothMediaTransportClient::BluetoothMediaTransportClient() {} - -BluetoothMediaTransportClient::~BluetoothMediaTransportClient() {} - -BluetoothMediaTransportClient* BluetoothMediaTransportClient::Create() { - return new BluetoothMediaTransportClientImpl(); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_media_transport_client.h b/chromeos/dbus/bluetooth_media_transport_client.h deleted file mode 100644 index 4476ae7a..0000000 --- a/chromeos/dbus/bluetooth_media_transport_client.h +++ /dev/null
@@ -1,142 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_ -#define CHROMEOS_DBUS_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_ - -#include <string> -#include <vector> - -#include "base/callback.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/dbus_client.h" -#include "dbus/file_descriptor.h" -#include "dbus/object_path.h" -#include "dbus/property.h" - -namespace chromeos { - -class CHROMEOS_EXPORT BluetoothMediaTransportClient : public DBusClient { - public: - struct Properties : public dbus::PropertySet { - // The path to the device object which the transport is connected to. - // Read-only. - dbus::Property<dbus::ObjectPath> device; - - // UUID of the profile which the transport is for. Read-only. - dbus::Property<std::string> uuid; - - // Assigned codec value supported by the media transport. Read-only. - dbus::Property<uint8_t> codec; - - // The configuration used by the media transport. Read-only. - dbus::Property<std::vector<uint8_t>> configuration; - - // The state of the transport. Read-only. - // The values can be one of the following: - // "idle": not streaming - // "pending": streaming but not acquired - // "active": streaming and acquired - dbus::Property<std::string> state; - - // The unit of transport delay is in 1/10 of millisecond. This property is - // only writeable when the transport was aquired by the sender. Optional. - dbus::Property<uint16_t> delay; - - // The volume level of the transport. This property is only writable when - // the transport was aquired by the sender. Optional. - dbus::Property<uint16_t> volume; - - Properties(dbus::ObjectProxy* object_proxy, - const std::string& interface_name, - const PropertyChangedCallback& callback); - ~Properties() override; - }; - - class Observer { - public: - virtual ~Observer() {} - - // Called when the Media Transport with object path |object_path| is added - // to the system. - virtual void MediaTransportAdded(const dbus::ObjectPath& object_path) {} - - // Called when the Media Transport with object path |object_path| is removed - // from the system. - virtual void MediaTransportRemoved(const dbus::ObjectPath& object_path) {} - - // Called when the Media Transport with object path |object_path| has - // a change in the value of the property with name |property_name|. - virtual void MediaTransportPropertyChanged( - const dbus::ObjectPath& object_path, - const std::string& property_name) {} - }; - - // TODO(mcchou): Move all static constants to service_constants.h. - // Constants used for the names of Media Transport's properties. - static const char kDeviceProperty[]; - static const char kUUIDProperty[]; - static const char kCodecProperty[]; - static const char kConfigurationProperty[]; - static const char kStateProperty[]; - static const char kDelayProperty[]; - static const char kVolumeProperty[]; - - // All possible states of a valid media transport object. - static const char kStateIdle[]; - static const char kStatePending[]; - static const char kStateActive[]; - - ~BluetoothMediaTransportClient() override; - - // The ErrorCallback is used by media transport API methods to indicate - // failure. It receives two arguments: the name of the error in |error_name| - // and an optional message in |error_message|. - typedef base::Callback<void(const std::string& error_name, - const std::string& error_message)> ErrorCallback; - - // The AcquireCallback is used by |Acquire| method of media tansport API tp - // indicate the success of the method. - typedef base::Callback<void(dbus::FileDescriptor* fd, - const uint16_t read_mtu, - const uint16_t write_mtu)> AcquireCallback; - - // Adds and removes observers for events on all remote Media Transports. Check - // the |object_path| parameter of observer methods to determine which Media - // Transport is issuing the event. - virtual void AddObserver(Observer* observer) = 0; - virtual void RemoveObserver(Observer* observer) = 0; - - virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; - - // Acquires transport file descriptor and the MTU for read and write. - virtual void Acquire(const dbus::ObjectPath& object_path, - const AcquireCallback& callback, - const ErrorCallback& error_callback) = 0; - - // Acquires transport file descriptor only if the transport is in "pending" - // state at the time the message is received by BlueZ. Otherwise no request - // will be sent to the remote device and the function will just fail with - // org.bluez.Error.NotAvailable. - virtual void TryAcquire(const dbus::ObjectPath& object_path, - const AcquireCallback& callback, - const ErrorCallback& error_callback) = 0; - - // Releases the file descriptor of the transport. - virtual void Release(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - static BluetoothMediaTransportClient* Create(); - - protected: - BluetoothMediaTransportClient(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothMediaTransportClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_profile_manager_client.cc b/chromeos/dbus/bluetooth_profile_manager_client.cc deleted file mode 100644 index 01301d4d..0000000 --- a/chromeos/dbus/bluetooth_profile_manager_client.cc +++ /dev/null
@@ -1,234 +0,0 @@ -// Copyright 2013 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 "chromeos/dbus/bluetooth_profile_manager_client.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "dbus/bus.h" -#include "dbus/message.h" -#include "dbus/object_proxy.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -const char BluetoothProfileManagerClient::kNoResponseError[] = - "org.chromium.Error.NoResponse"; - -BluetoothProfileManagerClient::Options::Options() {} - -BluetoothProfileManagerClient::Options::~Options() {} - -// The BluetoothProfileManagerClient implementation used in production. -class BluetoothProfileManagerClientImpl : public BluetoothProfileManagerClient { - public: - BluetoothProfileManagerClientImpl() : weak_ptr_factory_(this) {} - - ~BluetoothProfileManagerClientImpl() override {} - - // BluetoothProfileManagerClient override. - void RegisterProfile(const dbus::ObjectPath& profile_path, - const std::string& uuid, - const Options& options, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call( - bluetooth_profile_manager::kBluetoothProfileManagerInterface, - bluetooth_profile_manager::kRegisterProfile); - - dbus::MessageWriter writer(&method_call); - writer.AppendObjectPath(profile_path); - writer.AppendString(uuid); - - dbus::MessageWriter array_writer(NULL); - writer.OpenArray("{sv}", &array_writer); - - dbus::MessageWriter dict_writer(NULL); - - // Send Name if provided. - if (options.name.get() != NULL) { - array_writer.OpenDictEntry(&dict_writer); - dict_writer.AppendString(bluetooth_profile_manager::kNameOption); - dict_writer.AppendVariantOfString(*(options.name)); - array_writer.CloseContainer(&dict_writer); - } - - // Send Service if provided. - if (options.service.get() != NULL) { - dbus::MessageWriter dict_writer(NULL); - array_writer.OpenDictEntry(&dict_writer); - dict_writer.AppendString(bluetooth_profile_manager::kServiceOption); - dict_writer.AppendVariantOfString(*(options.service)); - array_writer.CloseContainer(&dict_writer); - } - - // Send Role if not the default value. - if (options.role != SYMMETRIC) { - dbus::MessageWriter dict_writer(NULL); - array_writer.OpenDictEntry(&dict_writer); - dict_writer.AppendString(bluetooth_profile_manager::kRoleOption); - if (options.role == CLIENT) - dict_writer.AppendVariantOfString( - bluetooth_profile_manager::kClientRoleOption); - else if (options.role == SERVER) - dict_writer.AppendVariantOfString( - bluetooth_profile_manager::kServerRoleOption); - else - dict_writer.AppendVariantOfString(""); - array_writer.CloseContainer(&dict_writer); - } - - // Send Channel if provided. - if (options.channel.get() != NULL) { - dbus::MessageWriter dict_writer(NULL); - array_writer.OpenDictEntry(&dict_writer); - dict_writer.AppendString(bluetooth_profile_manager::kChannelOption); - dict_writer.AppendVariantOfUint16(*(options.channel)); - array_writer.CloseContainer(&dict_writer); - } - - // Send PSM if provided. - if (options.psm.get() != NULL) { - dbus::MessageWriter dict_writer(NULL); - array_writer.OpenDictEntry(&dict_writer); - dict_writer.AppendString(bluetooth_profile_manager::kPSMOption); - dict_writer.AppendVariantOfUint16(*(options.psm)); - array_writer.CloseContainer(&dict_writer); - } - - // Send RequireAuthentication if provided. - if (options.require_authentication.get() != NULL) { - array_writer.OpenDictEntry(&dict_writer); - dict_writer.AppendString( - bluetooth_profile_manager::kRequireAuthenticationOption); - dict_writer.AppendVariantOfBool(*(options.require_authentication)); - array_writer.CloseContainer(&dict_writer); - } - - // Send RequireAuthorization if provided. - if (options.require_authorization.get() != NULL) { - array_writer.OpenDictEntry(&dict_writer); - dict_writer.AppendString( - bluetooth_profile_manager::kRequireAuthorizationOption); - dict_writer.AppendVariantOfBool(*(options.require_authorization)); - array_writer.CloseContainer(&dict_writer); - } - - // Send AutoConnect if provided. - if (options.auto_connect.get() != NULL) { - array_writer.OpenDictEntry(&dict_writer); - dict_writer.AppendString(bluetooth_profile_manager::kAutoConnectOption); - dict_writer.AppendVariantOfBool(*(options.auto_connect)); - array_writer.CloseContainer(&dict_writer); - } - - // Send ServiceRecord if provided. - if (options.service_record.get() != NULL) { - dbus::MessageWriter dict_writer(NULL); - array_writer.OpenDictEntry(&dict_writer); - dict_writer.AppendString(bluetooth_profile_manager::kServiceRecordOption); - dict_writer.AppendVariantOfString(*(options.service_record)); - array_writer.CloseContainer(&dict_writer); - } - - // Send Version if provided. - if (options.version.get() != NULL) { - dbus::MessageWriter dict_writer(NULL); - array_writer.OpenDictEntry(&dict_writer); - dict_writer.AppendString(bluetooth_profile_manager::kVersionOption); - dict_writer.AppendVariantOfUint16(*(options.version)); - array_writer.CloseContainer(&dict_writer); - } - - // Send Features if provided. - if (options.features.get() != NULL) { - dbus::MessageWriter dict_writer(NULL); - array_writer.OpenDictEntry(&dict_writer); - dict_writer.AppendString(bluetooth_profile_manager::kFeaturesOption); - dict_writer.AppendVariantOfUint16(*(options.features)); - array_writer.CloseContainer(&dict_writer); - } - - writer.CloseContainer(&array_writer); - - object_proxy_->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothProfileManagerClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothProfileManagerClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - // BluetoothProfileManagerClient override. - void UnregisterProfile(const dbus::ObjectPath& profile_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override { - dbus::MethodCall method_call( - bluetooth_profile_manager::kBluetoothProfileManagerInterface, - bluetooth_profile_manager::kUnregisterProfile); - - dbus::MessageWriter writer(&method_call); - writer.AppendObjectPath(profile_path); - - object_proxy_->CallMethodWithErrorCallback( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&BluetoothProfileManagerClientImpl::OnSuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothProfileManagerClientImpl::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); - } - - protected: - void Init(dbus::Bus* bus) override { - DCHECK(bus); - object_proxy_ = bus->GetObjectProxy( - bluetooth_profile_manager::kBluetoothProfileManagerServiceName, - dbus::ObjectPath( - bluetooth_profile_manager::kBluetoothProfileManagerServicePath)); - } - - private: - // Called when a response for successful method call is received. - void OnSuccess(const base::Closure& callback, dbus::Response* response) { - DCHECK(response); - callback.Run(); - } - - // Called when a response for a failed method call is received. - void OnError(const ErrorCallback& error_callback, - dbus::ErrorResponse* response) { - // Error response has optional error message argument. - std::string error_name; - std::string error_message; - if (response) { - dbus::MessageReader reader(response); - error_name = response->GetErrorName(); - reader.PopString(&error_message); - } else { - error_name = kNoResponseError; - error_message = ""; - } - error_callback.Run(error_name, error_message); - } - - dbus::ObjectProxy* object_proxy_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<BluetoothProfileManagerClientImpl> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothProfileManagerClientImpl); -}; - -BluetoothProfileManagerClient::BluetoothProfileManagerClient() {} - -BluetoothProfileManagerClient::~BluetoothProfileManagerClient() {} - -BluetoothProfileManagerClient* BluetoothProfileManagerClient::Create() { - return new BluetoothProfileManagerClientImpl(); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_profile_manager_client.h b/chromeos/dbus/bluetooth_profile_manager_client.h deleted file mode 100644 index 8f53412..0000000 --- a/chromeos/dbus/bluetooth_profile_manager_client.h +++ /dev/null
@@ -1,107 +0,0 @@ -// Copyright 2013 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 CHROMEOS_DBUS_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_ -#define CHROMEOS_DBUS_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_ - -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "base/values.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/dbus_client.h" -#include "dbus/object_path.h" - -namespace chromeos { - -// BluetoothProfileManagerClient is used to communicate with the profile -// manager object of the Bluetooth daemon. -class CHROMEOS_EXPORT BluetoothProfileManagerClient : public DBusClient { - public: - // Species the role of the object within the profile. SYMMETRIC should be - // usually used unless the profile requires you specify as a CLIENT or as a - // SERVER. - enum ProfileRole { SYMMETRIC, CLIENT, SERVER }; - - // Options used to register a Profile object. - struct CHROMEOS_EXPORT Options { - Options(); - ~Options(); - - // Human readable name for the profile. - scoped_ptr<std::string> name; - - // Primary service class UUID (if different from the actual UUID) - scoped_ptr<std::string> service; - - // Role. - enum ProfileRole role; - - // RFCOMM channel number. - scoped_ptr<uint16> channel; - - // PSM number. - scoped_ptr<uint16> psm; - - // Pairing is required before connections will be established. - scoped_ptr<bool> require_authentication; - - // Request authorization before connections will be established. - scoped_ptr<bool> require_authorization; - - // Force connections when a remote device is connected. - scoped_ptr<bool> auto_connect; - - // Manual SDP record. - scoped_ptr<std::string> service_record; - - // Profile version. - scoped_ptr<uint16> version; - - // Profile features. - scoped_ptr<uint16> features; - }; - - ~BluetoothProfileManagerClient() override; - - // The ErrorCallback is used by adapter methods to indicate failure. - // It receives two arguments: the name of the error in |error_name| and - // an optional message in |error_message|. - typedef base::Callback<void(const std::string& error_name, - const std::string& error_message)> ErrorCallback; - - // Registers a profile implementation within the local process at the - // D-bus object path |profile_path| with the remote profile manager. - // |uuid| specifies the identifier of the profile and |options| the way in - // which the profile is implemented. - virtual void RegisterProfile(const dbus::ObjectPath& profile_path, - const std::string& uuid, - const Options& options, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Unregisters the profile with the D-Bus object path |agent_path| from the - // remote profile manager. - virtual void UnregisterProfile(const dbus::ObjectPath& profile_path, - const base::Closure& callback, - const ErrorCallback& error_callback) = 0; - - // Creates the instance. - static BluetoothProfileManagerClient* Create(); - - // Constants used to indicate exceptional error conditions. - static const char kNoResponseError[]; - - protected: - BluetoothProfileManagerClient(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothProfileManagerClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_profile_service_provider.cc b/chromeos/dbus/bluetooth_profile_service_provider.cc deleted file mode 100644 index f63f5eab..0000000 --- a/chromeos/dbus/bluetooth_profile_service_provider.cc +++ /dev/null
@@ -1,248 +0,0 @@ -// Copyright 2013 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 "chromeos/dbus/bluetooth_profile_service_provider.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/threading/platform_thread.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_profile_service_provider.h" -#include "dbus/exported_object.h" -#include "dbus/message.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -// The BluetoothProfileServiceProvider implementation used in production. -class BluetoothProfileServiceProviderImpl - : public BluetoothProfileServiceProvider { - public: - BluetoothProfileServiceProviderImpl(dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate) - : origin_thread_id_(base::PlatformThread::CurrentId()), - bus_(bus), - delegate_(delegate), - object_path_(object_path), - weak_ptr_factory_(this) { - VLOG(1) << "Creating Bluetooth Profile: " << object_path_.value(); - - exported_object_ = bus_->GetExportedObject(object_path_); - - exported_object_->ExportMethod( - bluetooth_profile::kBluetoothProfileInterface, - bluetooth_profile::kRelease, - base::Bind(&BluetoothProfileServiceProviderImpl::Release, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothProfileServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - bluetooth_profile::kBluetoothProfileInterface, - bluetooth_profile::kNewConnection, - base::Bind(&BluetoothProfileServiceProviderImpl::NewConnection, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothProfileServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - bluetooth_profile::kBluetoothProfileInterface, - bluetooth_profile::kRequestDisconnection, - base::Bind(&BluetoothProfileServiceProviderImpl::RequestDisconnection, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothProfileServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - - exported_object_->ExportMethod( - bluetooth_profile::kBluetoothProfileInterface, - bluetooth_profile::kCancel, - base::Bind(&BluetoothProfileServiceProviderImpl::Cancel, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothProfileServiceProviderImpl::OnExported, - weak_ptr_factory_.GetWeakPtr())); - } - - ~BluetoothProfileServiceProviderImpl() override { - VLOG(1) << "Cleaning up Bluetooth Profile: " << object_path_.value(); - - // Unregister the object path so we can reuse with a new agent. - bus_->UnregisterExportedObject(object_path_); - } - - private: - // Returns true if the current thread is on the origin thread. - bool OnOriginThread() { - return base::PlatformThread::CurrentId() == origin_thread_id_; - } - - // Called by dbus:: when the profile is unregistered from the Bluetooth - // daemon, generally by our request. - void Release(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - delegate_->Released(); - - response_sender.Run(dbus::Response::FromMethodCall(method_call)); - } - - // Called by dbus:: when the Bluetooth daemon establishes a new connection - // to the profile. - void NewConnection(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - dbus::MessageReader reader(method_call); - dbus::ObjectPath device_path; - scoped_ptr<dbus::FileDescriptor> fd(new dbus::FileDescriptor()); - dbus::MessageReader array_reader(NULL); - if (!reader.PopObjectPath(&device_path) || - !reader.PopFileDescriptor(fd.get()) || - !reader.PopArray(&array_reader)) { - LOG(WARNING) << "NewConnection called with incorrect paramters: " - << method_call->ToString(); - return; - } - - Delegate::Options options; - while (array_reader.HasMoreData()) { - dbus::MessageReader dict_entry_reader(NULL); - std::string key; - if (!array_reader.PopDictEntry(&dict_entry_reader) || - !dict_entry_reader.PopString(&key)) { - LOG(WARNING) << "NewConnection called with incorrect paramters: " - << method_call->ToString(); - } else { - if (key == bluetooth_profile::kVersionProperty) - dict_entry_reader.PopVariantOfUint16(&options.version); - else if (key == bluetooth_profile::kFeaturesProperty) - dict_entry_reader.PopVariantOfUint16(&options.features); - } - } - - Delegate::ConfirmationCallback callback = base::Bind( - &BluetoothProfileServiceProviderImpl::OnConfirmation, - weak_ptr_factory_.GetWeakPtr(), method_call, response_sender); - - delegate_->NewConnection(device_path, fd.Pass(), options, callback); - } - - // Called by dbus:: when the Bluetooth daemon is about to disconnect the - // profile. - void RequestDisconnection( - dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - dbus::MessageReader reader(method_call); - dbus::ObjectPath device_path; - if (!reader.PopObjectPath(&device_path)) { - LOG(WARNING) << "RequestDisconnection called with incorrect paramters: " - << method_call->ToString(); - return; - } - - Delegate::ConfirmationCallback callback = base::Bind( - &BluetoothProfileServiceProviderImpl::OnConfirmation, - weak_ptr_factory_.GetWeakPtr(), method_call, response_sender); - - delegate_->RequestDisconnection(device_path, callback); - } - - // Called by dbus:: when the request failed before a reply was returned - // from the device. - void Cancel(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - DCHECK(OnOriginThread()); - DCHECK(delegate_); - - delegate_->Cancel(); - - response_sender.Run(dbus::Response::FromMethodCall(method_call)); - } - - // Called by dbus:: when a method is exported. - void OnExported(const std::string& interface_name, - const std::string& method_name, - bool success) { - LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "." - << method_name; - } - - // Called by the Delegate in response to a method requiring confirmation. - void OnConfirmation(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender, - Delegate::Status status) { - DCHECK(OnOriginThread()); - - switch (status) { - case Delegate::SUCCESS: { - response_sender.Run(dbus::Response::FromMethodCall(method_call)); - break; - } - case Delegate::REJECTED: { - response_sender.Run(dbus::ErrorResponse::FromMethodCall( - method_call, bluetooth_profile::kErrorRejected, "rejected")); - break; - } - case Delegate::CANCELLED: { - response_sender.Run(dbus::ErrorResponse::FromMethodCall( - method_call, bluetooth_profile::kErrorCanceled, "canceled")); - break; - } - default: - NOTREACHED() << "Unexpected status code from delegate: " << status; - } - } - - // Origin thread (i.e. the UI thread in production). - base::PlatformThreadId origin_thread_id_; - - // D-Bus bus object is exported on, not owned by this object and must - // outlive it. - dbus::Bus* bus_; - - // All incoming method calls are passed on to the Delegate and a callback - // passed to generate the reply. |delegate_| is generally the object that - // owns this one, and must outlive it. - Delegate* delegate_; - - // D-Bus object path of object we are exporting, kept so we can unregister - // again in our destructor. - dbus::ObjectPath object_path_; - - // D-Bus object we are exporting, owned by this object. - scoped_refptr<dbus::ExportedObject> exported_object_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<BluetoothProfileServiceProviderImpl> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothProfileServiceProviderImpl); -}; - -BluetoothProfileServiceProvider::BluetoothProfileServiceProvider() {} - -BluetoothProfileServiceProvider::~BluetoothProfileServiceProvider() {} - -// static -BluetoothProfileServiceProvider* BluetoothProfileServiceProvider::Create( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate) { - if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) { - return new BluetoothProfileServiceProviderImpl(bus, object_path, delegate); - } else { - return new FakeBluetoothProfileServiceProvider(object_path, delegate); - } -} - -} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_profile_service_provider.h b/chromeos/dbus/bluetooth_profile_service_provider.h deleted file mode 100644 index 366a354c..0000000 --- a/chromeos/dbus/bluetooth_profile_service_provider.h +++ /dev/null
@@ -1,120 +0,0 @@ -// Copyright 2013 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 CHROMEOS_DBUS_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_ -#define CHROMEOS_DBUS_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_ - -#include <string> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "chromeos/chromeos_export.h" -#include "dbus/bus.h" -#include "dbus/file_descriptor.h" -#include "dbus/object_path.h" - -namespace chromeos { - -// BluetoothProfileServiceProvider is used to provide a D-Bus object that the -// Bluetooth daemon can communicate with to connect application profiles. -// -// Instantiate with a chosen D-Bus object path and delegate object, and pass -// the D-Bus object path as the |agent_path| argument to the -// chromeos::BluetoothProfileManagerClient::RegisterProfile() method. -// -// When an incoming profile connection occurs, or after initiating a connection -// using the chromeos::BluetoothDeviceClient::ConnectProfile() method, the -// Bluetooth daemon will make calls to this profile object and they will be -// passed on to your Delegate object for handling. Responses should be returned -// using the callbacks supplied to those methods. -class CHROMEOS_EXPORT BluetoothProfileServiceProvider { - public: - // Interface for reacting to profile requests. - class Delegate { - public: - virtual ~Delegate() {} - - // Possible status values that may be returned to callbacks on a new - // connection or a requested disconnection. Success indicates acceptance, - // reject indicates the user rejected or denied the request; cancelled - // means the user cancelled the request without confirming either way. - enum Status { SUCCESS, REJECTED, CANCELLED }; - - // Connection-specific options. - struct CHROMEOS_EXPORT Options { - Options() {} - ~Options() {} - - // Profile version. - uint16 version; - - // Profile features. - uint16 features; - }; - - // The ConfirmationCallback is used for methods which require confirmation; - // it should be called with one argument, the |status| of the request - // (success, rejected or cancelled). - typedef base::Callback<void(Status)> ConfirmationCallback; - - // This method will be called when the profile is unregistered from the - // Bluetooth daemon, generally at shutdown or at the applications' request. - // It may be used to perform cleanup tasks. This corresponds to the - // org.bluez.Profile1.Release method and is renamed to avoid a conflict - // with base::Refcounted<T>. - virtual void Released() = 0; - - // This method will be called when a profile connection to the device - // with object path |device_path| is established. |callback| must be called - // to confirm the connection, or indicate rejection or cancellation. - // - // A file descriptor for the connection socket is provided in |fd|, and - // details about the specific implementation of the profile in |options|. - // - // IMPORTANT: Ownership of the file descriptor object |fd| is passed to - // the delegate by this call. The delegate is responsible for checking the - // validity of |fd| on a thread where I/O is permitted before taking the - // value. If the value is not taken, the file descriptor is closed. - // - // Ownership of |options| is NOT passed so information out of it must be - // copied if required. - virtual void NewConnection(const dbus::ObjectPath& device_path, - scoped_ptr<dbus::FileDescriptor> fd, - const Options& options, - const ConfirmationCallback& callback) = 0; - - // This method will be called when a profile connection to the device - // with object path |device_path| is disconnected. Any file descriptors - // owned by the service should be cleaned up and |callback| called to - // confirm, or indicate rejection or cancellation of the disconnection. - virtual void RequestDisconnection(const dbus::ObjectPath& device_path, - const ConfirmationCallback& callback) = 0; - - // This method will be called by the Bluetooth daemon to indicate that - // a profile request failed before a reply was returned from the device. - virtual void Cancel() = 0; - }; - - virtual ~BluetoothProfileServiceProvider(); - - // Creates the instance where |bus| is the D-Bus bus connection to export - // the object onto, |object_path| is the object path that it should have - // and |delegate| is the object to which all method calls will be passed - // and responses generated from. - static BluetoothProfileServiceProvider* Create( - dbus::Bus* bus, - const dbus::ObjectPath& object_path, - Delegate* delegate); - - protected: - BluetoothProfileServiceProvider(); - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothProfileServiceProvider); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/dbus_client_bundle.cc b/chromeos/dbus/dbus_client_bundle.cc index 941bec6..0397ff6 100644 --- a/chromeos/dbus/dbus_client_bundle.cc +++ b/chromeos/dbus/dbus_client_bundle.cc
@@ -14,18 +14,6 @@ #include "chromeos/dbus/ap_manager_client.h" #include "chromeos/dbus/arc_bridge_client.h" #include "chromeos/dbus/audio_dsp_client.h" -#include "chromeos/dbus/bluetooth_adapter_client.h" -#include "chromeos/dbus/bluetooth_agent_manager_client.h" -#include "chromeos/dbus/bluetooth_device_client.h" -#include "chromeos/dbus/bluetooth_gatt_characteristic_client.h" -#include "chromeos/dbus/bluetooth_gatt_descriptor_client.h" -#include "chromeos/dbus/bluetooth_gatt_manager_client.h" -#include "chromeos/dbus/bluetooth_gatt_service_client.h" -#include "chromeos/dbus/bluetooth_input_client.h" -#include "chromeos/dbus/bluetooth_le_advertising_manager_client.h" -#include "chromeos/dbus/bluetooth_media_client.h" -#include "chromeos/dbus/bluetooth_media_transport_client.h" -#include "chromeos/dbus/bluetooth_profile_manager_client.h" #include "chromeos/dbus/cras_audio_client.h" #include "chromeos/dbus/cros_disks_client.h" #include "chromeos/dbus/cryptohome_client.h" @@ -35,18 +23,6 @@ #include "chromeos/dbus/fake_ap_manager_client.h" #include "chromeos/dbus/fake_arc_bridge_client.h" #include "chromeos/dbus/fake_audio_dsp_client.h" -#include "chromeos/dbus/fake_bluetooth_adapter_client.h" -#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" -#include "chromeos/dbus/fake_bluetooth_device_client.h" -#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h" -#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h" -#include "chromeos/dbus/fake_bluetooth_gatt_manager_client.h" -#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h" -#include "chromeos/dbus/fake_bluetooth_input_client.h" -#include "chromeos/dbus/fake_bluetooth_le_advertising_manager_client.h" -#include "chromeos/dbus/fake_bluetooth_media_client.h" -#include "chromeos/dbus/fake_bluetooth_media_transport_client.h" -#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h" #include "chromeos/dbus/fake_cras_audio_client.h" #include "chromeos/dbus/fake_cryptohome_client.h" #include "chromeos/dbus/fake_debug_daemon_client.h" @@ -165,45 +141,6 @@ else audio_dsp_client_.reset(new FakeAudioDspClient); - if (!IsUsingStub(BLUETOOTH)) { - bluetooth_adapter_client_.reset(BluetoothAdapterClient::Create()); - bluetooth_le_advertising_manager_client_.reset( - BluetoothLEAdvertisingManagerClient::Create()); - bluetooth_agent_manager_client_.reset( - BluetoothAgentManagerClient::Create()); - bluetooth_device_client_.reset(BluetoothDeviceClient::Create()); - bluetooth_input_client_.reset(BluetoothInputClient::Create()); - bluetooth_media_client_.reset(BluetoothMediaClient::Create()); - bluetooth_media_transport_client_.reset( - BluetoothMediaTransportClient::Create()); - bluetooth_profile_manager_client_.reset( - BluetoothProfileManagerClient::Create()); - bluetooth_gatt_characteristic_client_.reset( - BluetoothGattCharacteristicClient::Create()); - bluetooth_gatt_descriptor_client_.reset( - BluetoothGattDescriptorClient::Create()); - bluetooth_gatt_manager_client_.reset(BluetoothGattManagerClient::Create()); - bluetooth_gatt_service_client_.reset(BluetoothGattServiceClient::Create()); - } else { - bluetooth_adapter_client_.reset(new FakeBluetoothAdapterClient); - bluetooth_le_advertising_manager_client_.reset( - new FakeBluetoothLEAdvertisingManagerClient); - bluetooth_agent_manager_client_.reset(new FakeBluetoothAgentManagerClient); - bluetooth_device_client_.reset(new FakeBluetoothDeviceClient); - bluetooth_input_client_.reset(new FakeBluetoothInputClient); - bluetooth_media_client_.reset(new FakeBluetoothMediaClient); - bluetooth_media_transport_client_.reset( - new FakeBluetoothMediaTransportClient); - bluetooth_profile_manager_client_.reset( - new FakeBluetoothProfileManagerClient); - bluetooth_gatt_characteristic_client_.reset( - new FakeBluetoothGattCharacteristicClient); - bluetooth_gatt_descriptor_client_.reset( - new FakeBluetoothGattDescriptorClient); - bluetooth_gatt_manager_client_.reset(new FakeBluetoothGattManagerClient); - bluetooth_gatt_service_client_.reset(new FakeBluetoothGattServiceClient); - } - if (!IsUsingStub(CRAS)) cras_audio_client_.reset(CrasAudioClient::Create()); else
diff --git a/chromeos/dbus/dbus_client_bundle.h b/chromeos/dbus/dbus_client_bundle.h index 536eb4d..2fd9e58 100644 --- a/chromeos/dbus/dbus_client_bundle.h +++ b/chromeos/dbus/dbus_client_bundle.h
@@ -16,18 +16,6 @@ class ApManagerClient; class ArcBridgeClient; class AudioDspClient; -class BluetoothAdapterClient; -class BluetoothAgentManagerClient; -class BluetoothDeviceClient; -class BluetoothGattCharacteristicClient; -class BluetoothGattDescriptorClient; -class BluetoothGattManagerClient; -class BluetoothGattServiceClient; -class BluetoothInputClient; -class BluetoothLEAdvertisingManagerClient; -class BluetoothMediaClient; -class BluetoothMediaTransportClient; -class BluetoothProfileManagerClient; class CrasAudioClient; class CrosDisksClient; class CryptohomeClient; @@ -120,55 +108,6 @@ AudioDspClient* audio_dsp_client() { return audio_dsp_client_.get(); } - BluetoothAdapterClient* bluetooth_adapter_client() { - return bluetooth_adapter_client_.get(); - } - - BluetoothLEAdvertisingManagerClient* - bluetooth_le_advertising_manager_client() { - return bluetooth_le_advertising_manager_client_.get(); - } - - BluetoothAgentManagerClient* bluetooth_agent_manager_client() { - return bluetooth_agent_manager_client_.get(); - } - - BluetoothDeviceClient* bluetooth_device_client() { - return bluetooth_device_client_.get(); - } - - BluetoothGattCharacteristicClient* bluetooth_gatt_characteristic_client() { - return bluetooth_gatt_characteristic_client_.get(); - } - - BluetoothGattDescriptorClient* bluetooth_gatt_descriptor_client() { - return bluetooth_gatt_descriptor_client_.get(); - } - - BluetoothGattManagerClient* bluetooth_gatt_manager_client() { - return bluetooth_gatt_manager_client_.get(); - } - - BluetoothGattServiceClient* bluetooth_gatt_service_client() { - return bluetooth_gatt_service_client_.get(); - } - - BluetoothInputClient* bluetooth_input_client() { - return bluetooth_input_client_.get(); - } - - BluetoothMediaClient* bluetooth_media_client() { - return bluetooth_media_client_.get(); - } - - BluetoothMediaTransportClient* bluetooth_media_transport_client() { - return bluetooth_media_transport_client_.get(); - } - - BluetoothProfileManagerClient* bluetooth_profile_manager_client() { - return bluetooth_profile_manager_client_.get(); - } - CrasAudioClient* cras_audio_client() { return cras_audio_client_.get(); } @@ -296,20 +235,6 @@ scoped_ptr<ApManagerClient> ap_manager_client_; scoped_ptr<ArcBridgeClient> arc_bridge_client_; scoped_ptr<AudioDspClient> audio_dsp_client_; - scoped_ptr<BluetoothAdapterClient> bluetooth_adapter_client_; - scoped_ptr<BluetoothLEAdvertisingManagerClient> - bluetooth_le_advertising_manager_client_; - scoped_ptr<BluetoothAgentManagerClient> bluetooth_agent_manager_client_; - scoped_ptr<BluetoothDeviceClient> bluetooth_device_client_; - scoped_ptr<BluetoothGattCharacteristicClient> - bluetooth_gatt_characteristic_client_; - scoped_ptr<BluetoothGattDescriptorClient> bluetooth_gatt_descriptor_client_; - scoped_ptr<BluetoothGattManagerClient> bluetooth_gatt_manager_client_; - scoped_ptr<BluetoothGattServiceClient> bluetooth_gatt_service_client_; - scoped_ptr<BluetoothInputClient> bluetooth_input_client_; - scoped_ptr<BluetoothMediaClient> bluetooth_media_client_; - scoped_ptr<BluetoothMediaTransportClient> bluetooth_media_transport_client_; - scoped_ptr<BluetoothProfileManagerClient> bluetooth_profile_manager_client_; scoped_ptr<CrasAudioClient> cras_audio_client_; scoped_ptr<CrosDisksClient> cros_disks_client_; scoped_ptr<CryptohomeClient> cryptohome_client_;
diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc index af03c1f..ab8db4f 100644 --- a/chromeos/dbus/dbus_thread_manager.cc +++ b/chromeos/dbus/dbus_thread_manager.cc
@@ -12,18 +12,6 @@ #include "chromeos/dbus/ap_manager_client.h" #include "chromeos/dbus/arc_bridge_client.h" #include "chromeos/dbus/audio_dsp_client.h" -#include "chromeos/dbus/bluetooth_adapter_client.h" -#include "chromeos/dbus/bluetooth_agent_manager_client.h" -#include "chromeos/dbus/bluetooth_device_client.h" -#include "chromeos/dbus/bluetooth_gatt_characteristic_client.h" -#include "chromeos/dbus/bluetooth_gatt_descriptor_client.h" -#include "chromeos/dbus/bluetooth_gatt_manager_client.h" -#include "chromeos/dbus/bluetooth_gatt_service_client.h" -#include "chromeos/dbus/bluetooth_input_client.h" -#include "chromeos/dbus/bluetooth_le_advertising_manager_client.h" -#include "chromeos/dbus/bluetooth_media_client.h" -#include "chromeos/dbus/bluetooth_media_transport_client.h" -#include "chromeos/dbus/bluetooth_profile_manager_client.h" #include "chromeos/dbus/cras_audio_client.h" #include "chromeos/dbus/cros_disks_client.h" #include "chromeos/dbus/cryptohome_client.h" @@ -132,60 +120,6 @@ return client_bundle_->audio_dsp_client(); } -BluetoothAdapterClient* DBusThreadManager::GetBluetoothAdapterClient() { - return client_bundle_->bluetooth_adapter_client(); -} - -BluetoothLEAdvertisingManagerClient* -DBusThreadManager::GetBluetoothLEAdvertisingManagerClient() { - return client_bundle_->bluetooth_le_advertising_manager_client(); -} - -BluetoothAgentManagerClient* -DBusThreadManager::GetBluetoothAgentManagerClient() { - return client_bundle_->bluetooth_agent_manager_client(); -} - -BluetoothDeviceClient* DBusThreadManager::GetBluetoothDeviceClient() { - return client_bundle_->bluetooth_device_client(); -} - -BluetoothGattCharacteristicClient* -DBusThreadManager::GetBluetoothGattCharacteristicClient() { - return client_bundle_->bluetooth_gatt_characteristic_client(); -} - -BluetoothGattDescriptorClient* -DBusThreadManager::GetBluetoothGattDescriptorClient() { - return client_bundle_->bluetooth_gatt_descriptor_client(); -} - -BluetoothGattManagerClient* DBusThreadManager::GetBluetoothGattManagerClient() { - return client_bundle_->bluetooth_gatt_manager_client(); -} - -BluetoothGattServiceClient* DBusThreadManager::GetBluetoothGattServiceClient() { - return client_bundle_->bluetooth_gatt_service_client(); -} - -BluetoothInputClient* DBusThreadManager::GetBluetoothInputClient() { - return client_bundle_->bluetooth_input_client(); -} - -BluetoothMediaClient* DBusThreadManager::GetBluetoothMediaClient() { - return client_bundle_->bluetooth_media_client(); -} - -BluetoothMediaTransportClient* -DBusThreadManager::GetBluetoothMediaTransportClient() { - return client_bundle_->bluetooth_media_transport_client(); -} - -BluetoothProfileManagerClient* -DBusThreadManager::GetBluetoothProfileManagerClient() { - return client_bundle_->bluetooth_profile_manager_client(); -} - CrasAudioClient* DBusThreadManager::GetCrasAudioClient() { return client_bundle_->cras_audio_client(); } @@ -314,18 +248,6 @@ GetApManagerClient()->Init(GetSystemBus()); GetArcBridgeClient()->Init(GetSystemBus()); GetAudioDspClient()->Init(GetSystemBus()); - GetBluetoothAdapterClient()->Init(GetSystemBus()); - GetBluetoothAgentManagerClient()->Init(GetSystemBus()); - GetBluetoothDeviceClient()->Init(GetSystemBus()); - GetBluetoothGattCharacteristicClient()->Init(GetSystemBus()); - GetBluetoothGattDescriptorClient()->Init(GetSystemBus()); - GetBluetoothGattManagerClient()->Init(GetSystemBus()); - GetBluetoothGattServiceClient()->Init(GetSystemBus()); - GetBluetoothInputClient()->Init(GetSystemBus()); - GetBluetoothLEAdvertisingManagerClient()->Init(GetSystemBus()); - GetBluetoothMediaClient()->Init(GetSystemBus()); - GetBluetoothMediaTransportClient()->Init(GetSystemBus()); - GetBluetoothProfileManagerClient()->Init(GetSystemBus()); GetCrasAudioClient()->Init(GetSystemBus()); GetCrosDisksClient()->Init(GetSystemBus()); GetCryptohomeClient()->Init(GetSystemBus()); @@ -485,79 +407,6 @@ DBusThreadManager::Get()->client_bundle_->audio_dsp_client_ = client.Pass(); } -void DBusThreadManagerSetter::SetBluetoothAdapterClient( - scoped_ptr<BluetoothAdapterClient> client) { - DBusThreadManager::Get()->client_bundle_->bluetooth_adapter_client_ = - client.Pass(); -} - -void DBusThreadManagerSetter::SetBluetoothLEAdvertisingManagerClient( - scoped_ptr<BluetoothLEAdvertisingManagerClient> client) { - DBusThreadManager::Get() - ->client_bundle_->bluetooth_le_advertising_manager_client_ = - client.Pass(); -} - -void DBusThreadManagerSetter::SetBluetoothAgentManagerClient( - scoped_ptr<BluetoothAgentManagerClient> client) { - DBusThreadManager::Get()->client_bundle_->bluetooth_agent_manager_client_ = - client.Pass(); -} - -void DBusThreadManagerSetter::SetBluetoothDeviceClient( - scoped_ptr<BluetoothDeviceClient> client) { - DBusThreadManager::Get()->client_bundle_->bluetooth_device_client_ = - client.Pass(); -} - -void DBusThreadManagerSetter::SetBluetoothGattCharacteristicClient( - scoped_ptr<BluetoothGattCharacteristicClient> client) { - DBusThreadManager::Get() - ->client_bundle_->bluetooth_gatt_characteristic_client_ = client.Pass(); -} - -void DBusThreadManagerSetter::SetBluetoothGattDescriptorClient( - scoped_ptr<BluetoothGattDescriptorClient> client) { - DBusThreadManager::Get()->client_bundle_->bluetooth_gatt_descriptor_client_ = - client.Pass(); -} - -void DBusThreadManagerSetter::SetBluetoothGattManagerClient( - scoped_ptr<BluetoothGattManagerClient> client) { - DBusThreadManager::Get()->client_bundle_->bluetooth_gatt_manager_client_ = - client.Pass(); -} - -void DBusThreadManagerSetter::SetBluetoothGattServiceClient( - scoped_ptr<BluetoothGattServiceClient> client) { - DBusThreadManager::Get()->client_bundle_->bluetooth_gatt_service_client_ = - client.Pass(); -} - -void DBusThreadManagerSetter::SetBluetoothInputClient( - scoped_ptr<BluetoothInputClient> client) { - DBusThreadManager::Get()->client_bundle_->bluetooth_input_client_ = - client.Pass(); -} - -void DBusThreadManagerSetter::SetBluetoothMediaClient( - scoped_ptr<BluetoothMediaClient> client) { - DBusThreadManager::Get()->client_bundle_->bluetooth_media_client_ = - client.Pass(); -} - -void DBusThreadManagerSetter::SetBluetoothMediaTransportClient( - scoped_ptr<BluetoothMediaTransportClient> client) { - DBusThreadManager::Get()->client_bundle_->bluetooth_media_transport_client_ = - client.Pass(); -} - -void DBusThreadManagerSetter::SetBluetoothProfileManagerClient( - scoped_ptr<BluetoothProfileManagerClient> client) { - DBusThreadManager::Get()->client_bundle_->bluetooth_profile_manager_client_ = - client.Pass(); -} - void DBusThreadManagerSetter::SetCrasAudioClient( scoped_ptr<CrasAudioClient> client) { DBusThreadManager::Get()->client_bundle_->cras_audio_client_ = client.Pass();
diff --git a/chromeos/dbus/dbus_thread_manager.h b/chromeos/dbus/dbus_thread_manager.h index b002c9f..eaf9109f 100644 --- a/chromeos/dbus/dbus_thread_manager.h +++ b/chromeos/dbus/dbus_thread_manager.h
@@ -29,18 +29,6 @@ class ApManagerClient; class ArcBridgeClient; class AudioDspClient; -class BluetoothAdapterClient; -class BluetoothLEAdvertisingManagerClient; -class BluetoothAgentManagerClient; -class BluetoothDeviceClient; -class BluetoothGattCharacteristicClient; -class BluetoothGattDescriptorClient; -class BluetoothGattManagerClient; -class BluetoothGattServiceClient; -class BluetoothInputClient; -class BluetoothMediaClient; -class BluetoothMediaTransportClient; -class BluetoothProfileManagerClient; class CrasAudioClient; class CrosDisksClient; class CryptohomeClient; @@ -126,18 +114,6 @@ ApManagerClient* GetApManagerClient(); ArcBridgeClient* GetArcBridgeClient(); AudioDspClient* GetAudioDspClient(); - BluetoothAdapterClient* GetBluetoothAdapterClient(); - BluetoothLEAdvertisingManagerClient* GetBluetoothLEAdvertisingManagerClient(); - BluetoothAgentManagerClient* GetBluetoothAgentManagerClient(); - BluetoothDeviceClient* GetBluetoothDeviceClient(); - BluetoothGattCharacteristicClient* GetBluetoothGattCharacteristicClient(); - BluetoothGattDescriptorClient* GetBluetoothGattDescriptorClient(); - BluetoothGattManagerClient* GetBluetoothGattManagerClient(); - BluetoothGattServiceClient* GetBluetoothGattServiceClient(); - BluetoothInputClient* GetBluetoothInputClient(); - BluetoothMediaClient* GetBluetoothMediaClient(); - BluetoothMediaTransportClient* GetBluetoothMediaTransportClient(); - BluetoothProfileManagerClient* GetBluetoothProfileManagerClient(); CrasAudioClient* GetCrasAudioClient(); CrosDisksClient* GetCrosDisksClient(); CryptohomeClient* GetCryptohomeClient(); @@ -213,26 +189,6 @@ void SetAmplifierClient(scoped_ptr<AmplifierClient> client); void SetArcBridgeClient(scoped_ptr<ArcBridgeClient> client); void SetAudioDspClient(scoped_ptr<AudioDspClient> client); - void SetBluetoothAdapterClient(scoped_ptr<BluetoothAdapterClient> client); - void SetBluetoothLEAdvertisingManagerClient( - scoped_ptr<BluetoothLEAdvertisingManagerClient> client); - void SetBluetoothAgentManagerClient( - scoped_ptr<BluetoothAgentManagerClient> client); - void SetBluetoothDeviceClient(scoped_ptr<BluetoothDeviceClient> client); - void SetBluetoothGattCharacteristicClient( - scoped_ptr<BluetoothGattCharacteristicClient> client); - void SetBluetoothGattDescriptorClient( - scoped_ptr<BluetoothGattDescriptorClient> client); - void SetBluetoothGattManagerClient( - scoped_ptr<BluetoothGattManagerClient> client); - void SetBluetoothGattServiceClient( - scoped_ptr<BluetoothGattServiceClient> client); - void SetBluetoothInputClient(scoped_ptr<BluetoothInputClient> client); - void SetBluetoothMediaClient(scoped_ptr<BluetoothMediaClient> client); - void SetBluetoothMediaTransportClient( - scoped_ptr<BluetoothMediaTransportClient> client); - void SetBluetoothProfileManagerClient( - scoped_ptr<BluetoothProfileManagerClient> client); void SetCrasAudioClient(scoped_ptr<CrasAudioClient> client); void SetCrosDisksClient(scoped_ptr<CrosDisksClient> client); void SetCryptohomeClient(scoped_ptr<CryptohomeClient> client);
diff --git a/chromeos/dbus/fake_bluetooth_adapter_client.cc b/chromeos/dbus/fake_bluetooth_adapter_client.cc deleted file mode 100644 index 1ff4bccf..0000000 --- a/chromeos/dbus/fake_bluetooth_adapter_client.cc +++ /dev/null
@@ -1,296 +0,0 @@ -// Copyright (c) 2013 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 "chromeos/dbus/fake_bluetooth_adapter_client.h" - -#include "base/location.h" -#include "base/logging.h" -#include "base/single_thread_task_runner.h" -#include "base/thread_task_runner_handle.h" -#include "base/time/time.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_device_client.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -namespace { - -// Default interval for delayed tasks. -const int kSimulationIntervalMs = 750; - -} // namespace - -const char FakeBluetoothAdapterClient::kAdapterPath[] = "/fake/hci0"; -const char FakeBluetoothAdapterClient::kAdapterName[] = "Fake Adapter"; -const char FakeBluetoothAdapterClient::kAdapterAddress[] = "01:1A:2B:1A:2B:03"; - -const char FakeBluetoothAdapterClient::kSecondAdapterPath[] = "/fake/hci1"; -const char FakeBluetoothAdapterClient::kSecondAdapterName[] = - "Second Fake Adapter"; -const char FakeBluetoothAdapterClient::kSecondAdapterAddress[] = - "00:DE:51:10:01:00"; - -FakeBluetoothAdapterClient::Properties::Properties( - const PropertyChangedCallback& callback) - : BluetoothAdapterClient::Properties( - NULL, - bluetooth_adapter::kBluetoothAdapterInterface, - callback) {} - -FakeBluetoothAdapterClient::Properties::~Properties() {} - -void FakeBluetoothAdapterClient::Properties::Get( - dbus::PropertyBase* property, - dbus::PropertySet::GetCallback callback) { - VLOG(1) << "Get " << property->name(); - callback.Run(false); -} - -void FakeBluetoothAdapterClient::Properties::GetAll() { - VLOG(1) << "GetAll"; -} - -void FakeBluetoothAdapterClient::Properties::Set( - dbus::PropertyBase* property, - dbus::PropertySet::SetCallback callback) { - VLOG(1) << "Set " << property->name(); - if (property->name() == powered.name() || property->name() == alias.name() || - property->name() == discoverable.name() || - property->name() == discoverable_timeout.name()) { - callback.Run(true); - property->ReplaceValueWithSetValue(); - } else { - callback.Run(false); - } -} - -FakeBluetoothAdapterClient::FakeBluetoothAdapterClient() - : visible_(true), - second_visible_(false), - discovering_count_(0), - set_discovery_filter_should_fail_(false), - simulation_interval_ms_(kSimulationIntervalMs) { - properties_.reset(new Properties(base::Bind( - &FakeBluetoothAdapterClient::OnPropertyChanged, base::Unretained(this)))); - - properties_->address.ReplaceValue(kAdapterAddress); - properties_->name.ReplaceValue("Fake Adapter (Name)"); - properties_->alias.ReplaceValue(kAdapterName); - properties_->pairable.ReplaceValue(true); - - second_properties_.reset(new Properties(base::Bind( - &FakeBluetoothAdapterClient::OnPropertyChanged, base::Unretained(this)))); - - second_properties_->address.ReplaceValue(kSecondAdapterAddress); - second_properties_->name.ReplaceValue("Second Fake Adapter (Name)"); - second_properties_->alias.ReplaceValue(kSecondAdapterName); - second_properties_->pairable.ReplaceValue(true); -} - -FakeBluetoothAdapterClient::~FakeBluetoothAdapterClient() {} - -void FakeBluetoothAdapterClient::Init(dbus::Bus* bus) {} - -void FakeBluetoothAdapterClient::AddObserver(Observer* observer) { - observers_.AddObserver(observer); -} - -void FakeBluetoothAdapterClient::RemoveObserver(Observer* observer) { - observers_.RemoveObserver(observer); -} - -std::vector<dbus::ObjectPath> FakeBluetoothAdapterClient::GetAdapters() { - std::vector<dbus::ObjectPath> object_paths; - if (visible_) - object_paths.push_back(dbus::ObjectPath(kAdapterPath)); - if (second_visible_) - object_paths.push_back(dbus::ObjectPath(kSecondAdapterPath)); - return object_paths; -} - -FakeBluetoothAdapterClient::Properties* -FakeBluetoothAdapterClient::GetProperties(const dbus::ObjectPath& object_path) { - if (object_path == dbus::ObjectPath(kAdapterPath)) - return properties_.get(); - else if (object_path == dbus::ObjectPath(kSecondAdapterPath)) - return second_properties_.get(); - else - return NULL; -} - -void FakeBluetoothAdapterClient::StartDiscovery( - const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - if (object_path != dbus::ObjectPath(kAdapterPath)) { - PostDelayedTask(base::Bind(error_callback, kNoResponseError, "")); - return; - } - - ++discovering_count_; - VLOG(1) << "StartDiscovery: " << object_path.value() << ", " - << "count is now " << discovering_count_; - PostDelayedTask(callback); - - if (discovering_count_ == 1) { - properties_->discovering.ReplaceValue(true); - - FakeBluetoothDeviceClient* device_client = - static_cast<FakeBluetoothDeviceClient*>( - DBusThreadManager::Get()->GetBluetoothDeviceClient()); - device_client->BeginDiscoverySimulation(dbus::ObjectPath(kAdapterPath)); - } -} - -void FakeBluetoothAdapterClient::StopDiscovery( - const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - if (object_path != dbus::ObjectPath(kAdapterPath)) { - PostDelayedTask(base::Bind(error_callback, kNoResponseError, "")); - return; - } - - if (!discovering_count_) { - LOG(WARNING) << "StopDiscovery called when not discovering"; - PostDelayedTask(base::Bind(error_callback, kNoResponseError, "")); - return; - } - - --discovering_count_; - VLOG(1) << "StopDiscovery: " << object_path.value() << ", " - << "count is now " << discovering_count_; - PostDelayedTask(callback); - - if (discovering_count_ == 0) { - FakeBluetoothDeviceClient* device_client = - static_cast<FakeBluetoothDeviceClient*>( - DBusThreadManager::Get()->GetBluetoothDeviceClient()); - device_client->EndDiscoverySimulation(dbus::ObjectPath(kAdapterPath)); - - if (simulation_interval_ms_ > 100) { - device_client->BeginIncomingPairingSimulation( - dbus::ObjectPath(kAdapterPath)); - } - - discovery_filter_.reset(); - properties_->discovering.ReplaceValue(false); - } -} - -void FakeBluetoothAdapterClient::RemoveDevice( - const dbus::ObjectPath& object_path, - const dbus::ObjectPath& device_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - if (object_path != dbus::ObjectPath(kAdapterPath)) { - error_callback.Run(kNoResponseError, ""); - return; - } - - VLOG(1) << "RemoveDevice: " << object_path.value() << " " - << device_path.value(); - callback.Run(); - - FakeBluetoothDeviceClient* device_client = - static_cast<FakeBluetoothDeviceClient*>( - DBusThreadManager::Get()->GetBluetoothDeviceClient()); - device_client->RemoveDevice(dbus::ObjectPath(kAdapterPath), device_path); -} - -void FakeBluetoothAdapterClient::MakeSetDiscoveryFilterFail() { - set_discovery_filter_should_fail_ = true; -} - -void FakeBluetoothAdapterClient::SetDiscoveryFilter( - const dbus::ObjectPath& object_path, - const DiscoveryFilter& discovery_filter, - const base::Closure& callback, - const ErrorCallback& error_callback) { - if (object_path != dbus::ObjectPath(kAdapterPath)) { - PostDelayedTask(base::Bind(error_callback, kNoResponseError, "")); - return; - } - VLOG(1) << "SetDiscoveryFilter: " << object_path.value(); - - if (set_discovery_filter_should_fail_) { - PostDelayedTask(base::Bind(error_callback, kNoResponseError, "")); - set_discovery_filter_should_fail_ = false; - return; - } - - discovery_filter_.reset(new DiscoveryFilter()); - discovery_filter_->CopyFrom(discovery_filter); - PostDelayedTask(callback); -} - -void FakeBluetoothAdapterClient::SetSimulationIntervalMs(int interval_ms) { - simulation_interval_ms_ = interval_ms; -} - -BluetoothAdapterClient::DiscoveryFilter* -FakeBluetoothAdapterClient::GetDiscoveryFilter() { - return discovery_filter_.get(); -} - -void FakeBluetoothAdapterClient::SetVisible(bool visible) { - if (visible && !visible_) { - // Adapter becoming visible - visible_ = visible; - - FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, - AdapterAdded(dbus::ObjectPath(kAdapterPath))); - - } else if (visible_ && !visible) { - // Adapter becoming invisible - visible_ = visible; - - FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, - AdapterRemoved(dbus::ObjectPath(kAdapterPath))); - } -} - -void FakeBluetoothAdapterClient::SetSecondVisible(bool visible) { - if (visible && !second_visible_) { - // Second adapter becoming visible - second_visible_ = visible; - - FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, - AdapterAdded(dbus::ObjectPath(kSecondAdapterPath))); - - } else if (second_visible_ && !visible) { - // Second adapter becoming invisible - second_visible_ = visible; - - FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, - AdapterRemoved(dbus::ObjectPath(kSecondAdapterPath))); - } -} - -void FakeBluetoothAdapterClient::OnPropertyChanged( - const std::string& property_name) { - if (property_name == properties_->powered.name() && - !properties_->powered.value()) { - VLOG(1) << "Adapter powered off"; - - if (discovering_count_) { - discovering_count_ = 0; - properties_->discovering.ReplaceValue(false); - } - } - - FOR_EACH_OBSERVER( - BluetoothAdapterClient::Observer, observers_, - AdapterPropertyChanged(dbus::ObjectPath(kAdapterPath), property_name)); -} - -void FakeBluetoothAdapterClient::PostDelayedTask( - const base::Closure& callback) { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, callback, - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_adapter_client.h b/chromeos/dbus/fake_bluetooth_adapter_client.h deleted file mode 100644 index 987fc6f..0000000 --- a/chromeos/dbus/fake_bluetooth_adapter_client.h +++ /dev/null
@@ -1,118 +0,0 @@ -// Copyright (c) 2013 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 CHROMEOS_DBUS_FAKE_BLUETOOTH_ADAPTER_CLIENT_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_ADAPTER_CLIENT_H_ - -#include <vector> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/observer_list.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_adapter_client.h" -#include "dbus/object_path.h" -#include "dbus/property.h" - -namespace chromeos { - -// FakeBluetoothAdapterClient simulates the behavior of the Bluetooth Daemon -// adapter objects and is used both in test cases in place of a mock and on -// the Linux desktop. -class CHROMEOS_EXPORT FakeBluetoothAdapterClient - : public BluetoothAdapterClient { - public: - struct Properties : public BluetoothAdapterClient::Properties { - explicit Properties(const PropertyChangedCallback& callback); - ~Properties() override; - - // dbus::PropertySet override - void Get(dbus::PropertyBase* property, - dbus::PropertySet::GetCallback callback) override; - void GetAll() override; - void Set(dbus::PropertyBase* property, - dbus::PropertySet::SetCallback callback) override; - }; - - FakeBluetoothAdapterClient(); - ~FakeBluetoothAdapterClient() override; - - // BluetoothAdapterClient overrides - void Init(dbus::Bus* bus) override; - void AddObserver(Observer* observer) override; - void RemoveObserver(Observer* observer) override; - std::vector<dbus::ObjectPath> GetAdapters() override; - Properties* GetProperties(const dbus::ObjectPath& object_path) override; - void StartDiscovery(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - void StopDiscovery(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - void RemoveDevice(const dbus::ObjectPath& object_path, - const dbus::ObjectPath& device_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - void SetDiscoveryFilter(const dbus::ObjectPath& object_path, - const DiscoveryFilter& discovery_filter, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - - // Sets the current simulation timeout interval. - void SetSimulationIntervalMs(int interval_ms); - - // Returns current discovery filter in use by this adapter. - DiscoveryFilter* GetDiscoveryFilter(); - - // Make SetDiscoveryFilter fail when called next time. - void MakeSetDiscoveryFilterFail(); - - // Mark the adapter and second adapter as visible or invisible. - void SetVisible(bool visible); - void SetSecondVisible(bool visible); - - // Object path, name and addresses of the adapters we emulate. - static const char kAdapterPath[]; - static const char kAdapterName[]; - static const char kAdapterAddress[]; - - static const char kSecondAdapterPath[]; - static const char kSecondAdapterName[]; - static const char kSecondAdapterAddress[]; - - private: - // Property callback passed when we create Properties* structures. - void OnPropertyChanged(const std::string& property_name); - - // Posts the delayed task represented by |callback| onto the current - // message loop to be executed after |simulation_interval_ms_| milliseconds. - void PostDelayedTask(const base::Closure& callback); - - // List of observers interested in event notifications from us. - base::ObserverList<Observer> observers_; - - // Static properties we return. - scoped_ptr<Properties> properties_; - scoped_ptr<Properties> second_properties_; - - // Whether the adapter and second adapter should be visible or not. - bool visible_; - bool second_visible_; - - // Number of times we've been asked to discover. - int discovering_count_; - - // Current discovery filter - scoped_ptr<DiscoveryFilter> discovery_filter_; - - // When set, next call to SetDiscoveryFilter would fail. - bool set_discovery_filter_should_fail_; - - // Current timeout interval used when posting delayed tasks. - int simulation_interval_ms_; -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_ADAPTER_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_agent_manager_client.cc b/chromeos/dbus/fake_bluetooth_agent_manager_client.cc deleted file mode 100644 index 4ced274..0000000 --- a/chromeos/dbus/fake_bluetooth_agent_manager_client.cc +++ /dev/null
@@ -1,78 +0,0 @@ -// Copyright (c) 2013 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 "chromeos/dbus/fake_bluetooth_agent_manager_client.h" - -#include "base/logging.h" -#include "chromeos/dbus/fake_bluetooth_agent_service_provider.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -FakeBluetoothAgentManagerClient::FakeBluetoothAgentManagerClient() - : service_provider_(NULL) {} - -FakeBluetoothAgentManagerClient::~FakeBluetoothAgentManagerClient() {} - -void FakeBluetoothAgentManagerClient::Init(dbus::Bus* bus) {} - -void FakeBluetoothAgentManagerClient::RegisterAgent( - const dbus::ObjectPath& agent_path, - const std::string& capability, - const base::Closure& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "RegisterAgent: " << agent_path.value(); - - if (service_provider_ == NULL) { - error_callback.Run(bluetooth_agent_manager::kErrorInvalidArguments, - "No agent created"); - } else if (service_provider_->object_path_ != agent_path) { - error_callback.Run(bluetooth_agent_manager::kErrorAlreadyExists, - "Agent already registered"); - } else { - callback.Run(); - } -} - -void FakeBluetoothAgentManagerClient::UnregisterAgent( - const dbus::ObjectPath& agent_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "UnregisterAgent: " << agent_path.value(); - if (service_provider_ == NULL) { - error_callback.Run(bluetooth_agent_manager::kErrorDoesNotExist, - "No agent registered"); - } else if (service_provider_->object_path_ != agent_path) { - error_callback.Run(bluetooth_agent_manager::kErrorDoesNotExist, - "Agent still registered"); - } else { - callback.Run(); - } -} - -void FakeBluetoothAgentManagerClient::RequestDefaultAgent( - const dbus::ObjectPath& agent_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "RequestDefaultAgent: " << agent_path.value(); - callback.Run(); -} - -void FakeBluetoothAgentManagerClient::RegisterAgentServiceProvider( - FakeBluetoothAgentServiceProvider* service_provider) { - service_provider_ = service_provider; -} - -void FakeBluetoothAgentManagerClient::UnregisterAgentServiceProvider( - FakeBluetoothAgentServiceProvider* service_provider) { - if (service_provider_ == service_provider) - service_provider_ = NULL; -} - -FakeBluetoothAgentServiceProvider* -FakeBluetoothAgentManagerClient::GetAgentServiceProvider() { - return service_provider_; -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_agent_manager_client.h b/chromeos/dbus/fake_bluetooth_agent_manager_client.h deleted file mode 100644 index 68c91202c3..0000000 --- a/chromeos/dbus/fake_bluetooth_agent_manager_client.h +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright (c) 2013 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 CHROMEOS_DBUS_FAKE_BLUETOOTH_AGENT_MANAGER_CLIENT_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_AGENT_MANAGER_CLIENT_H_ - -#include "base/bind.h" -#include "base/callback.h" -#include "base/observer_list.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_agent_manager_client.h" -#include "dbus/object_path.h" -#include "dbus/property.h" - -namespace chromeos { - -class FakeBluetoothAgentServiceProvider; - -// FakeBluetoothAgentManagerClient simulates the behavior of the Bluetooth -// Daemon's agent manager object and is used both in test cases in place of a -// mock and on the Linux desktop. -class CHROMEOS_EXPORT FakeBluetoothAgentManagerClient - : public BluetoothAgentManagerClient { - public: - FakeBluetoothAgentManagerClient(); - ~FakeBluetoothAgentManagerClient() override; - - // BluetoothAgentManagerClient overrides - void Init(dbus::Bus* bus) override; - void RegisterAgent(const dbus::ObjectPath& agent_path, - const std::string& capability, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - void UnregisterAgent(const dbus::ObjectPath& agent_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - void RequestDefaultAgent(const dbus::ObjectPath& agent_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - - // Register, unregister and retrieve pointers to agent service providers. - void RegisterAgentServiceProvider( - FakeBluetoothAgentServiceProvider* service_provider); - void UnregisterAgentServiceProvider( - FakeBluetoothAgentServiceProvider* service_provider); - FakeBluetoothAgentServiceProvider* GetAgentServiceProvider(); - - private: - // The single agent service provider we permit, owned by the application - // using it. - FakeBluetoothAgentServiceProvider* service_provider_; -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_AGENT_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_agent_service_provider.cc b/chromeos/dbus/fake_bluetooth_agent_service_provider.cc deleted file mode 100644 index de2dbd3..0000000 --- a/chromeos/dbus/fake_bluetooth_agent_service_provider.cc +++ /dev/null
@@ -1,102 +0,0 @@ -// Copyright (c) 2013 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 "chromeos/dbus/fake_bluetooth_agent_service_provider.h" - -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" - -namespace chromeos { - -FakeBluetoothAgentServiceProvider::FakeBluetoothAgentServiceProvider( - const dbus::ObjectPath& object_path, - Delegate* delegate) - : object_path_(object_path), delegate_(delegate) { - VLOG(1) << "Creating Bluetooth Agent: " << object_path_.value(); - - FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client = - static_cast<FakeBluetoothAgentManagerClient*>( - DBusThreadManager::Get()->GetBluetoothAgentManagerClient()); - fake_bluetooth_agent_manager_client->RegisterAgentServiceProvider(this); -} - -FakeBluetoothAgentServiceProvider::~FakeBluetoothAgentServiceProvider() { - VLOG(1) << "Cleaning up Bluetooth Agent: " << object_path_.value(); - - FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client = - static_cast<FakeBluetoothAgentManagerClient*>( - DBusThreadManager::Get()->GetBluetoothAgentManagerClient()); - fake_bluetooth_agent_manager_client->UnregisterAgentServiceProvider(this); -} - -void FakeBluetoothAgentServiceProvider::Release() { - VLOG(1) << object_path_.value() << ": Release"; - delegate_->Released(); -} - -void FakeBluetoothAgentServiceProvider::RequestPinCode( - const dbus::ObjectPath& device_path, - const Delegate::PinCodeCallback& callback) { - VLOG(1) << object_path_.value() << ": RequestPinCode for " - << device_path.value(); - delegate_->RequestPinCode(device_path, callback); -} - -void FakeBluetoothAgentServiceProvider::DisplayPinCode( - const dbus::ObjectPath& device_path, - const std::string& pincode) { - VLOG(1) << object_path_.value() << ": DisplayPincode " << pincode << " for " - << device_path.value(); - delegate_->DisplayPinCode(device_path, pincode); -} - -void FakeBluetoothAgentServiceProvider::RequestPasskey( - const dbus::ObjectPath& device_path, - const Delegate::PasskeyCallback& callback) { - VLOG(1) << object_path_.value() << ": RequestPasskey for " - << device_path.value(); - delegate_->RequestPasskey(device_path, callback); -} - -void FakeBluetoothAgentServiceProvider::DisplayPasskey( - const dbus::ObjectPath& device_path, - uint32 passkey, - int16 entered) { - VLOG(1) << object_path_.value() << ": DisplayPasskey " << passkey << " (" - << entered << " entered) for " << device_path.value(); - delegate_->DisplayPasskey(device_path, passkey, entered); -} - -void FakeBluetoothAgentServiceProvider::RequestConfirmation( - const dbus::ObjectPath& device_path, - uint32 passkey, - const Delegate::ConfirmationCallback& callback) { - VLOG(1) << object_path_.value() << ": RequestConfirmation " << passkey - << " for " << device_path.value(); - delegate_->RequestConfirmation(device_path, passkey, callback); -} - -void FakeBluetoothAgentServiceProvider::RequestAuthorization( - const dbus::ObjectPath& device_path, - const Delegate::ConfirmationCallback& callback) { - VLOG(1) << object_path_.value() << ": RequestAuthorization for " - << device_path.value(); - delegate_->RequestAuthorization(device_path, callback); -} - -void FakeBluetoothAgentServiceProvider::AuthorizeService( - const dbus::ObjectPath& device_path, - const std::string& uuid, - const Delegate::ConfirmationCallback& callback) { - VLOG(1) << object_path_.value() << ": AuthorizeService " << uuid << " for " - << device_path.value(); - delegate_->AuthorizeService(device_path, uuid, callback); -} - -void FakeBluetoothAgentServiceProvider::Cancel() { - VLOG(1) << object_path_.value() << ": Cancel"; - delegate_->Cancel(); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_agent_service_provider.h b/chromeos/dbus/fake_bluetooth_agent_service_provider.h deleted file mode 100644 index 6d17519a..0000000 --- a/chromeos/dbus/fake_bluetooth_agent_service_provider.h +++ /dev/null
@@ -1,68 +0,0 @@ -// Copyright (c) 2013 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 CHROMEOS_DBUS_FAKE_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_ - -#include "base/bind.h" -#include "base/callback.h" -#include "base/observer_list.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_agent_service_provider.h" -#include "dbus/object_path.h" -#include "dbus/property.h" - -namespace chromeos { - -class FakeBluetoothAgentManagerClient; - -// FakeBluetoothAgentServiceProvider simulates the behavior of a local -// Bluetooth agent object and is used both in test cases in place of a -// mock and on the Linux desktop. -class CHROMEOS_EXPORT FakeBluetoothAgentServiceProvider - : public BluetoothAgentServiceProvider { - public: - FakeBluetoothAgentServiceProvider(const dbus::ObjectPath& object_path, - Delegate* delegate); - ~FakeBluetoothAgentServiceProvider() override; - - // Each of these calls the equivalent BluetoothAgentServiceProvider::Delegate - // method on the object passed on construction. - virtual void Release(); - virtual void RequestPinCode(const dbus::ObjectPath& device_path, - const Delegate::PinCodeCallback& callback); - virtual void DisplayPinCode(const dbus::ObjectPath& device_path, - const std::string& pincode); - virtual void RequestPasskey(const dbus::ObjectPath& device_path, - const Delegate::PasskeyCallback& callback); - virtual void DisplayPasskey(const dbus::ObjectPath& device_path, - uint32 passkey, - int16 entered); - virtual void RequestConfirmation( - const dbus::ObjectPath& device_path, - uint32 passkey, - const Delegate::ConfirmationCallback& callback); - virtual void RequestAuthorization( - const dbus::ObjectPath& device_path, - const Delegate::ConfirmationCallback& callback); - virtual void AuthorizeService(const dbus::ObjectPath& device_path, - const std::string& uuid, - const Delegate::ConfirmationCallback& callback); - virtual void Cancel(); - - private: - friend class FakeBluetoothAgentManagerClient; - - // D-Bus object path we are faking. - dbus::ObjectPath object_path_; - - // All incoming method calls are passed on to the Delegate and a callback - // passed to generate the reply. |delegate_| is generally the object that - // owns this one, and must outlive it. - Delegate* delegate_; -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/fake_bluetooth_device_client.cc b/chromeos/dbus/fake_bluetooth_device_client.cc deleted file mode 100644 index 1aa01a5..0000000 --- a/chromeos/dbus/fake_bluetooth_device_client.cc +++ /dev/null
@@ -1,1662 +0,0 @@ -// Copyright (c) 2013 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 "chromeos/dbus/fake_bluetooth_device_client.h" - -#include <fcntl.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <unistd.h> - -#include <algorithm> -#include <string> -#include <utility> - -#include "base/location.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/rand_util.h" -#include "base/single_thread_task_runner.h" -#include "base/stl_util.h" -#include "base/thread_task_runner_handle.h" -#include "base/threading/worker_pool.h" -#include "base/time/time.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_adapter_client.h" -#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" -#include "chromeos/dbus/fake_bluetooth_agent_service_provider.h" -#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h" -#include "chromeos/dbus/fake_bluetooth_input_client.h" -#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h" -#include "chromeos/dbus/fake_bluetooth_profile_service_provider.h" -#include "dbus/file_descriptor.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace { - -// Default interval between simulated events. -const int kSimulationIntervalMs = 750; - -// Minimum and maximum bounds for randomly generated RSSI values. -const int kMinRSSI = -90; -const int kMaxRSSI = -30; - -// The default value of connection info properties from GetConnInfo(). -const int kUnkownPower = 127; - -// This is meant to delay the removal of a pre defined device until the -// developer has time to see it. -const int kVanishingDevicePairTimeMultiplier = 4; - -// Meant to delay a pair request for an observable amount of time. -const int kIncomingSimulationPairTimeMultiplier = 45; - -// Meant to delay a request that asks for pair requests for an observable -// amount of time. -const int kIncomingSimulationStartPairTimeMultiplier = 30; - -// This allows the PIN code dialog to be shown for a long enough time to see -// the PIN code UI in detail. -const int kPinCodeDevicePairTimeMultiplier = 7; - -// This allows the pairing dialog to be shown for a long enough time to see -// its UI in detail. -const int kSimulateNormalPairTimeMultiplier = 3; - -void SimulatedProfileSocket(int fd) { - // Simulate a server-side socket of a profile; read data from the socket, - // write it back, and then close. - char buf[1024]; - ssize_t len; - ssize_t count; - - len = read(fd, buf, sizeof buf); - if (len < 0) { - close(fd); - return; - } - - count = len; - len = write(fd, buf, count); - if (len < 0) { - close(fd); - return; - } - - close(fd); -} - -void SimpleErrorCallback(const std::string& error_name, - const std::string& error_message) { - VLOG(1) << "Bluetooth Error: " << error_name << ": " << error_message; -} - -} // namespace - -namespace chromeos { - -const char FakeBluetoothDeviceClient::kTestPinCode[] = "123456"; -const int FakeBluetoothDeviceClient::kTestPassKey = 123456; - -const char FakeBluetoothDeviceClient::kPairingMethodNone[] = "None"; -const char FakeBluetoothDeviceClient::kPairingMethodPinCode[] = "PIN Code"; -const char FakeBluetoothDeviceClient::kPairingMethodPassKey[] = "PassKey"; - -const char FakeBluetoothDeviceClient::kPairingActionConfirmation[] = - "Confirmation"; -const char FakeBluetoothDeviceClient::kPairingActionDisplay[] = "Display"; -const char FakeBluetoothDeviceClient::kPairingActionFail[] = "Fail"; -const char FakeBluetoothDeviceClient::kPairingActionRequest[] = "Request"; - -const char FakeBluetoothDeviceClient::kPairedDevicePath[] = "/fake/hci0/dev0"; -const char FakeBluetoothDeviceClient::kPairedDeviceAddress[] = - "00:11:22:33:44:55"; -const char FakeBluetoothDeviceClient::kPairedDeviceName[] = "Fake Device"; -const uint32 FakeBluetoothDeviceClient::kPairedDeviceClass = 0x000104; - -const char FakeBluetoothDeviceClient::kLegacyAutopairPath[] = "/fake/hci0/dev1"; -const char FakeBluetoothDeviceClient::kLegacyAutopairAddress[] = - "28:CF:DA:00:00:00"; -const char FakeBluetoothDeviceClient::kLegacyAutopairName[] = - "Bluetooth 2.0 Mouse"; -const uint32 FakeBluetoothDeviceClient::kLegacyAutopairClass = 0x002580; - -const char FakeBluetoothDeviceClient::kDisplayPinCodePath[] = "/fake/hci0/dev2"; -const char FakeBluetoothDeviceClient::kDisplayPinCodeAddress[] = - "28:37:37:00:00:00"; -const char FakeBluetoothDeviceClient::kDisplayPinCodeName[] = - "Bluetooth 2.0 Keyboard"; -const uint32 FakeBluetoothDeviceClient::kDisplayPinCodeClass = 0x002540; - -const char FakeBluetoothDeviceClient::kVanishingDevicePath[] = - "/fake/hci0/dev3"; -const char FakeBluetoothDeviceClient::kVanishingDeviceAddress[] = - "01:02:03:04:05:06"; -const char FakeBluetoothDeviceClient::kVanishingDeviceName[] = - "Vanishing Device"; -const uint32 FakeBluetoothDeviceClient::kVanishingDeviceClass = 0x000104; - -const char FakeBluetoothDeviceClient::kConnectUnpairablePath[] = - "/fake/hci0/dev4"; -const char FakeBluetoothDeviceClient::kConnectUnpairableAddress[] = - "7C:ED:8D:00:00:00"; -const char FakeBluetoothDeviceClient::kConnectUnpairableName[] = - "Unpairable Device"; -const uint32 FakeBluetoothDeviceClient::kConnectUnpairableClass = 0x002580; - -const char FakeBluetoothDeviceClient::kDisplayPasskeyPath[] = "/fake/hci0/dev5"; -const char FakeBluetoothDeviceClient::kDisplayPasskeyAddress[] = - "00:0F:F6:00:00:00"; -const char FakeBluetoothDeviceClient::kDisplayPasskeyName[] = - "Bluetooth 2.1+ Keyboard"; -const uint32 FakeBluetoothDeviceClient::kDisplayPasskeyClass = 0x002540; - -const char FakeBluetoothDeviceClient::kRequestPinCodePath[] = "/fake/hci0/dev6"; -const char FakeBluetoothDeviceClient::kRequestPinCodeAddress[] = - "00:24:BE:00:00:00"; -const char FakeBluetoothDeviceClient::kRequestPinCodeName[] = "PIN Device"; -const uint32 FakeBluetoothDeviceClient::kRequestPinCodeClass = 0x240408; - -const char FakeBluetoothDeviceClient::kConfirmPasskeyPath[] = "/fake/hci0/dev7"; -const char FakeBluetoothDeviceClient::kConfirmPasskeyAddress[] = - "20:7D:74:00:00:00"; -const char FakeBluetoothDeviceClient::kConfirmPasskeyName[] = "Phone"; -const uint32 FakeBluetoothDeviceClient::kConfirmPasskeyClass = 0x7a020c; - -const char FakeBluetoothDeviceClient::kRequestPasskeyPath[] = "/fake/hci0/dev8"; -const char FakeBluetoothDeviceClient::kRequestPasskeyAddress[] = - "20:7D:74:00:00:01"; -const char FakeBluetoothDeviceClient::kRequestPasskeyName[] = "Passkey Device"; -const uint32 FakeBluetoothDeviceClient::kRequestPasskeyClass = 0x7a020c; - -const char FakeBluetoothDeviceClient::kUnconnectableDevicePath[] = - "/fake/hci0/dev9"; -const char FakeBluetoothDeviceClient::kUnconnectableDeviceAddress[] = - "20:7D:74:00:00:02"; -const char FakeBluetoothDeviceClient::kUnconnectableDeviceName[] = - "Unconnectable Device"; -const uint32 FakeBluetoothDeviceClient::kUnconnectableDeviceClass = 0x7a020c; - -const char FakeBluetoothDeviceClient::kUnpairableDevicePath[] = - "/fake/hci0/devA"; -const char FakeBluetoothDeviceClient::kUnpairableDeviceAddress[] = - "20:7D:74:00:00:03"; -const char FakeBluetoothDeviceClient::kUnpairableDeviceName[] = - "Unpairable Device"; -const uint32 FakeBluetoothDeviceClient::kUnpairableDeviceClass = 0x002540; - -const char FakeBluetoothDeviceClient::kJustWorksPath[] = "/fake/hci0/devB"; -const char FakeBluetoothDeviceClient::kJustWorksAddress[] = "00:0C:8A:00:00:00"; -const char FakeBluetoothDeviceClient::kJustWorksName[] = "Just-Works Device"; -const uint32 FakeBluetoothDeviceClient::kJustWorksClass = 0x240428; - -const char FakeBluetoothDeviceClient::kLowEnergyPath[] = "/fake/hci0/devC"; -const char FakeBluetoothDeviceClient::kLowEnergyAddress[] = "00:1A:11:00:15:30"; -const char FakeBluetoothDeviceClient::kLowEnergyName[] = - "Bluetooth 4.0 Heart Rate Monitor"; -const uint32 FakeBluetoothDeviceClient::kLowEnergyClass = - 0x000918; // Major class "Health", Minor class "Heart/Pulse Rate Monitor." - -const char FakeBluetoothDeviceClient::kPairedUnconnectableDevicePath[] = - "/fake/hci0/devD"; -const char FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress[] = - "20:7D:74:00:00:04"; -const char FakeBluetoothDeviceClient::kPairedUnconnectableDeviceName[] = - "Paired Unconnectable Device"; -const uint32 FakeBluetoothDeviceClient::kPairedUnconnectableDeviceClass = - 0x000104; - -const char FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDevicePath[] = - "/fake/hci0/devE"; -const char - FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDeviceAddress[] = - "11:22:33:44:55:66"; -const char FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDeviceName[] = - "Connected Pairable Device"; -const uint32 FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDeviceClass = - 0x7a020c; - -FakeBluetoothDeviceClient::Properties::Properties( - const PropertyChangedCallback& callback) - : BluetoothDeviceClient::Properties( - NULL, - bluetooth_device::kBluetoothDeviceInterface, - callback) {} - -FakeBluetoothDeviceClient::Properties::~Properties() {} - -void FakeBluetoothDeviceClient::Properties::Get( - dbus::PropertyBase* property, - dbus::PropertySet::GetCallback callback) { - VLOG(1) << "Get " << property->name(); - callback.Run(false); -} - -void FakeBluetoothDeviceClient::Properties::GetAll() { - VLOG(1) << "GetAll"; -} - -void FakeBluetoothDeviceClient::Properties::Set( - dbus::PropertyBase* property, - dbus::PropertySet::SetCallback callback) { - VLOG(1) << "Set " << property->name(); - if (property->name() == trusted.name()) { - callback.Run(true); - property->ReplaceValueWithSetValue(); - } else { - callback.Run(false); - } -} - -FakeBluetoothDeviceClient::SimulatedPairingOptions::SimulatedPairingOptions() {} - -FakeBluetoothDeviceClient::SimulatedPairingOptions::~SimulatedPairingOptions() { -} - -FakeBluetoothDeviceClient::IncomingDeviceProperties:: - IncomingDeviceProperties() {} - -FakeBluetoothDeviceClient::IncomingDeviceProperties:: - ~IncomingDeviceProperties() {} - -FakeBluetoothDeviceClient::FakeBluetoothDeviceClient() - : simulation_interval_ms_(kSimulationIntervalMs), - discovery_simulation_step_(0), - incoming_pairing_simulation_step_(0), - pairing_cancelled_(false), - connection_rssi_(kUnkownPower), - transmit_power_(kUnkownPower), - max_transmit_power_(kUnkownPower) { - scoped_ptr<Properties> properties(new Properties( - base::Bind(&FakeBluetoothDeviceClient::OnPropertyChanged, - base::Unretained(this), dbus::ObjectPath(kPairedDevicePath)))); - properties->address.ReplaceValue(kPairedDeviceAddress); - properties->bluetooth_class.ReplaceValue(kPairedDeviceClass); - properties->name.ReplaceValue("Fake Device (Name)"); - properties->alias.ReplaceValue(kPairedDeviceName); - properties->paired.ReplaceValue(true); - properties->trusted.ReplaceValue(true); - properties->adapter.ReplaceValue( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); - - std::vector<std::string> uuids; - uuids.push_back("00001800-0000-1000-8000-00805f9b34fb"); - uuids.push_back("00001801-0000-1000-8000-00805f9b34fb"); - properties->uuids.ReplaceValue(uuids); - - properties->modalias.ReplaceValue("usb:v05ACp030Dd0306"); - - properties_map_.insert(dbus::ObjectPath(kPairedDevicePath), - properties.Pass()); - device_list_.push_back(dbus::ObjectPath(kPairedDevicePath)); - - properties.reset(new Properties(base::Bind( - &FakeBluetoothDeviceClient::OnPropertyChanged, base::Unretained(this), - dbus::ObjectPath(kPairedUnconnectableDevicePath)))); - properties->address.ReplaceValue(kPairedUnconnectableDeviceAddress); - properties->bluetooth_class.ReplaceValue(kPairedUnconnectableDeviceClass); - properties->name.ReplaceValue("Fake Device 2 (Unconnectable)"); - properties->alias.ReplaceValue(kPairedUnconnectableDeviceName); - properties->paired.ReplaceValue(true); - properties->trusted.ReplaceValue(true); - properties->adapter.ReplaceValue( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); - - properties->uuids.ReplaceValue(uuids); - - properties->modalias.ReplaceValue("usb:v05ACp030Dd0306"); - - properties_map_.insert(dbus::ObjectPath(kPairedUnconnectableDevicePath), - properties.Pass()); - device_list_.push_back(dbus::ObjectPath(kPairedUnconnectableDevicePath)); -} - -FakeBluetoothDeviceClient::~FakeBluetoothDeviceClient() {} - -void FakeBluetoothDeviceClient::Init(dbus::Bus* bus) {} - -void FakeBluetoothDeviceClient::AddObserver(Observer* observer) { - observers_.AddObserver(observer); -} - -void FakeBluetoothDeviceClient::RemoveObserver(Observer* observer) { - observers_.RemoveObserver(observer); -} - -std::vector<dbus::ObjectPath> FakeBluetoothDeviceClient::GetDevicesForAdapter( - const dbus::ObjectPath& adapter_path) { - if (adapter_path == - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)) - return device_list_; - else - return std::vector<dbus::ObjectPath>(); -} - -FakeBluetoothDeviceClient::Properties* FakeBluetoothDeviceClient::GetProperties( - const dbus::ObjectPath& object_path) { - PropertiesMap::const_iterator iter = properties_map_.find(object_path); - if (iter != properties_map_.end()) - return iter->second; - return NULL; -} - -FakeBluetoothDeviceClient::SimulatedPairingOptions* -FakeBluetoothDeviceClient::GetPairingOptions( - const dbus::ObjectPath& object_path) { - PairingOptionsMap::const_iterator iter = - pairing_options_map_.find(object_path); - if (iter != pairing_options_map_.end()) - return iter->second; - return iter != pairing_options_map_.end() ? iter->second : nullptr; -} - -void FakeBluetoothDeviceClient::Connect(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "Connect: " << object_path.value(); - Properties* properties = GetProperties(object_path); - - if (properties->connected.value() == true) { - // Already connected. - callback.Run(); - return; - } - - if (properties->paired.value() != true && - object_path != dbus::ObjectPath(kConnectUnpairablePath) && - object_path != dbus::ObjectPath(kLowEnergyPath)) { - // Must be paired. - error_callback.Run(bluetooth_device::kErrorFailed, "Not paired"); - return; - } else if (properties->paired.value() == true && - (object_path == dbus::ObjectPath(kUnconnectableDevicePath) || - object_path == - dbus::ObjectPath(kPairedUnconnectableDevicePath))) { - // Must not be paired - error_callback.Run(bluetooth_device::kErrorFailed, - "Connection fails while paired"); - return; - } - - // The device can be connected. - properties->connected.ReplaceValue(true); - callback.Run(); - - // Expose GATT services if connected to LE device. - if (object_path == dbus::ObjectPath(kLowEnergyPath)) { - FakeBluetoothGattServiceClient* gatt_service_client = - static_cast<FakeBluetoothGattServiceClient*>( - DBusThreadManager::Get()->GetBluetoothGattServiceClient()); - gatt_service_client->ExposeHeartRateService( - dbus::ObjectPath(kLowEnergyPath)); - properties->gatt_services.ReplaceValue(gatt_service_client->GetServices()); - } - - AddInputDeviceIfNeeded(object_path, properties); -} - -void FakeBluetoothDeviceClient::Disconnect( - const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "Disconnect: " << object_path.value(); - Properties* properties = GetProperties(object_path); - - if (!properties->connected.value()) { - error_callback.Run("org.bluez.Error.NotConnected", "Not Connected"); - return; - } - - // Hide the Heart Rate Service if disconnected from LE device. - if (object_path == dbus::ObjectPath(kLowEnergyPath)) { - FakeBluetoothGattServiceClient* gatt_service_client = - static_cast<FakeBluetoothGattServiceClient*>( - DBusThreadManager::Get()->GetBluetoothGattServiceClient()); - gatt_service_client->HideHeartRateService(); - } - - callback.Run(); - properties->connected.ReplaceValue(false); -} - -void FakeBluetoothDeviceClient::ConnectProfile( - const dbus::ObjectPath& object_path, - const std::string& uuid, - const base::Closure& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "ConnectProfile: " << object_path.value() << " " << uuid; - - FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = - static_cast<FakeBluetoothProfileManagerClient*>( - DBusThreadManager::Get()->GetBluetoothProfileManagerClient()); - FakeBluetoothProfileServiceProvider* profile_service_provider = - fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid); - if (profile_service_provider == NULL) { - error_callback.Run(kNoResponseError, "Missing profile"); - return; - } - - if (object_path == dbus::ObjectPath(kPairedUnconnectableDevicePath)) { - error_callback.Run(bluetooth_device::kErrorFailed, "unconnectable"); - return; - } - - // Make a socket pair of a compatible type with the type used by Bluetooth; - // spin up a thread to simulate the server side and wrap the client side in - // a D-Bus file descriptor object. - int socket_type = SOCK_STREAM; - if (uuid == FakeBluetoothProfileManagerClient::kL2capUuid) - socket_type = SOCK_SEQPACKET; - - int fds[2]; - if (socketpair(AF_UNIX, socket_type, 0, fds) < 0) { - error_callback.Run(kNoResponseError, "socketpair call failed"); - return; - } - - int args; - args = fcntl(fds[1], F_GETFL, NULL); - if (args < 0) { - error_callback.Run(kNoResponseError, "failed to get socket flags"); - return; - } - - args |= O_NONBLOCK; - if (fcntl(fds[1], F_SETFL, args) < 0) { - error_callback.Run(kNoResponseError, "failed to set socket non-blocking"); - return; - } - - base::WorkerPool::GetTaskRunner(false) - ->PostTask(FROM_HERE, base::Bind(&SimulatedProfileSocket, fds[0])); - - scoped_ptr<dbus::FileDescriptor> fd(new dbus::FileDescriptor(fds[1])); - - // Post the new connection to the service provider. - BluetoothProfileServiceProvider::Delegate::Options options; - - profile_service_provider->NewConnection( - object_path, fd.Pass(), options, - base::Bind(&FakeBluetoothDeviceClient::ConnectionCallback, - base::Unretained(this), object_path, callback, - error_callback)); -} - -void FakeBluetoothDeviceClient::DisconnectProfile( - const dbus::ObjectPath& object_path, - const std::string& uuid, - const base::Closure& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "DisconnectProfile: " << object_path.value() << " " << uuid; - - FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = - static_cast<FakeBluetoothProfileManagerClient*>( - DBusThreadManager::Get()->GetBluetoothProfileManagerClient()); - FakeBluetoothProfileServiceProvider* profile_service_provider = - fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid); - if (profile_service_provider == NULL) { - error_callback.Run(kNoResponseError, "Missing profile"); - return; - } - - profile_service_provider->RequestDisconnection( - object_path, base::Bind(&FakeBluetoothDeviceClient::DisconnectionCallback, - base::Unretained(this), object_path, callback, - error_callback)); -} - -void FakeBluetoothDeviceClient::Pair(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "Pair: " << object_path.value(); - Properties* properties = GetProperties(object_path); - - if (properties->paired.value() == true) { - // Already paired. - callback.Run(); - return; - } - - SimulatePairing(object_path, false, callback, error_callback); -} - -void FakeBluetoothDeviceClient::CancelPairing( - const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "CancelPairing: " << object_path.value(); - pairing_cancelled_ = true; - callback.Run(); -} - -void FakeBluetoothDeviceClient::GetConnInfo( - const dbus::ObjectPath& object_path, - const ConnInfoCallback& callback, - const ErrorCallback& error_callback) { - Properties* properties = GetProperties(object_path); - if (!properties->connected.value()) { - error_callback.Run("org.bluez.Error.NotConnected", "Not Connected"); - return; - } - - callback.Run(connection_rssi_, transmit_power_, max_transmit_power_); -} - -void FakeBluetoothDeviceClient::BeginDiscoverySimulation( - const dbus::ObjectPath& adapter_path) { - VLOG(1) << "starting discovery simulation"; - - discovery_simulation_step_ = 1; - - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer, - base::Unretained(this)), - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); -} - -void FakeBluetoothDeviceClient::EndDiscoverySimulation( - const dbus::ObjectPath& adapter_path) { - VLOG(1) << "stopping discovery simulation"; - discovery_simulation_step_ = 0; -} - -void FakeBluetoothDeviceClient::BeginIncomingPairingSimulation( - const dbus::ObjectPath& adapter_path) { - VLOG(1) << "starting incoming pairing simulation"; - - incoming_pairing_simulation_step_ = 1; - - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::IncomingPairingSimulationTimer, - base::Unretained(this)), - base::TimeDelta::FromMilliseconds( - kIncomingSimulationStartPairTimeMultiplier * - simulation_interval_ms_)); -} - -void FakeBluetoothDeviceClient::EndIncomingPairingSimulation( - const dbus::ObjectPath& adapter_path) { - VLOG(1) << "stopping incoming pairing simulation"; - incoming_pairing_simulation_step_ = 0; -} - -void FakeBluetoothDeviceClient::SetSimulationIntervalMs(int interval_ms) { - simulation_interval_ms_ = interval_ms; -} - -void FakeBluetoothDeviceClient::CreateDevice( - const dbus::ObjectPath& adapter_path, - const dbus::ObjectPath& device_path) { - if (std::find(device_list_.begin(), device_list_.end(), device_path) != - device_list_.end()) - return; - - scoped_ptr<Properties> properties( - new Properties(base::Bind(&FakeBluetoothDeviceClient::OnPropertyChanged, - base::Unretained(this), device_path))); - properties->adapter.ReplaceValue(adapter_path); - - if (device_path == dbus::ObjectPath(kLegacyAutopairPath)) { - properties->address.ReplaceValue(kLegacyAutopairAddress); - properties->bluetooth_class.ReplaceValue(kLegacyAutopairClass); - properties->name.ReplaceValue("LegacyAutopair"); - properties->alias.ReplaceValue(kLegacyAutopairName); - - std::vector<std::string> uuids; - uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); - properties->uuids.ReplaceValue(uuids); - - } else if (device_path == dbus::ObjectPath(kDisplayPinCodePath)) { - properties->address.ReplaceValue(kDisplayPinCodeAddress); - properties->bluetooth_class.ReplaceValue(kDisplayPinCodeClass); - properties->name.ReplaceValue("DisplayPinCode"); - properties->alias.ReplaceValue(kDisplayPinCodeName); - - std::vector<std::string> uuids; - uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); - properties->uuids.ReplaceValue(uuids); - - } else if (device_path == dbus::ObjectPath(kVanishingDevicePath)) { - properties->address.ReplaceValue(kVanishingDeviceAddress); - properties->bluetooth_class.ReplaceValue(kVanishingDeviceClass); - properties->name.ReplaceValue("VanishingDevice"); - properties->alias.ReplaceValue(kVanishingDeviceName); - - } else if (device_path == dbus::ObjectPath(kConnectUnpairablePath)) { - properties->address.ReplaceValue(kConnectUnpairableAddress); - properties->bluetooth_class.ReplaceValue(kConnectUnpairableClass); - properties->name.ReplaceValue("ConnectUnpairable"); - properties->alias.ReplaceValue(kConnectUnpairableName); - - std::vector<std::string> uuids; - uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); - properties->uuids.ReplaceValue(uuids); - - } else if (device_path == dbus::ObjectPath(kDisplayPasskeyPath)) { - properties->address.ReplaceValue(kDisplayPasskeyAddress); - properties->bluetooth_class.ReplaceValue(kDisplayPasskeyClass); - properties->name.ReplaceValue("DisplayPasskey"); - properties->alias.ReplaceValue(kDisplayPasskeyName); - - std::vector<std::string> uuids; - uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); - properties->uuids.ReplaceValue(uuids); - - } else if (device_path == dbus::ObjectPath(kRequestPinCodePath)) { - properties->address.ReplaceValue(kRequestPinCodeAddress); - properties->bluetooth_class.ReplaceValue(kRequestPinCodeClass); - properties->name.ReplaceValue("RequestPinCode"); - properties->alias.ReplaceValue(kRequestPinCodeName); - - } else if (device_path == dbus::ObjectPath(kConfirmPasskeyPath)) { - properties->address.ReplaceValue(kConfirmPasskeyAddress); - properties->bluetooth_class.ReplaceValue(kConfirmPasskeyClass); - properties->name.ReplaceValue("ConfirmPasskey"); - properties->alias.ReplaceValue(kConfirmPasskeyName); - - } else if (device_path == dbus::ObjectPath(kRequestPasskeyPath)) { - properties->address.ReplaceValue(kRequestPasskeyAddress); - properties->bluetooth_class.ReplaceValue(kRequestPasskeyClass); - properties->name.ReplaceValue("RequestPasskey"); - properties->alias.ReplaceValue(kRequestPasskeyName); - - } else if (device_path == dbus::ObjectPath(kUnconnectableDevicePath)) { - properties->address.ReplaceValue(kUnconnectableDeviceAddress); - properties->bluetooth_class.ReplaceValue(kUnconnectableDeviceClass); - properties->name.ReplaceValue("UnconnectableDevice"); - properties->alias.ReplaceValue(kUnconnectableDeviceName); - - } else if (device_path == dbus::ObjectPath(kUnpairableDevicePath)) { - properties->address.ReplaceValue(kUnpairableDeviceAddress); - properties->bluetooth_class.ReplaceValue(kUnpairableDeviceClass); - properties->name.ReplaceValue("Fake Unpairable Device"); - properties->alias.ReplaceValue(kUnpairableDeviceName); - - } else if (device_path == dbus::ObjectPath(kJustWorksPath)) { - properties->address.ReplaceValue(kJustWorksAddress); - properties->bluetooth_class.ReplaceValue(kJustWorksClass); - properties->name.ReplaceValue("JustWorks"); - properties->alias.ReplaceValue(kJustWorksName); - - } else if (device_path == dbus::ObjectPath(kLowEnergyPath)) { - properties->address.ReplaceValue(kLowEnergyAddress); - properties->bluetooth_class.ReplaceValue(kLowEnergyClass); - properties->name.ReplaceValue("Heart Rate Monitor"); - properties->alias.ReplaceValue(kLowEnergyName); - - std::vector<std::string> uuids; - uuids.push_back(FakeBluetoothGattServiceClient::kHeartRateServiceUUID); - properties->uuids.ReplaceValue(uuids); - } else if (device_path == - dbus::ObjectPath(kConnectedTrustedNotPairedDevicePath)) { - properties->address.ReplaceValue(kConnectedTrustedNotPairedDeviceAddress); - properties->bluetooth_class.ReplaceValue( - kConnectedTrustedNotPairedDeviceClass); - properties->trusted.ReplaceValue(true); - properties->connected.ReplaceValue(true); - properties->paired.ReplaceValue(false); - properties->name.ReplaceValue("Connected Pairable Device"); - properties->alias.ReplaceValue(kConnectedTrustedNotPairedDeviceName); - } else { - NOTREACHED(); - } - - properties_map_.insert(device_path, properties.Pass()); - device_list_.push_back(device_path); - FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, - DeviceAdded(device_path)); -} - -void FakeBluetoothDeviceClient::CreateDeviceWithProperties( - const dbus::ObjectPath& adapter_path, - const IncomingDeviceProperties& props) { - dbus::ObjectPath device_path(props.device_path); - if (std::find(device_list_.begin(), device_list_.end(), device_path) != - device_list_.end()) - return; - - scoped_ptr<Properties> properties( - new Properties(base::Bind(&FakeBluetoothDeviceClient::OnPropertyChanged, - base::Unretained(this), device_path))); - properties->adapter.ReplaceValue(adapter_path); - properties->name.ReplaceValue(props.device_name); - properties->alias.ReplaceValue(props.device_alias); - properties->address.ReplaceValue(props.device_address); - properties->bluetooth_class.ReplaceValue(props.device_class); - properties->trusted.ReplaceValue(props.is_trusted); - - if (props.is_trusted) - properties->paired.ReplaceValue(true); - - scoped_ptr<SimulatedPairingOptions> options(new SimulatedPairingOptions); - options->pairing_method = props.pairing_method; - options->pairing_auth_token = props.pairing_auth_token; - options->pairing_action = props.pairing_action; - options->incoming = props.incoming; - - properties_map_.insert(device_path, properties.Pass()); - device_list_.push_back(device_path); - pairing_options_map_.insert(device_path, options.Pass()); - FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, - DeviceAdded(device_path)); -} - -scoped_ptr<base::ListValue> -FakeBluetoothDeviceClient::GetBluetoothDevicesAsDictionaries() const { - scoped_ptr<base::ListValue> predefined_devices(new base::ListValue); - scoped_ptr<base::DictionaryValue> pairedDevice(new base::DictionaryValue); - pairedDevice->SetString("path", kPairedDevicePath); - pairedDevice->SetString("address", kPairedDeviceAddress); - pairedDevice->SetString("name", kPairedDeviceName); - pairedDevice->SetString("alias", kPairedDeviceName); - pairedDevice->SetString("pairingMethod", ""); - pairedDevice->SetString("pairingAuthToken", ""); - pairedDevice->SetString("pairingAction", ""); - pairedDevice->SetInteger("classValue", kPairedDeviceClass); - pairedDevice->SetBoolean("discoverable", true); - pairedDevice->SetBoolean("isTrusted", true); - pairedDevice->SetBoolean("paired", true); - pairedDevice->SetBoolean("incoming", false); - predefined_devices->Append(pairedDevice.Pass()); - - scoped_ptr<base::DictionaryValue> legacyDevice(new base::DictionaryValue); - legacyDevice->SetString("path", kLegacyAutopairPath); - legacyDevice->SetString("address", kLegacyAutopairAddress); - legacyDevice->SetString("name", kLegacyAutopairName); - legacyDevice->SetString("alias", kLegacyAutopairName); - legacyDevice->SetString("pairingMethod", ""); - legacyDevice->SetString("pairingAuthToken", ""); - legacyDevice->SetString("pairingAction", ""); - legacyDevice->SetInteger("classValue", kLegacyAutopairClass); - legacyDevice->SetBoolean("isTrusted", true); - legacyDevice->SetBoolean("discoverable", false); - legacyDevice->SetBoolean("paired", false); - legacyDevice->SetBoolean("incoming", false); - predefined_devices->Append(legacyDevice.Pass()); - - scoped_ptr<base::DictionaryValue> pin(new base::DictionaryValue); - pin->SetString("path", kDisplayPinCodePath); - pin->SetString("address", kDisplayPinCodeAddress); - pin->SetString("name", kDisplayPinCodeName); - pin->SetString("alias", kDisplayPinCodeName); - pin->SetString("pairingMethod", kPairingMethodPinCode); - pin->SetString("pairingAuthToken", kTestPinCode); - pin->SetString("pairingAction", kPairingActionDisplay); - pin->SetInteger("classValue", kDisplayPinCodeClass); - pin->SetBoolean("isTrusted", false); - pin->SetBoolean("discoverable", false); - pin->SetBoolean("paired", false); - pin->SetBoolean("incoming", false); - predefined_devices->Append(pin.Pass()); - - scoped_ptr<base::DictionaryValue> vanishing(new base::DictionaryValue); - vanishing->SetString("path", kVanishingDevicePath); - vanishing->SetString("address", kVanishingDeviceAddress); - vanishing->SetString("name", kVanishingDeviceName); - vanishing->SetString("alias", kVanishingDeviceName); - vanishing->SetString("pairingMethod", ""); - vanishing->SetString("pairingAuthToken", ""); - vanishing->SetString("pairingAction", ""); - vanishing->SetInteger("classValue", kVanishingDeviceClass); - vanishing->SetBoolean("isTrusted", false); - vanishing->SetBoolean("discoverable", false); - vanishing->SetBoolean("paired", false); - vanishing->SetBoolean("incoming", false); - predefined_devices->Append(vanishing.Pass()); - - scoped_ptr<base::DictionaryValue> connect_unpairable( - new base::DictionaryValue); - connect_unpairable->SetString("path", kConnectUnpairablePath); - connect_unpairable->SetString("address", kConnectUnpairableAddress); - connect_unpairable->SetString("name", kConnectUnpairableName); - connect_unpairable->SetString("pairingMethod", ""); - connect_unpairable->SetString("pairingAuthToken", ""); - connect_unpairable->SetString("pairingAction", ""); - connect_unpairable->SetString("alias", kConnectUnpairableName); - connect_unpairable->SetInteger("classValue", kConnectUnpairableClass); - connect_unpairable->SetBoolean("isTrusted", false); - connect_unpairable->SetBoolean("discoverable", false); - connect_unpairable->SetBoolean("paired", false); - connect_unpairable->SetBoolean("incoming", false); - predefined_devices->Append(connect_unpairable.Pass()); - - scoped_ptr<base::DictionaryValue> passkey(new base::DictionaryValue); - passkey->SetString("path", kDisplayPasskeyPath); - passkey->SetString("address", kDisplayPasskeyAddress); - passkey->SetString("name", kDisplayPasskeyName); - passkey->SetString("alias", kDisplayPasskeyName); - passkey->SetString("pairingMethod", kPairingMethodPassKey); - passkey->SetInteger("pairingAuthToken", kTestPassKey); - passkey->SetString("pairingAction", kPairingActionDisplay); - passkey->SetInteger("classValue", kDisplayPasskeyClass); - passkey->SetBoolean("isTrusted", false); - passkey->SetBoolean("discoverable", false); - passkey->SetBoolean("paired", false); - passkey->SetBoolean("incoming", false); - predefined_devices->Append(passkey.Pass()); - - scoped_ptr<base::DictionaryValue> request_pin(new base::DictionaryValue); - request_pin->SetString("path", kRequestPinCodePath); - request_pin->SetString("address", kRequestPinCodeAddress); - request_pin->SetString("name", kRequestPinCodeName); - request_pin->SetString("alias", kRequestPinCodeName); - request_pin->SetString("pairingMethod", ""); - request_pin->SetString("pairingAuthToken", ""); - request_pin->SetString("pairingAction", kPairingActionRequest); - request_pin->SetInteger("classValue", kRequestPinCodeClass); - request_pin->SetBoolean("isTrusted", false); - request_pin->SetBoolean("discoverable", false); - request_pin->SetBoolean("paired", false); - request_pin->SetBoolean("incoming", false); - predefined_devices->Append(request_pin.Pass()); - - scoped_ptr<base::DictionaryValue> confirm(new base::DictionaryValue); - confirm->SetString("path", kConfirmPasskeyPath); - confirm->SetString("address", kConfirmPasskeyAddress); - confirm->SetString("name", kConfirmPasskeyName); - confirm->SetString("alias", kConfirmPasskeyName); - confirm->SetString("pairingMethod", ""); - confirm->SetInteger("pairingAuthToken", kTestPassKey); - confirm->SetString("pairingAction", kPairingActionConfirmation); - confirm->SetInteger("classValue", kConfirmPasskeyClass); - confirm->SetBoolean("isTrusted", false); - confirm->SetBoolean("discoverable", false); - confirm->SetBoolean("paired", false); - confirm->SetBoolean("incoming", false); - predefined_devices->Append(confirm.Pass()); - - scoped_ptr<base::DictionaryValue> request_passkey(new base::DictionaryValue); - request_passkey->SetString("path", kRequestPasskeyPath); - request_passkey->SetString("address", kRequestPasskeyAddress); - request_passkey->SetString("name", kRequestPasskeyName); - request_passkey->SetString("alias", kRequestPasskeyName); - request_passkey->SetString("pairingMethod", kPairingMethodPassKey); - request_passkey->SetString("pairingAction", kPairingActionRequest); - request_passkey->SetInteger("pairingAuthToken", kTestPassKey); - request_passkey->SetInteger("classValue", kRequestPasskeyClass); - request_passkey->SetBoolean("isTrusted", false); - request_passkey->SetBoolean("discoverable", false); - request_passkey->SetBoolean("paired", false); - request_passkey->SetBoolean("incoming", false); - predefined_devices->Append(request_passkey.Pass()); - - scoped_ptr<base::DictionaryValue> unconnectable(new base::DictionaryValue); - unconnectable->SetString("path", kUnconnectableDevicePath); - unconnectable->SetString("address", kUnconnectableDeviceAddress); - unconnectable->SetString("name", kUnconnectableDeviceName); - unconnectable->SetString("alias", kUnconnectableDeviceName); - unconnectable->SetString("pairingMethod", ""); - unconnectable->SetString("pairingAuthToken", ""); - unconnectable->SetString("pairingAction", ""); - unconnectable->SetInteger("classValue", kUnconnectableDeviceClass); - unconnectable->SetBoolean("isTrusted", true); - unconnectable->SetBoolean("discoverable", false); - unconnectable->SetBoolean("paired", false); - unconnectable->SetBoolean("incoming", false); - predefined_devices->Append(unconnectable.Pass()); - - scoped_ptr<base::DictionaryValue> unpairable(new base::DictionaryValue); - unpairable->SetString("path", kUnpairableDevicePath); - unpairable->SetString("address", kUnpairableDeviceAddress); - unpairable->SetString("name", kUnpairableDeviceName); - unpairable->SetString("alias", kUnpairableDeviceName); - unpairable->SetString("pairingMethod", ""); - unpairable->SetString("pairingAuthToken", ""); - unpairable->SetString("pairingAction", kPairingActionFail); - unpairable->SetInteger("classValue", kUnpairableDeviceClass); - unpairable->SetBoolean("isTrusted", false); - unpairable->SetBoolean("discoverable", false); - unpairable->SetBoolean("paired", false); - unpairable->SetBoolean("incoming", false); - predefined_devices->Append(unpairable.Pass()); - - scoped_ptr<base::DictionaryValue> just_works(new base::DictionaryValue); - just_works->SetString("path", kJustWorksPath); - just_works->SetString("address", kJustWorksAddress); - just_works->SetString("name", kJustWorksName); - just_works->SetString("alias", kJustWorksName); - just_works->SetString("pairingMethod", ""); - just_works->SetString("pairingAuthToken", ""); - just_works->SetString("pairingAction", ""); - just_works->SetInteger("classValue", kJustWorksClass); - just_works->SetBoolean("isTrusted", false); - just_works->SetBoolean("discoverable", false); - just_works->SetBoolean("paired", false); - just_works->SetBoolean("incoming", false); - predefined_devices->Append(just_works.Pass()); - - scoped_ptr<base::DictionaryValue> low_energy(new base::DictionaryValue); - low_energy->SetString("path", kLowEnergyPath); - low_energy->SetString("address", kLowEnergyAddress); - low_energy->SetString("name", kLowEnergyName); - low_energy->SetString("alias", kLowEnergyName); - low_energy->SetString("pairingMethod", ""); - low_energy->SetString("pairingAuthToken", ""); - low_energy->SetString("pairingAction", ""); - low_energy->SetInteger("classValue", kLowEnergyClass); - low_energy->SetBoolean("isTrusted", false); - low_energy->SetBoolean("discoverable", false); - low_energy->SetBoolean("paireed", false); - low_energy->SetBoolean("incoming", false); - predefined_devices->Append(low_energy.Pass()); - - scoped_ptr<base::DictionaryValue> paired_unconnectable( - new base::DictionaryValue); - paired_unconnectable->SetString("path", kPairedUnconnectableDevicePath); - paired_unconnectable->SetString("address", kPairedUnconnectableDeviceAddress); - paired_unconnectable->SetString("name", kPairedUnconnectableDeviceName); - paired_unconnectable->SetString("pairingMethod", ""); - paired_unconnectable->SetString("pairingAuthToken", ""); - paired_unconnectable->SetString("pairingAction", ""); - paired_unconnectable->SetString("alias", kPairedUnconnectableDeviceName); - paired_unconnectable->SetInteger("classValue", - kPairedUnconnectableDeviceClass); - paired_unconnectable->SetBoolean("isTrusted", false); - paired_unconnectable->SetBoolean("discoverable", true); - paired_unconnectable->SetBoolean("paired", true); - paired_unconnectable->SetBoolean("incoming", false); - predefined_devices->Append(paired_unconnectable.Pass()); - - scoped_ptr<base::DictionaryValue> connected_trusted_not_paired( - new base::DictionaryValue); - connected_trusted_not_paired->SetString("path", - kConnectedTrustedNotPairedDevicePath); - connected_trusted_not_paired->SetString( - "address", kConnectedTrustedNotPairedDeviceAddress); - connected_trusted_not_paired->SetString("name", - kConnectedTrustedNotPairedDeviceName); - connected_trusted_not_paired->SetString("pairingMethod", ""); - connected_trusted_not_paired->SetString("pairingAuthToken", ""); - connected_trusted_not_paired->SetString("pairingAction", ""); - connected_trusted_not_paired->SetString("alias", - kConnectedTrustedNotPairedDeviceName); - connected_trusted_not_paired->SetInteger( - "classValue", kConnectedTrustedNotPairedDeviceClass); - connected_trusted_not_paired->SetBoolean("isTrusted", true); - connected_trusted_not_paired->SetBoolean("discoverable", true); - connected_trusted_not_paired->SetBoolean("paired", false); - connected_trusted_not_paired->SetBoolean("incoming", false); - predefined_devices->Append(connected_trusted_not_paired.Pass()); - - return predefined_devices.Pass(); -} - -void FakeBluetoothDeviceClient::RemoveDevice( - const dbus::ObjectPath& adapter_path, - const dbus::ObjectPath& device_path) { - std::vector<dbus::ObjectPath>::iterator listiter = - std::find(device_list_.begin(), device_list_.end(), device_path); - if (listiter == device_list_.end()) - return; - - PropertiesMap::const_iterator iter = properties_map_.find(device_path); - Properties* properties = iter->second; - - VLOG(1) << "removing device: " << properties->alias.value(); - device_list_.erase(listiter); - - // Remove the Input interface if it exists. This should be called before the - // BluetoothDeviceClient::Observer::DeviceRemoved because it deletes the - // BluetoothDeviceChromeOS object, including the device_path referenced here. - FakeBluetoothInputClient* fake_bluetooth_input_client = - static_cast<FakeBluetoothInputClient*>( - DBusThreadManager::Get()->GetBluetoothInputClient()); - fake_bluetooth_input_client->RemoveInputDevice(device_path); - - if (device_path == dbus::ObjectPath(kLowEnergyPath)) { - FakeBluetoothGattServiceClient* gatt_service_client = - static_cast<FakeBluetoothGattServiceClient*>( - DBusThreadManager::Get()->GetBluetoothGattServiceClient()); - gatt_service_client->HideHeartRateService(); - } - - FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, - DeviceRemoved(device_path)); - - properties_map_.erase(iter); - PairingOptionsMap::const_iterator options_iter = - pairing_options_map_.find(device_path); - - if (options_iter != pairing_options_map_.end()) { - pairing_options_map_.erase(options_iter); - } -} - -void FakeBluetoothDeviceClient::OnPropertyChanged( - const dbus::ObjectPath& object_path, - const std::string& property_name) { - VLOG(2) << "Fake Bluetooth device property changed: " << object_path.value() - << ": " << property_name; - FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, - DevicePropertyChanged(object_path, property_name)); -} - -void FakeBluetoothDeviceClient::DiscoverySimulationTimer() { - if (!discovery_simulation_step_) - return; - - // Timer fires every .75s, the numbers below are arbitrary to give a feel - // for a discovery process. - VLOG(1) << "discovery simulation, step " << discovery_simulation_step_; - if (discovery_simulation_step_ == 2) { - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kLegacyAutopairPath)); - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kLowEnergyPath)); - - } else if (discovery_simulation_step_ == 4) { - UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), - base::RandInt(kMinRSSI, kMaxRSSI)); - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kDisplayPinCodePath)); - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kVanishingDevicePath)); - - } else if (discovery_simulation_step_ == 7) { - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kConnectUnpairablePath)); - UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), - base::RandInt(kMinRSSI, kMaxRSSI)); - - } else if (discovery_simulation_step_ == 8) { - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kDisplayPasskeyPath)); - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kRequestPinCodePath)); - UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), - base::RandInt(kMinRSSI, kMaxRSSI)); - - } else if (discovery_simulation_step_ == 10) { - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kConfirmPasskeyPath)); - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kRequestPasskeyPath)); - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kUnconnectableDevicePath)); - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kUnpairableDevicePath)); - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kJustWorksPath)); - UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), - base::RandInt(kMinRSSI, kMaxRSSI)); - - } else if (discovery_simulation_step_ == 13) { - UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), - base::RandInt(kMinRSSI, kMaxRSSI)); - RemoveDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kVanishingDevicePath)); - } else if (discovery_simulation_step_ == 14) { - UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), - base::RandInt(kMinRSSI, kMaxRSSI)); - return; - } - - ++discovery_simulation_step_; - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer, - base::Unretained(this)), - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); -} - -void FakeBluetoothDeviceClient::IncomingPairingSimulationTimer() { - if (!incoming_pairing_simulation_step_) - return; - - VLOG(1) << "incoming pairing simulation, step " - << incoming_pairing_simulation_step_; - switch (incoming_pairing_simulation_step_) { - case 1: - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kConfirmPasskeyPath)); - SimulatePairing(dbus::ObjectPath(kConfirmPasskeyPath), true, - base::Bind(&base::DoNothing), - base::Bind(&SimpleErrorCallback)); - break; - case 2: - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kJustWorksPath)); - SimulatePairing(dbus::ObjectPath(kJustWorksPath), true, - base::Bind(&base::DoNothing), - base::Bind(&SimpleErrorCallback)); - break; - case 3: - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kDisplayPinCodePath)); - SimulatePairing(dbus::ObjectPath(kDisplayPinCodePath), true, - base::Bind(&base::DoNothing), - base::Bind(&SimpleErrorCallback)); - break; - case 4: - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kDisplayPasskeyPath)); - SimulatePairing(dbus::ObjectPath(kDisplayPasskeyPath), true, - base::Bind(&base::DoNothing), - base::Bind(&SimpleErrorCallback)); - break; - case 5: - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kRequestPinCodePath)); - SimulatePairing(dbus::ObjectPath(kRequestPinCodePath), true, - base::Bind(&base::DoNothing), - base::Bind(&SimpleErrorCallback)); - break; - case 6: - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kRequestPasskeyPath)); - SimulatePairing(dbus::ObjectPath(kRequestPasskeyPath), true, - base::Bind(&base::DoNothing), - base::Bind(&SimpleErrorCallback)); - break; - default: - return; - } - - ++incoming_pairing_simulation_step_; - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::IncomingPairingSimulationTimer, - base::Unretained(this)), - base::TimeDelta::FromMilliseconds(kIncomingSimulationPairTimeMultiplier * - simulation_interval_ms_)); -} - -void FakeBluetoothDeviceClient::SimulatePairing( - const dbus::ObjectPath& object_path, - bool incoming_request, - const base::Closure& callback, - const ErrorCallback& error_callback) { - pairing_cancelled_ = false; - - FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client = - static_cast<FakeBluetoothAgentManagerClient*>( - DBusThreadManager::Get()->GetBluetoothAgentManagerClient()); - FakeBluetoothAgentServiceProvider* agent_service_provider = - fake_bluetooth_agent_manager_client->GetAgentServiceProvider(); - CHECK(agent_service_provider != NULL); - - // Grab the device's pairing properties. - PairingOptionsMap::const_iterator iter = - pairing_options_map_.find(object_path); - - // If the device with path |object_path| has simulated pairing properties - // defined, then pair it based on its |pairing_method|. - if (iter != pairing_options_map_.end()) { - if (iter->second->pairing_action == kPairingActionFail) { - // Fails the pairing with an org.bluez.Error.Failed error. - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::FailSimulatedPairing, - base::Unretained(this), object_path, error_callback), - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); - } else if (iter->second->pairing_method == kPairingMethodNone || - iter->second->pairing_method.empty()) { - if (!iter->second->incoming) { - // Simply pair and connect the device. - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, - base::Unretained(this), object_path, callback, - error_callback), - base::TimeDelta::FromMilliseconds( - kSimulateNormalPairTimeMultiplier * simulation_interval_ms_)); - } else { - agent_service_provider->RequestAuthorization( - object_path, - base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback, - base::Unretained(this), object_path, callback, - error_callback)); - } - } else if (iter->second->pairing_method == kPairingMethodPinCode) { - if (iter->second->pairing_action == kPairingActionDisplay) { - // Display a Pincode, and wait before acting as if the other end - // accepted it. - agent_service_provider->DisplayPinCode( - object_path, iter->second->pairing_auth_token); - - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, - base::Unretained(this), object_path, callback, - error_callback), - base::TimeDelta::FromMilliseconds(kPinCodeDevicePairTimeMultiplier * - simulation_interval_ms_)); - } else if (iter->second->pairing_action == kPairingActionRequest) { - // Request a pin code. - agent_service_provider->RequestPinCode( - object_path, base::Bind(&FakeBluetoothDeviceClient::PinCodeCallback, - base::Unretained(this), object_path, - callback, error_callback)); - } else if (iter->second->pairing_action == kPairingActionConfirmation) { - error_callback.Run(kNoResponseError, "No confirm for pincode pairing."); - } - } else if (iter->second->pairing_method == kPairingMethodPassKey) { - // Display a passkey, and each interval act as if another key was entered - // for it. - if (iter->second->pairing_action == kPairingActionDisplay) { - agent_service_provider->DisplayPasskey( - object_path, std::stoi(iter->second->pairing_auth_token), 0); - - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress, - base::Unretained(this), 1, object_path, - callback, error_callback), - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); - } else if (iter->second->pairing_action == kPairingActionRequest) { - agent_service_provider->RequestPasskey( - object_path, base::Bind(&FakeBluetoothDeviceClient::PasskeyCallback, - base::Unretained(this), object_path, - callback, error_callback)); - } else if (iter->second->pairing_action == kPairingActionConfirmation) { - agent_service_provider->RequestConfirmation( - object_path, std::stoi(iter->second->pairing_auth_token), - base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback, - base::Unretained(this), object_path, callback, - error_callback)); - } - } - } else { - if (object_path == dbus::ObjectPath(kLegacyAutopairPath) || - object_path == dbus::ObjectPath(kConnectUnpairablePath) || - object_path == dbus::ObjectPath(kUnconnectableDevicePath) || - object_path == dbus::ObjectPath(kLowEnergyPath)) { - // No need to call anything on the pairing delegate, just wait 3 times - // the interval before acting as if the other end accepted it. - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, - base::Unretained(this), object_path, callback, - error_callback), - base::TimeDelta::FromMilliseconds(kSimulateNormalPairTimeMultiplier * - simulation_interval_ms_)); - - } else if (object_path == dbus::ObjectPath(kDisplayPinCodePath)) { - // Display a Pincode, and wait before acting as if the other end accepted - // it. - agent_service_provider->DisplayPinCode(object_path, kTestPinCode); - - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, - base::Unretained(this), object_path, callback, - error_callback), - base::TimeDelta::FromMilliseconds(kPinCodeDevicePairTimeMultiplier * - simulation_interval_ms_)); - - } else if (object_path == dbus::ObjectPath(kVanishingDevicePath)) { - // The vanishing device simulates being too far away, and thus times out. - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::TimeoutSimulatedPairing, - base::Unretained(this), object_path, error_callback), - base::TimeDelta::FromMilliseconds(kVanishingDevicePairTimeMultiplier * - simulation_interval_ms_)); - - } else if (object_path == dbus::ObjectPath(kDisplayPasskeyPath)) { - // Display a passkey, and each interval act as if another key was entered - // for it. - agent_service_provider->DisplayPasskey(object_path, kTestPassKey, 0); - - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress, - base::Unretained(this), 1, object_path, - callback, error_callback), - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); - - } else if (object_path == dbus::ObjectPath(kRequestPinCodePath)) { - // Request a Pincode. - agent_service_provider->RequestPinCode( - object_path, base::Bind(&FakeBluetoothDeviceClient::PinCodeCallback, - base::Unretained(this), object_path, callback, - error_callback)); - - } else if (object_path == dbus::ObjectPath(kConfirmPasskeyPath) || - object_path == - dbus::ObjectPath(kConnectedTrustedNotPairedDevicePath)) { - // Request confirmation of a Passkey. - agent_service_provider->RequestConfirmation( - object_path, kTestPassKey, - base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback, - base::Unretained(this), object_path, callback, - error_callback)); - - } else if (object_path == dbus::ObjectPath(kRequestPasskeyPath)) { - // Request a Passkey from the user. - agent_service_provider->RequestPasskey( - object_path, base::Bind(&FakeBluetoothDeviceClient::PasskeyCallback, - base::Unretained(this), object_path, callback, - error_callback)); - - } else if (object_path == dbus::ObjectPath(kUnpairableDevicePath)) { - // Fails the pairing with an org.bluez.Error.Failed error. - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::FailSimulatedPairing, - base::Unretained(this), object_path, error_callback), - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); - - } else if (object_path == dbus::ObjectPath(kJustWorksPath)) { - if (incoming_request) { - agent_service_provider->RequestAuthorization( - object_path, - base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback, - base::Unretained(this), object_path, callback, - error_callback)); - - } else { - // No need to call anything on the pairing delegate, just wait before - // acting as if the other end accepted it. - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, - base::Unretained(this), object_path, callback, - error_callback), - base::TimeDelta::FromMilliseconds( - kSimulateNormalPairTimeMultiplier * simulation_interval_ms_)); - } - - } else { - error_callback.Run(kNoResponseError, "No pairing fake"); - } - } -} - -void FakeBluetoothDeviceClient::CompleteSimulatedPairing( - const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "CompleteSimulatedPairing: " << object_path.value(); - if (pairing_cancelled_) { - pairing_cancelled_ = false; - - error_callback.Run(bluetooth_device::kErrorAuthenticationCanceled, - "Cancelled"); - } else { - Properties* properties = GetProperties(object_path); - - properties->paired.ReplaceValue(true); - callback.Run(); - - AddInputDeviceIfNeeded(object_path, properties); - } -} - -void FakeBluetoothDeviceClient::TimeoutSimulatedPairing( - const dbus::ObjectPath& object_path, - const ErrorCallback& error_callback) { - VLOG(1) << "TimeoutSimulatedPairing: " << object_path.value(); - - error_callback.Run(bluetooth_device::kErrorAuthenticationTimeout, - "Timed out"); -} - -void FakeBluetoothDeviceClient::CancelSimulatedPairing( - const dbus::ObjectPath& object_path, - const ErrorCallback& error_callback) { - VLOG(1) << "CancelSimulatedPairing: " << object_path.value(); - - error_callback.Run(bluetooth_device::kErrorAuthenticationCanceled, - "Canceled"); -} - -void FakeBluetoothDeviceClient::RejectSimulatedPairing( - const dbus::ObjectPath& object_path, - const ErrorCallback& error_callback) { - VLOG(1) << "RejectSimulatedPairing: " << object_path.value(); - - error_callback.Run(bluetooth_device::kErrorAuthenticationRejected, - "Rejected"); -} - -void FakeBluetoothDeviceClient::FailSimulatedPairing( - const dbus::ObjectPath& object_path, - const ErrorCallback& error_callback) { - VLOG(1) << "FailSimulatedPairing: " << object_path.value(); - - error_callback.Run(bluetooth_device::kErrorFailed, "Failed"); -} - -void FakeBluetoothDeviceClient::AddInputDeviceIfNeeded( - const dbus::ObjectPath& object_path, - Properties* properties) { - // If the paired device is a HID device based on it's bluetooth class, - // simulate the Input interface. - FakeBluetoothInputClient* fake_bluetooth_input_client = - static_cast<FakeBluetoothInputClient*>( - DBusThreadManager::Get()->GetBluetoothInputClient()); - - if ((properties->bluetooth_class.value() & 0x001f03) == 0x000500) - fake_bluetooth_input_client->AddInputDevice(object_path); -} - -void FakeBluetoothDeviceClient::UpdateDeviceRSSI( - const dbus::ObjectPath& object_path, - int16 rssi) { - PropertiesMap::const_iterator iter = properties_map_.find(object_path); - if (iter == properties_map_.end()) { - VLOG(2) << "Fake device does not exist: " << object_path.value(); - return; - } - Properties* properties = iter->second; - DCHECK(properties); - properties->rssi.ReplaceValue(rssi); -} - -void FakeBluetoothDeviceClient::UpdateConnectionInfo( - uint16 connection_rssi, - uint16 transmit_power, - uint16 max_transmit_power) { - connection_rssi_ = connection_rssi; - transmit_power_ = transmit_power; - max_transmit_power_ = max_transmit_power; -} - -void FakeBluetoothDeviceClient::PinCodeCallback( - const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback, - BluetoothAgentServiceProvider::Delegate::Status status, - const std::string& pincode) { - VLOG(1) << "PinCodeCallback: " << object_path.value(); - - if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) { - PairingOptionsMap::const_iterator iter = - pairing_options_map_.find(object_path); - - bool success = true; - - // If the device has pairing options defined - if (iter != pairing_options_map_.end()) { - success = iter->second->pairing_auth_token == pincode; - } - - if (success) { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, - base::Unretained(this), object_path, callback, - error_callback), - base::TimeDelta::FromMilliseconds(kSimulateNormalPairTimeMultiplier * - simulation_interval_ms_)); - } else { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, - base::Unretained(this), object_path, error_callback), - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); - } - - } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing, - base::Unretained(this), object_path, error_callback), - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); - - } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, - base::Unretained(this), object_path, error_callback), - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); - } -} - -void FakeBluetoothDeviceClient::PasskeyCallback( - const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback, - BluetoothAgentServiceProvider::Delegate::Status status, - uint32 passkey) { - VLOG(1) << "PasskeyCallback: " << object_path.value(); - - if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) { - PairingOptionsMap::const_iterator iter = - pairing_options_map_.find(object_path); - bool success = true; - - if (iter != pairing_options_map_.end()) { - success = static_cast<uint32>( - std::stoi(iter->second->pairing_auth_token)) == passkey; - } - - if (success) { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, - base::Unretained(this), object_path, callback, - error_callback), - base::TimeDelta::FromMilliseconds(kSimulateNormalPairTimeMultiplier * - simulation_interval_ms_)); - } else { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, - base::Unretained(this), object_path, error_callback), - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); - } - - } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing, - base::Unretained(this), object_path, error_callback), - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); - - } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, - base::Unretained(this), object_path, error_callback), - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); - } -} - -void FakeBluetoothDeviceClient::ConfirmationCallback( - const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback, - BluetoothAgentServiceProvider::Delegate::Status status) { - VLOG(1) << "ConfirmationCallback: " << object_path.value(); - - if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, - base::Unretained(this), object_path, callback, - error_callback), - base::TimeDelta::FromMilliseconds(kSimulateNormalPairTimeMultiplier * - simulation_interval_ms_)); - - } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing, - base::Unretained(this), object_path, error_callback), - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); - - } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, - base::Unretained(this), object_path, error_callback), - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); - } -} - -void FakeBluetoothDeviceClient::SimulateKeypress( - uint16 entered, - const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "SimulateKeypress " << entered << ": " << object_path.value(); - - FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client = - static_cast<FakeBluetoothAgentManagerClient*>( - DBusThreadManager::Get()->GetBluetoothAgentManagerClient()); - FakeBluetoothAgentServiceProvider* agent_service_provider = - fake_bluetooth_agent_manager_client->GetAgentServiceProvider(); - - // The agent service provider object could have been destroyed after the - // pairing is canceled. - if (!agent_service_provider) - return; - - agent_service_provider->DisplayPasskey(object_path, kTestPassKey, entered); - - if (entered < 7) { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress, - base::Unretained(this), entered + 1, object_path, - callback, error_callback), - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); - - } else { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, - base::Unretained(this), object_path, callback, - error_callback), - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); - } -} - -void FakeBluetoothDeviceClient::ConnectionCallback( - const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback, - BluetoothProfileServiceProvider::Delegate::Status status) { - VLOG(1) << "ConnectionCallback: " << object_path.value(); - - if (status == BluetoothProfileServiceProvider::Delegate::SUCCESS) { - callback.Run(); - } else if (status == BluetoothProfileServiceProvider::Delegate::CANCELLED) { - // TODO(keybuk): tear down this side of the connection - error_callback.Run(bluetooth_device::kErrorFailed, "Canceled"); - } else if (status == BluetoothProfileServiceProvider::Delegate::REJECTED) { - // TODO(keybuk): tear down this side of the connection - error_callback.Run(bluetooth_device::kErrorFailed, "Rejected"); - } -} - -void FakeBluetoothDeviceClient::DisconnectionCallback( - const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback, - BluetoothProfileServiceProvider::Delegate::Status status) { - VLOG(1) << "DisconnectionCallback: " << object_path.value(); - - if (status == BluetoothProfileServiceProvider::Delegate::SUCCESS) { - // TODO(keybuk): tear down this side of the connection - callback.Run(); - } else if (status == BluetoothProfileServiceProvider::Delegate::CANCELLED) { - error_callback.Run(bluetooth_device::kErrorFailed, "Canceled"); - } else if (status == BluetoothProfileServiceProvider::Delegate::REJECTED) { - error_callback.Run(bluetooth_device::kErrorFailed, "Rejected"); - } -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_device_client.h b/chromeos/dbus/fake_bluetooth_device_client.h deleted file mode 100644 index 03a2cb1f0..0000000 --- a/chromeos/dbus/fake_bluetooth_device_client.h +++ /dev/null
@@ -1,320 +0,0 @@ -// Copyright (c) 2013 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 CHROMEOS_DBUS_FAKE_BLUETOOTH_DEVICE_CLIENT_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_DEVICE_CLIENT_H_ - -#include <map> -#include <vector> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/containers/scoped_ptr_map.h" -#include "base/observer_list.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_agent_service_provider.h" -#include "chromeos/dbus/bluetooth_device_client.h" -#include "chromeos/dbus/bluetooth_profile_service_provider.h" -#include "dbus/object_path.h" -#include "dbus/property.h" - -namespace chromeos { - -// FakeBluetoothDeviceClient simulates the behavior of the Bluetooth Daemon -// device objects and is used both in test cases in place of a mock and on -// the Linux desktop. -class CHROMEOS_EXPORT FakeBluetoothDeviceClient : public BluetoothDeviceClient { - public: - struct Properties : public BluetoothDeviceClient::Properties { - explicit Properties(const PropertyChangedCallback& callback); - ~Properties() override; - - // dbus::PropertySet override - void Get(dbus::PropertyBase* property, - dbus::PropertySet::GetCallback callback) override; - void GetAll() override; - void Set(dbus::PropertyBase* property, - dbus::PropertySet::SetCallback callback) override; - }; - - struct SimulatedPairingOptions { - SimulatedPairingOptions(); - ~SimulatedPairingOptions(); - - bool incoming = false; - std::string pairing_method; - std::string pairing_auth_token; - std::string pairing_action; - }; - - // Stores properties of a device that is about to be created. - struct IncomingDeviceProperties { - IncomingDeviceProperties(); - ~IncomingDeviceProperties(); - - std::string device_address; - std::string device_alias; - int device_class = 0; - std::string device_name; - std::string device_path; - bool is_trusted = true; - bool incoming = false; - std::string pairing_action; - std::string pairing_auth_token; - std::string pairing_method; - }; - - FakeBluetoothDeviceClient(); - ~FakeBluetoothDeviceClient() override; - - // BluetoothDeviceClient overrides - void Init(dbus::Bus* bus) override; - void AddObserver(Observer* observer) override; - void RemoveObserver(Observer* observer) override; - std::vector<dbus::ObjectPath> GetDevicesForAdapter( - const dbus::ObjectPath& adapter_path) override; - Properties* GetProperties(const dbus::ObjectPath& object_path) override; - void Connect(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - void Disconnect(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - void ConnectProfile(const dbus::ObjectPath& object_path, - const std::string& uuid, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - void DisconnectProfile(const dbus::ObjectPath& object_path, - const std::string& uuid, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - void Pair(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - void CancelPairing(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - void GetConnInfo(const dbus::ObjectPath& object_path, - const ConnInfoCallback& callback, - const ErrorCallback& error_callback) override; - - void SetSimulationIntervalMs(int interval_ms); - - // Simulates discovery of devices for the given adapter. - void BeginDiscoverySimulation(const dbus::ObjectPath& adapter_path); - void EndDiscoverySimulation(const dbus::ObjectPath& adapter_path); - - // Simulates incoming pairing of devices for the given adapter. - void BeginIncomingPairingSimulation(const dbus::ObjectPath& adapter_path); - void EndIncomingPairingSimulation(const dbus::ObjectPath& adapter_path); - - // Creates a device from the set we return for the given adapter. - void CreateDevice(const dbus::ObjectPath& adapter_path, - const dbus::ObjectPath& device_path); - - // Creates a device with the given properties. - void CreateDeviceWithProperties(const dbus::ObjectPath& adapter_path, - const IncomingDeviceProperties& props); - - // Creates and returns a list of scoped_ptr<base::DictionaryValue> - // objects, which contain all the data from the constants for devices with - // predefined behavior. - scoped_ptr<base::ListValue> GetBluetoothDevicesAsDictionaries() const; - - SimulatedPairingOptions* GetPairingOptions( - const dbus::ObjectPath& object_path); - - // Removes a device from the set we return for the given adapter. - void RemoveDevice(const dbus::ObjectPath& adapter_path, - const dbus::ObjectPath& device_path); - - // Simulates a pairing for the device with the given D-Bus object path, - // |object_path|. Set |incoming_request| to true if simulating an incoming - // pairing request, false for an outgoing one. On successful completion - // |callback| will be called, on failure, |error_callback| is called. - void SimulatePairing(const dbus::ObjectPath& object_path, - bool incoming_request, - const base::Closure& callback, - const ErrorCallback& error_callback); - - // Updates the connection properties of the fake device that will be returned - // by GetConnInfo. - void UpdateConnectionInfo(uint16 connection_rssi, - uint16 transmit_power, - uint16 max_transmit_power); - - static const char kTestPinCode[]; - static const int kTestPassKey; - - static const char kPairingMethodNone[]; - static const char kPairingMethodPinCode[]; - static const char kPairingMethodPassKey[]; - - static const char kPairingActionConfirmation[]; - static const char kPairingActionDisplay[]; - static const char kPairingActionFail[]; - static const char kPairingActionRequest[]; - - // Object paths, names, addresses and bluetooth classes of the devices - // we can emulate. - static const char kPairedDevicePath[]; - static const char kPairedDeviceName[]; - static const char kPairedDeviceAddress[]; - static const uint32 kPairedDeviceClass; - - static const char kLegacyAutopairPath[]; - static const char kLegacyAutopairName[]; - static const char kLegacyAutopairAddress[]; - static const uint32 kLegacyAutopairClass; - - static const char kDisplayPinCodePath[]; - static const char kDisplayPinCodeName[]; - static const char kDisplayPinCodeAddress[]; - static const uint32 kDisplayPinCodeClass; - - static const char kVanishingDevicePath[]; - static const char kVanishingDeviceName[]; - static const char kVanishingDeviceAddress[]; - static const uint32 kVanishingDeviceClass; - - static const char kConnectUnpairablePath[]; - static const char kConnectUnpairableName[]; - static const char kConnectUnpairableAddress[]; - static const uint32 kConnectUnpairableClass; - - static const char kDisplayPasskeyPath[]; - static const char kDisplayPasskeyName[]; - static const char kDisplayPasskeyAddress[]; - static const uint32 kDisplayPasskeyClass; - - static const char kRequestPinCodePath[]; - static const char kRequestPinCodeName[]; - static const char kRequestPinCodeAddress[]; - static const uint32 kRequestPinCodeClass; - - static const char kConfirmPasskeyPath[]; - static const char kConfirmPasskeyName[]; - static const char kConfirmPasskeyAddress[]; - static const uint32 kConfirmPasskeyClass; - - static const char kRequestPasskeyPath[]; - static const char kRequestPasskeyName[]; - static const char kRequestPasskeyAddress[]; - static const uint32 kRequestPasskeyClass; - - static const char kUnconnectableDevicePath[]; - static const char kUnconnectableDeviceName[]; - static const char kUnconnectableDeviceAddress[]; - static const uint32 kUnconnectableDeviceClass; - - static const char kUnpairableDevicePath[]; - static const char kUnpairableDeviceName[]; - static const char kUnpairableDeviceAddress[]; - static const uint32 kUnpairableDeviceClass; - - static const char kJustWorksPath[]; - static const char kJustWorksName[]; - static const char kJustWorksAddress[]; - static const uint32 kJustWorksClass; - - static const char kLowEnergyPath[]; - static const char kLowEnergyName[]; - static const char kLowEnergyAddress[]; - static const uint32 kLowEnergyClass; - - static const char kPairedUnconnectableDevicePath[]; - static const char kPairedUnconnectableDeviceName[]; - static const char kPairedUnconnectableDeviceAddress[]; - static const uint32 kPairedUnconnectableDeviceClass; - - static const char kConnectedTrustedNotPairedDevicePath[]; - static const char kConnectedTrustedNotPairedDeviceAddress[]; - static const char kConnectedTrustedNotPairedDeviceName[]; - static const uint32 kConnectedTrustedNotPairedDeviceClass; - - private: - // Property callback passed when we create Properties* structures. - void OnPropertyChanged(const dbus::ObjectPath& object_path, - const std::string& property_name); - - void DiscoverySimulationTimer(); - void IncomingPairingSimulationTimer(); - - void CompleteSimulatedPairing(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback); - void TimeoutSimulatedPairing(const dbus::ObjectPath& object_path, - const ErrorCallback& error_callback); - void CancelSimulatedPairing(const dbus::ObjectPath& object_path, - const ErrorCallback& error_callback); - void RejectSimulatedPairing(const dbus::ObjectPath& object_path, - const ErrorCallback& error_callback); - void FailSimulatedPairing(const dbus::ObjectPath& object_path, - const ErrorCallback& error_callback); - void AddInputDeviceIfNeeded(const dbus::ObjectPath& object_path, - Properties* properties); - - // Updates the inquiry RSSI property of fake device with object path - // |object_path| to |rssi|, if the fake device exists. - void UpdateDeviceRSSI(const dbus::ObjectPath& object_path, int16 rssi); - - void PinCodeCallback(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback, - BluetoothAgentServiceProvider::Delegate::Status status, - const std::string& pincode); - void PasskeyCallback(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback, - BluetoothAgentServiceProvider::Delegate::Status status, - uint32 passkey); - void ConfirmationCallback( - const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback, - BluetoothAgentServiceProvider::Delegate::Status status); - void SimulateKeypress(uint16 entered, - const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback); - - void ConnectionCallback( - const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback, - BluetoothProfileServiceProvider::Delegate::Status status); - void DisconnectionCallback( - const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback, - BluetoothProfileServiceProvider::Delegate::Status status); - - // List of observers interested in event notifications from us. - base::ObserverList<Observer> observers_; - - using PropertiesMap = - base::ScopedPtrMap<const dbus::ObjectPath, scoped_ptr<Properties>>; - PropertiesMap properties_map_; - std::vector<dbus::ObjectPath> device_list_; - - // Properties which are used to decied which method of pairing should - // be done on request. - using PairingOptionsMap = - base::ScopedPtrMap<const dbus::ObjectPath, - scoped_ptr<SimulatedPairingOptions>>; - PairingOptionsMap pairing_options_map_; - - int simulation_interval_ms_; - uint32_t discovery_simulation_step_; - uint32_t incoming_pairing_simulation_step_; - bool pairing_cancelled_; - - int16 connection_rssi_; - int16 transmit_power_; - int16 max_transmit_power_; -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_DEVICE_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc b/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc deleted file mode 100644 index 69779ec..0000000 --- a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc +++ /dev/null
@@ -1,562 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h" - -#include "base/bind.h" -#include "base/location.h" -#include "base/rand_util.h" -#include "base/single_thread_task_runner.h" -#include "base/thread_task_runner_handle.h" -#include "base/time/time.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -namespace { - -const int kStartNotifyResponseIntervalMs = 200; -const int kHeartRateMeasurementNotificationIntervalMs = 2000; - -} // namespace - -FakeBluetoothGattCharacteristicClient::DelayedCallback::DelayedCallback( - base::Closure callback, - size_t delay) - : callback_(callback), delay_(delay) {} - -FakeBluetoothGattCharacteristicClient::DelayedCallback::~DelayedCallback() {} - -// static -const char FakeBluetoothGattCharacteristicClient:: - kHeartRateMeasurementPathComponent[] = "char0000"; -const char - FakeBluetoothGattCharacteristicClient::kBodySensorLocationPathComponent[] = - "char0001"; -const char FakeBluetoothGattCharacteristicClient:: - kHeartRateControlPointPathComponent[] = "char0002"; - -// static -const char FakeBluetoothGattCharacteristicClient::kHeartRateMeasurementUUID[] = - "00002a37-0000-1000-8000-00805f9b34fb"; -const char FakeBluetoothGattCharacteristicClient::kBodySensorLocationUUID[] = - "00002a38-0000-1000-8000-00805f9b34fb"; -const char FakeBluetoothGattCharacteristicClient::kHeartRateControlPointUUID[] = - "00002a39-0000-1000-8000-00805f9b34fb"; - -FakeBluetoothGattCharacteristicClient::Properties::Properties( - const PropertyChangedCallback& callback) - : BluetoothGattCharacteristicClient::Properties( - NULL, - bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, - callback) {} - -FakeBluetoothGattCharacteristicClient::Properties::~Properties() {} - -void FakeBluetoothGattCharacteristicClient::Properties::Get( - dbus::PropertyBase* property, - dbus::PropertySet::GetCallback callback) { - VLOG(1) << "Get " << property->name(); - callback.Run(true); -} - -void FakeBluetoothGattCharacteristicClient::Properties::GetAll() { - VLOG(1) << "GetAll"; -} - -void FakeBluetoothGattCharacteristicClient::Properties::Set( - dbus::PropertyBase* property, - dbus::PropertySet::SetCallback callback) { - VLOG(1) << "Set " << property->name(); - callback.Run(false); -} - -FakeBluetoothGattCharacteristicClient::FakeBluetoothGattCharacteristicClient() - : heart_rate_visible_(false), - authorized_(true), - authenticated_(true), - calories_burned_(0), - extra_requests_(0), - weak_ptr_factory_(this) {} - -FakeBluetoothGattCharacteristicClient:: - ~FakeBluetoothGattCharacteristicClient() { - for (const auto& it : action_extra_requests_) { - delete it.second; - } - action_extra_requests_.clear(); -} - -void FakeBluetoothGattCharacteristicClient::Init(dbus::Bus* bus) {} - -void FakeBluetoothGattCharacteristicClient::AddObserver(Observer* observer) { - observers_.AddObserver(observer); -} - -void FakeBluetoothGattCharacteristicClient::RemoveObserver(Observer* observer) { - observers_.RemoveObserver(observer); -} - -std::vector<dbus::ObjectPath> -FakeBluetoothGattCharacteristicClient::GetCharacteristics() { - std::vector<dbus::ObjectPath> paths; - if (IsHeartRateVisible()) { - paths.push_back(dbus::ObjectPath(heart_rate_measurement_path_)); - paths.push_back(dbus::ObjectPath(body_sensor_location_path_)); - paths.push_back(dbus::ObjectPath(heart_rate_control_point_path_)); - } - return paths; -} - -FakeBluetoothGattCharacteristicClient::Properties* -FakeBluetoothGattCharacteristicClient::GetProperties( - const dbus::ObjectPath& object_path) { - if (object_path.value() == heart_rate_measurement_path_) { - DCHECK(heart_rate_measurement_properties_.get()); - return heart_rate_measurement_properties_.get(); - } - if (object_path.value() == body_sensor_location_path_) { - DCHECK(body_sensor_location_properties_.get()); - return body_sensor_location_properties_.get(); - } - if (object_path.value() == heart_rate_control_point_path_) { - DCHECK(heart_rate_control_point_properties_.get()); - return heart_rate_control_point_properties_.get(); - } - return NULL; -} - -void FakeBluetoothGattCharacteristicClient::ReadValue( - const dbus::ObjectPath& object_path, - const ValueCallback& callback, - const ErrorCallback& error_callback) { - if (!authenticated_) { - error_callback.Run("org.bluez.Error.NotPaired", "Please login"); - return; - } - - if (!authorized_) { - error_callback.Run("org.bluez.Error.NotAuthorized", "Authorize first"); - return; - } - - if (object_path.value() == heart_rate_control_point_path_) { - error_callback.Run("org.bluez.Error.NotPermitted", - "Reads of this value are not allowed"); - return; - } - - if (object_path.value() == heart_rate_measurement_path_) { - error_callback.Run("org.bluez.Error.NotSupported", - "Action not supported on this characteristic"); - return; - } - - if (object_path.value() != body_sensor_location_path_) { - error_callback.Run(kUnknownCharacteristicError, ""); - return; - } - - if (action_extra_requests_.find("ReadValue") != - action_extra_requests_.end()) { - DelayedCallback* delayed = action_extra_requests_["ReadValue"]; - delayed->delay_--; - error_callback.Run("org.bluez.Error.InProgress", - "Another read is currenty in progress"); - if (delayed->delay_ == 0) { - delayed->callback_.Run(); - action_extra_requests_.erase("ReadValue"); - delete delayed; - } - return; - } - - base::Closure completed_callback; - if (!IsHeartRateVisible()) { - completed_callback = - base::Bind(error_callback, kUnknownCharacteristicError, ""); - } else { - std::vector<uint8> value = {0x06}; // Location is "foot". - completed_callback = base::Bind( - &FakeBluetoothGattCharacteristicClient::DelayedReadValueCallback, - weak_ptr_factory_.GetWeakPtr(), object_path, callback, value); - } - - if (extra_requests_ > 0) { - action_extra_requests_["ReadValue"] = - new DelayedCallback(completed_callback, extra_requests_); - return; - } - - completed_callback.Run(); -} - -void FakeBluetoothGattCharacteristicClient::WriteValue( - const dbus::ObjectPath& object_path, - const std::vector<uint8>& value, - const base::Closure& callback, - const ErrorCallback& error_callback) { - if (!authenticated_) { - error_callback.Run("org.bluez.Error.NotPaired", "Please login"); - return; - } - - if (!authorized_) { - error_callback.Run("org.bluez.Error.NotAuthorized", "Authorize first"); - return; - } - - if (!IsHeartRateVisible()) { - error_callback.Run(kUnknownCharacteristicError, ""); - return; - } - - if (object_path.value() == heart_rate_measurement_path_) { - error_callback.Run("org.bluez.Error.NotSupported", - "Action not supported on this characteristic"); - return; - } - - if (object_path.value() != heart_rate_control_point_path_) { - error_callback.Run("org.bluez.Error.NotPermitted", - "Writes of this value are not allowed"); - return; - } - - DCHECK(heart_rate_control_point_properties_.get()); - if (action_extra_requests_.find("WriteValue") != - action_extra_requests_.end()) { - DelayedCallback* delayed = action_extra_requests_["WriteValue"]; - delayed->delay_--; - error_callback.Run("org.bluez.Error.InProgress", - "Another write is in progress"); - if (delayed->delay_ == 0) { - delayed->callback_.Run(); - action_extra_requests_.erase("WriteValue"); - delete delayed; - } - return; - } - base::Closure completed_callback; - if (value.size() != 1) { - completed_callback = - base::Bind(error_callback, "org.bluez.Error.InvalidValueLength", - "Invalid length for write"); - } else if (value[0] > 1) { - completed_callback = base::Bind(error_callback, "org.bluez.Error.Failed", - "Invalid value given for write"); - } else if (value[0] == 1) { - // TODO(jamuraa): make this happen when the callback happens - calories_burned_ = 0; - completed_callback = callback; - } - - if (extra_requests_ > 0) { - action_extra_requests_["WriteValue"] = - new DelayedCallback(completed_callback, extra_requests_); - return; - } - completed_callback.Run(); -} - -void FakeBluetoothGattCharacteristicClient::StartNotify( - const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - if (!IsHeartRateVisible()) { - error_callback.Run(kUnknownCharacteristicError, ""); - return; - } - - if (object_path.value() != heart_rate_measurement_path_) { - error_callback.Run("org.bluez.Error.NotSupported", - "This characteristic does not support notifications"); - return; - } - - if (heart_rate_measurement_properties_->notifying.value()) { - error_callback.Run("org.bluez.Error.InProgress", - "Characteristic already notifying"); - return; - } - - heart_rate_measurement_properties_->notifying.ReplaceValue(true); - ScheduleHeartRateMeasurementValueChange(); - - // Respond asynchronously. - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, callback, - base::TimeDelta::FromMilliseconds(kStartNotifyResponseIntervalMs)); -} - -void FakeBluetoothGattCharacteristicClient::StopNotify( - const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - if (!IsHeartRateVisible()) { - error_callback.Run(kUnknownCharacteristicError, ""); - return; - } - - if (object_path.value() != heart_rate_measurement_path_) { - error_callback.Run("org.bluez.Error.NotSupported", - "This characteristic does not support notifications"); - return; - } - - if (!heart_rate_measurement_properties_->notifying.value()) { - error_callback.Run("org.bluez.Error.Failed", "Not notifying"); - return; - } - - heart_rate_measurement_properties_->notifying.ReplaceValue(false); - - callback.Run(); -} - -void FakeBluetoothGattCharacteristicClient::ExposeHeartRateCharacteristics( - const dbus::ObjectPath& service_path) { - if (IsHeartRateVisible()) { - VLOG(2) << "Fake Heart Rate characteristics are already visible."; - return; - } - - VLOG(2) << "Exposing fake Heart Rate characteristics."; - - std::vector<std::string> flags; - - // ==== Heart Rate Measurement Characteristic ==== - heart_rate_measurement_path_ = - service_path.value() + "/" + kHeartRateMeasurementPathComponent; - heart_rate_measurement_properties_.reset(new Properties( - base::Bind(&FakeBluetoothGattCharacteristicClient::OnPropertyChanged, - weak_ptr_factory_.GetWeakPtr(), - dbus::ObjectPath(heart_rate_measurement_path_)))); - heart_rate_measurement_properties_->uuid.ReplaceValue( - kHeartRateMeasurementUUID); - heart_rate_measurement_properties_->service.ReplaceValue(service_path); - flags.push_back(bluetooth_gatt_characteristic::kFlagNotify); - heart_rate_measurement_properties_->flags.ReplaceValue(flags); - - // ==== Body Sensor Location Characteristic ==== - body_sensor_location_path_ = - service_path.value() + "/" + kBodySensorLocationPathComponent; - body_sensor_location_properties_.reset(new Properties( - base::Bind(&FakeBluetoothGattCharacteristicClient::OnPropertyChanged, - weak_ptr_factory_.GetWeakPtr(), - dbus::ObjectPath(body_sensor_location_path_)))); - body_sensor_location_properties_->uuid.ReplaceValue(kBodySensorLocationUUID); - body_sensor_location_properties_->service.ReplaceValue(service_path); - flags.clear(); - flags.push_back(bluetooth_gatt_characteristic::kFlagRead); - body_sensor_location_properties_->flags.ReplaceValue(flags); - - // ==== Heart Rate Control Point Characteristic ==== - heart_rate_control_point_path_ = - service_path.value() + "/" + kHeartRateControlPointPathComponent; - heart_rate_control_point_properties_.reset(new Properties( - base::Bind(&FakeBluetoothGattCharacteristicClient::OnPropertyChanged, - weak_ptr_factory_.GetWeakPtr(), - dbus::ObjectPath(heart_rate_control_point_path_)))); - heart_rate_control_point_properties_->uuid.ReplaceValue( - kHeartRateControlPointUUID); - heart_rate_control_point_properties_->service.ReplaceValue(service_path); - flags.clear(); - flags.push_back(bluetooth_gatt_characteristic::kFlagWrite); - heart_rate_control_point_properties_->flags.ReplaceValue(flags); - - heart_rate_visible_ = true; - - NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_measurement_path_)); - NotifyCharacteristicAdded(dbus::ObjectPath(body_sensor_location_path_)); - NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_control_point_path_)); - - // Expose CCC descriptor for Heart Rate Measurement characteristic. - FakeBluetoothGattDescriptorClient* descriptor_client = - static_cast<FakeBluetoothGattDescriptorClient*>( - DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()); - dbus::ObjectPath ccc_path(descriptor_client->ExposeDescriptor( - dbus::ObjectPath(heart_rate_measurement_path_), - FakeBluetoothGattDescriptorClient:: - kClientCharacteristicConfigurationUUID)); - DCHECK(ccc_path.IsValid()); - heart_rate_measurement_ccc_desc_path_ = ccc_path.value(); - - std::vector<dbus::ObjectPath> desc_paths; - desc_paths.push_back(ccc_path); - - heart_rate_measurement_properties_->descriptors.ReplaceValue(desc_paths); -} - -void FakeBluetoothGattCharacteristicClient::HideHeartRateCharacteristics() { - VLOG(2) << "Hiding fake Heart Rate characteristics."; - - // Hide the descriptors. - FakeBluetoothGattDescriptorClient* descriptor_client = - static_cast<FakeBluetoothGattDescriptorClient*>( - DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()); - descriptor_client->HideDescriptor( - dbus::ObjectPath(heart_rate_measurement_ccc_desc_path_)); - - // Notify the observers before deleting the properties structures so that they - // can be accessed from the observer method. - NotifyCharacteristicRemoved(dbus::ObjectPath(heart_rate_measurement_path_)); - NotifyCharacteristicRemoved(dbus::ObjectPath(body_sensor_location_path_)); - NotifyCharacteristicRemoved(dbus::ObjectPath(heart_rate_control_point_path_)); - - heart_rate_measurement_properties_.reset(); - body_sensor_location_properties_.reset(); - heart_rate_control_point_properties_.reset(); - - heart_rate_measurement_path_.clear(); - body_sensor_location_path_.clear(); - heart_rate_control_point_path_.clear(); - heart_rate_visible_ = false; -} - -void FakeBluetoothGattCharacteristicClient::SetExtraProcessing( - size_t requests) { - extra_requests_ = requests; - if (extra_requests_ == 0) { - for (const auto& it : action_extra_requests_) { - it.second->callback_.Run(); - delete it.second; - } - action_extra_requests_.clear(); - return; - } - VLOG(2) << "Requests SLOW now, " << requests << " InProgress errors each."; -} - -size_t FakeBluetoothGattCharacteristicClient::GetExtraProcessing() const { - return extra_requests_; -} - -dbus::ObjectPath -FakeBluetoothGattCharacteristicClient::GetHeartRateMeasurementPath() const { - return dbus::ObjectPath(heart_rate_measurement_path_); -} - -dbus::ObjectPath -FakeBluetoothGattCharacteristicClient::GetBodySensorLocationPath() const { - return dbus::ObjectPath(body_sensor_location_path_); -} - -dbus::ObjectPath -FakeBluetoothGattCharacteristicClient::GetHeartRateControlPointPath() const { - return dbus::ObjectPath(heart_rate_control_point_path_); -} - -void FakeBluetoothGattCharacteristicClient::OnPropertyChanged( - const dbus::ObjectPath& object_path, - const std::string& property_name) { - VLOG(2) << "Characteristic property changed: " << object_path.value() << ": " - << property_name; - - FOR_EACH_OBSERVER( - BluetoothGattCharacteristicClient::Observer, observers_, - GattCharacteristicPropertyChanged(object_path, property_name)); -} - -void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicAdded( - const dbus::ObjectPath& object_path) { - VLOG(2) << "GATT characteristic added: " << object_path.value(); - FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, - GattCharacteristicAdded(object_path)); -} - -void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicRemoved( - const dbus::ObjectPath& object_path) { - VLOG(2) << "GATT characteristic removed: " << object_path.value(); - FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, - GattCharacteristicRemoved(object_path)); -} - -void FakeBluetoothGattCharacteristicClient:: - ScheduleHeartRateMeasurementValueChange() { - if (!IsHeartRateVisible()) - return; - - // Don't send updates if the characteristic is not notifying. - if (!heart_rate_measurement_properties_->notifying.value()) - return; - - VLOG(2) << "Updating heart rate value."; - std::vector<uint8> measurement = GetHeartRateMeasurementValue(); - heart_rate_measurement_properties_->value.ReplaceValue(measurement); - - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&FakeBluetoothGattCharacteristicClient:: - ScheduleHeartRateMeasurementValueChange, - weak_ptr_factory_.GetWeakPtr()), - base::TimeDelta::FromMilliseconds( - kHeartRateMeasurementNotificationIntervalMs)); -} - -void FakeBluetoothGattCharacteristicClient::DelayedReadValueCallback( - const dbus::ObjectPath& object_path, - const ValueCallback& callback, - const std::vector<uint8_t>& value) { - Properties* properties = GetProperties(object_path); - DCHECK(properties); - - properties->value.ReplaceValue(value); - callback.Run(value); -} - -std::vector<uint8> -FakeBluetoothGattCharacteristicClient::GetHeartRateMeasurementValue() { - // TODO(armansito): We should make sure to properly pack this struct to ensure - // correct byte alignment and endianness. It doesn't matter too much right now - // as this is a fake and GCC on Linux seems to do the right thing. - struct { - uint8 flags; - uint8 bpm; - uint16 energy_expanded; - uint16 rr_interval; - } value; - - // Flags in LSB: 0 11 1 1 000 - // | | | | | - // 8-bit bpm format -- | | | | - // Sensor contact supported -- | | | - // Energy expanded field present -- | | - // RR-Interval values present ------- | - // Reserved for future use ------------ - value.flags = 0x0; - value.flags |= (0x03 << 1); - value.flags |= (0x01 << 3); - value.flags |= (0x01 << 4); - - // Pick a value between 117 bpm and 153 bpm for heart rate. - value.bpm = static_cast<uint8>(base::RandInt(117, 153)); - - // Total calories burned in kJoules since the last reset. Increment this by 1 - // every time. It's fine if it overflows: it becomes 0 when the user resets - // the heart rate monitor (or pretend that he had a lot of cheeseburgers). - value.energy_expanded = calories_burned_++; - - // Include one RR-Interval value, in seconds. - value.rr_interval = 60 / value.bpm; - - // Return the bytes in an array. - uint8* bytes = reinterpret_cast<uint8*>(&value); - std::vector<uint8> return_value; - return_value.assign(bytes, bytes + sizeof(value)); - return return_value; -} - -bool FakeBluetoothGattCharacteristicClient::IsHeartRateVisible() const { - DCHECK(heart_rate_visible_ != heart_rate_measurement_path_.empty()); - DCHECK(heart_rate_visible_ != body_sensor_location_path_.empty()); - DCHECK(heart_rate_visible_ != heart_rate_control_point_path_.empty()); - DCHECK(heart_rate_visible_ == !!heart_rate_measurement_properties_.get()); - DCHECK(heart_rate_visible_ == !!body_sensor_location_properties_.get()); - DCHECK(heart_rate_visible_ == !!heart_rate_control_point_properties_.get()); - return heart_rate_visible_; -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h b/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h deleted file mode 100644 index dc1eab3..0000000 --- a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h +++ /dev/null
@@ -1,194 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_ - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/observer_list.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_gatt_characteristic_client.h" -#include "dbus/object_path.h" -#include "dbus/property.h" - -namespace chromeos { - -// FakeBluetoothGattCharacteristicClient simulates the behavior of the -// Bluetooth Daemon GATT characteristic objects and is used in test cases in -// place of a mock and on the Linux desktop. -class CHROMEOS_EXPORT FakeBluetoothGattCharacteristicClient - : public BluetoothGattCharacteristicClient { - public: - struct Properties : public BluetoothGattCharacteristicClient::Properties { - explicit Properties(const PropertyChangedCallback& callback); - ~Properties() override; - - // dbus::PropertySet override - void Get(dbus::PropertyBase* property, - dbus::PropertySet::GetCallback callback) override; - void GetAll() override; - void Set(dbus::PropertyBase* property, - dbus::PropertySet::SetCallback callback) override; - }; - - FakeBluetoothGattCharacteristicClient(); - ~FakeBluetoothGattCharacteristicClient() override; - - // DBusClient override. - void Init(dbus::Bus* bus) override; - - // BluetoothGattCharacteristicClient overrides. - void AddObserver(Observer* observer) override; - void RemoveObserver(Observer* observer) override; - std::vector<dbus::ObjectPath> GetCharacteristics() override; - Properties* GetProperties(const dbus::ObjectPath& object_path) override; - void ReadValue(const dbus::ObjectPath& object_path, - const ValueCallback& callback, - const ErrorCallback& error_callback) override; - void WriteValue(const dbus::ObjectPath& object_path, - const std::vector<uint8>& value, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - void StartNotify(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - void StopNotify(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - - // Makes the group of characteristics belonging to a particular GATT based - // profile available under the GATT service with object path |service_path|. - // Characteristic paths are hierarchical to service paths. - void ExposeHeartRateCharacteristics(const dbus::ObjectPath& service_path); - void HideHeartRateCharacteristics(); - - // Returns whether or not the heart rate characteristics are visible and - // performs the appropriate assertions. - bool IsHeartRateVisible() const; - - // Makes this characteristic client really slow. - // So slow, that it is guaranteed that |requests| requests will - // come in while the client is doing the previous request. - // Setting |requests| to zero will cause all delayed actions to - // complete immediately. - void SetExtraProcessing(size_t requests); - - size_t GetExtraProcessing() const; - - // Sets whether the client is authorized or not. - // Defaults to authorized. - void SetAuthorized(bool authorized) { authorized_ = authorized; } - - // Get the current Authorization state. - bool IsAuthorized() const { return authorized_; } - - // Whether the client is Authenticated - // Defaults to authenticated. - void SetAuthenticated(bool authenticated) { authenticated_ = authenticated; } - - // Get the current Authenticated state. - bool IsAuthenticated() const { return authenticated_; } - - // Returns the current object paths of exposed characteristics. If the - // characteristic is not visible, returns an invalid empty path. - dbus::ObjectPath GetHeartRateMeasurementPath() const; - dbus::ObjectPath GetBodySensorLocationPath() const; - dbus::ObjectPath GetHeartRateControlPointPath() const; - - // Object path components and UUIDs of GATT characteristics. - // Heart Rate Service: - static const char kHeartRateMeasurementPathComponent[]; - static const char kHeartRateMeasurementUUID[]; - static const char kBodySensorLocationPathComponent[]; - static const char kBodySensorLocationUUID[]; - static const char kHeartRateControlPointPathComponent[]; - static const char kHeartRateControlPointUUID[]; - - private: - // Property callback passed when we create Properties structures. - void OnPropertyChanged(const dbus::ObjectPath& object_path, - const std::string& property_name); - - // Notifies observers. - void NotifyCharacteristicAdded(const dbus::ObjectPath& object_path); - void NotifyCharacteristicRemoved(const dbus::ObjectPath& object_path); - - // Schedules a heart rate measurement value change, if the heart rate - // characteristics are visible. - void ScheduleHeartRateMeasurementValueChange(); - - // Returns a random Heart Rate Measurement value. All the fields of the value - // are populated according to the the fake behavior. The measurement value - // is a random value within a reasonable range. - std::vector<uint8> GetHeartRateMeasurementValue(); - - // Callback that executes a delayed ReadValue action by updating the - // appropriate "Value" property and invoking the ValueCallback. - void DelayedReadValueCallback(const dbus::ObjectPath& object_path, - const ValueCallback& callback, - const std::vector<uint8_t>& value); - - // If true, characteristics of the Heart Rate Service are visible. Use - // IsHeartRateVisible() to check the value. - bool heart_rate_visible_; - - // If true, the client is authorized to read and write. - bool authorized_; - - // If true, the client is authenticated. - bool authenticated_; - - // Total calories burned, used for the Heart Rate Measurement characteristic. - uint16 calories_burned_; - - // Static properties returned for simulated characteristics for the Heart - // Rate Service. These pointers are not NULL only if the characteristics are - // actually exposed. - scoped_ptr<Properties> heart_rate_measurement_properties_; - scoped_ptr<Properties> body_sensor_location_properties_; - scoped_ptr<Properties> heart_rate_control_point_properties_; - - // Object paths of the exposed characteristics. If a characteristic is not - // exposed, these will be empty. - std::string heart_rate_measurement_path_; - std::string heart_rate_measurement_ccc_desc_path_; - std::string body_sensor_location_path_; - std::string heart_rate_control_point_path_; - - // Number of extra requests that need to come in simulating slowness. - size_t extra_requests_; - - // Current countdowns for extra requests for various actions. - struct DelayedCallback { - public: - DelayedCallback(base::Closure callback, size_t delay); - ~DelayedCallback(); - - base::Closure callback_; - size_t delay_; - }; - - // Map of delayed callbacks. - std::map<std::string, DelayedCallback*> action_extra_requests_; - - // List of observers interested in event notifications from us. - base::ObserverList<Observer> observers_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<FakeBluetoothGattCharacteristicClient> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattCharacteristicClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.cc b/chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.cc deleted file mode 100644 index 39132d9..0000000 --- a/chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.cc +++ /dev/null
@@ -1,105 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.h" - -#include "base/logging.h" -#include "base/strings/string_util.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_gatt_manager_client.h" - -namespace chromeos { - -FakeBluetoothGattCharacteristicServiceProvider:: - FakeBluetoothGattCharacteristicServiceProvider( - const dbus::ObjectPath& object_path, - Delegate* delegate, - const std::string& uuid, - const std::vector<std::string>& flags, - const std::vector<std::string>& permissions, - const dbus::ObjectPath& service_path) - : object_path_(object_path), - uuid_(uuid), - service_path_(service_path), - delegate_(delegate) { - VLOG(1) << "Creating Bluetooth GATT characteristic: " << object_path_.value(); - - DCHECK(object_path_.IsValid()); - DCHECK(service_path_.IsValid()); - DCHECK(!uuid.empty()); - DCHECK(delegate_); - DCHECK(base::StartsWith(object_path_.value(), service_path_.value() + "/", - base::CompareCase::SENSITIVE)); - - // TODO(armansito): Do something with |flags| and |permissions|. - - FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = - static_cast<FakeBluetoothGattManagerClient*>( - DBusThreadManager::Get()->GetBluetoothGattManagerClient()); - fake_bluetooth_gatt_manager_client->RegisterCharacteristicServiceProvider( - this); -} - -FakeBluetoothGattCharacteristicServiceProvider:: - ~FakeBluetoothGattCharacteristicServiceProvider() { - VLOG(1) << "Cleaning up Bluetooth GATT characteristic: " - << object_path_.value(); - - FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = - static_cast<FakeBluetoothGattManagerClient*>( - DBusThreadManager::Get()->GetBluetoothGattManagerClient()); - fake_bluetooth_gatt_manager_client->UnregisterCharacteristicServiceProvider( - this); -} - -void FakeBluetoothGattCharacteristicServiceProvider::SendValueChanged( - const std::vector<uint8>& value) { - VLOG(1) << "Sent characteristic value changed: " << object_path_.value() - << " UUID: " << uuid_; -} - -void FakeBluetoothGattCharacteristicServiceProvider::GetValue( - const Delegate::ValueCallback& callback, - const Delegate::ErrorCallback& error_callback) { - VLOG(1) << "GATT characteristic value Get request: " << object_path_.value() - << " UUID: " << uuid_; - - // Check if this characteristic is registered. - FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = - static_cast<FakeBluetoothGattManagerClient*>( - DBusThreadManager::Get()->GetBluetoothGattManagerClient()); - if (!fake_bluetooth_gatt_manager_client->IsServiceRegistered(service_path_)) { - VLOG(1) << "GATT characteristic not registered."; - error_callback.Run(); - return; - } - - // Pass on to the delegate. - DCHECK(delegate_); - delegate_->GetCharacteristicValue(callback, error_callback); -} - -void FakeBluetoothGattCharacteristicServiceProvider::SetValue( - const std::vector<uint8>& value, - const base::Closure& callback, - const Delegate::ErrorCallback& error_callback) { - VLOG(1) << "GATT characteristic value Set request: " << object_path_.value() - << " UUID: " << uuid_; - - // Check if this characteristic is registered. - FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = - static_cast<FakeBluetoothGattManagerClient*>( - DBusThreadManager::Get()->GetBluetoothGattManagerClient()); - if (!fake_bluetooth_gatt_manager_client->IsServiceRegistered(service_path_)) { - VLOG(1) << "GATT characteristic not registered."; - error_callback.Run(); - return; - } - - // Pass on to the delegate. - DCHECK(delegate_); - delegate_->SetCharacteristicValue(value, callback, error_callback); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.h b/chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.h deleted file mode 100644 index 8a8440b..0000000 --- a/chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.h +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_ - -#include <string> -#include <vector> - -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_gatt_characteristic_service_provider.h" -#include "dbus/object_path.h" - -namespace chromeos { - -// FakeBluetoothGattCharacteristicServiceProvider simulates behavior of a local -// GATT characteristic object and is used both in test cases in place of a mock -// and on the Linux desktop. -class CHROMEOS_EXPORT FakeBluetoothGattCharacteristicServiceProvider - : public BluetoothGattCharacteristicServiceProvider { - public: - FakeBluetoothGattCharacteristicServiceProvider( - const dbus::ObjectPath& object_path, - Delegate* delegate, - const std::string& uuid, - const std::vector<std::string>& flags, - const std::vector<std::string>& permissions, - const dbus::ObjectPath& service_path); - ~FakeBluetoothGattCharacteristicServiceProvider() override; - - // BluetoothGattCharacteristicServiceProvider override. - void SendValueChanged(const std::vector<uint8>& value) override; - - // Methods to simulate value get/set requests issued from a remote device. The - // methods do nothing, if the associated service was not registered with the - // GATT manager. - void GetValue(const Delegate::ValueCallback& callback, - const Delegate::ErrorCallback& error_callback); - void SetValue(const std::vector<uint8>& value, - const base::Closure& callback, - const Delegate::ErrorCallback& error_callback); - - const dbus::ObjectPath& object_path() const { return object_path_; } - const std::string& uuid() const { return uuid_; } - const dbus::ObjectPath& service_path() const { return service_path_; } - - private: - // D-Bus object path of the fake GATT characteristic. - dbus::ObjectPath object_path_; - - // 128-bit GATT characteristic UUID. - std::string uuid_; - - // Object path of the service that this characteristic belongs to. - dbus::ObjectPath service_path_; - - // The delegate that method calls are passed on to. - Delegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattCharacteristicServiceProvider); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/fake_bluetooth_gatt_descriptor_client.cc b/chromeos/dbus/fake_bluetooth_gatt_descriptor_client.cc deleted file mode 100644 index 2e9cdf0..0000000 --- a/chromeos/dbus/fake_bluetooth_gatt_descriptor_client.cc +++ /dev/null
@@ -1,209 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "chromeos/dbus/bluetooth_gatt_characteristic_client.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -const char FakeBluetoothGattDescriptorClient:: - kClientCharacteristicConfigurationPathComponent[] = "desc0000"; -const char FakeBluetoothGattDescriptorClient:: - kClientCharacteristicConfigurationUUID[] = - "00002902-0000-1000-8000-00805f9b34fb"; - -FakeBluetoothGattDescriptorClient::Properties::Properties( - const PropertyChangedCallback& callback) - : BluetoothGattDescriptorClient::Properties( - NULL, - bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface, - callback) {} - -FakeBluetoothGattDescriptorClient::Properties::~Properties() {} - -void FakeBluetoothGattDescriptorClient::Properties::Get( - dbus::PropertyBase* property, - dbus::PropertySet::GetCallback callback) { - VLOG(1) << "Get " << property->name(); - callback.Run(true); -} - -void FakeBluetoothGattDescriptorClient::Properties::GetAll() { - VLOG(1) << "GetAll"; -} - -void FakeBluetoothGattDescriptorClient::Properties::Set( - dbus::PropertyBase* property, - dbus::PropertySet::SetCallback callback) { - VLOG(1) << "Set " << property->name(); - callback.Run(false); -} - -FakeBluetoothGattDescriptorClient::DescriptorData::DescriptorData() {} - -FakeBluetoothGattDescriptorClient::DescriptorData::~DescriptorData() {} - -FakeBluetoothGattDescriptorClient::FakeBluetoothGattDescriptorClient() - : weak_ptr_factory_(this) {} - -FakeBluetoothGattDescriptorClient::~FakeBluetoothGattDescriptorClient() { - for (PropertiesMap::iterator iter = properties_.begin(); - iter != properties_.end(); iter++) - delete iter->second; -} - -void FakeBluetoothGattDescriptorClient::Init(dbus::Bus* bus) {} - -void FakeBluetoothGattDescriptorClient::AddObserver(Observer* observer) { - observers_.AddObserver(observer); -} - -void FakeBluetoothGattDescriptorClient::RemoveObserver(Observer* observer) { - observers_.RemoveObserver(observer); -} - -std::vector<dbus::ObjectPath> -FakeBluetoothGattDescriptorClient::GetDescriptors() { - std::vector<dbus::ObjectPath> descriptors; - for (PropertiesMap::const_iterator iter = properties_.begin(); - iter != properties_.end(); ++iter) { - descriptors.push_back(iter->first); - } - return descriptors; -} - -FakeBluetoothGattDescriptorClient::Properties* -FakeBluetoothGattDescriptorClient::GetProperties( - const dbus::ObjectPath& object_path) { - PropertiesMap::const_iterator iter = properties_.find(object_path); - if (iter == properties_.end()) - return NULL; - return iter->second->properties.get(); -} - -void FakeBluetoothGattDescriptorClient::ReadValue( - const dbus::ObjectPath& object_path, - const ValueCallback& callback, - const ErrorCallback& error_callback) { - PropertiesMap::iterator iter = properties_.find(object_path); - if (iter == properties_.end()) { - error_callback.Run(kUnknownDescriptorError, ""); - return; - } - - // Assign the value of the descriptor as necessary - Properties* properties = iter->second->properties.get(); - if (properties->uuid.value() == kClientCharacteristicConfigurationUUID) { - BluetoothGattCharacteristicClient::Properties* chrc_props = - DBusThreadManager::Get() - ->GetBluetoothGattCharacteristicClient() - ->GetProperties(properties->characteristic.value()); - DCHECK(chrc_props); - - uint8_t value_byte = chrc_props->notifying.value() ? 0x01 : 0x00; - const std::vector<uint8_t>& cur_value = properties->value.value(); - - if (!cur_value.size() || cur_value[0] != value_byte) { - std::vector<uint8_t> value = {value_byte, 0x00}; - properties->value.ReplaceValue(value); - } - } - - callback.Run(iter->second->properties->value.value()); -} - -void FakeBluetoothGattDescriptorClient::WriteValue( - const dbus::ObjectPath& object_path, - const std::vector<uint8>& value, - const base::Closure& callback, - const ErrorCallback& error_callback) { - if (properties_.find(object_path) == properties_.end()) { - error_callback.Run(kUnknownDescriptorError, ""); - return; - } - - // Since the only fake descriptor is "Client Characteristic Configuration" - // and BlueZ doesn't allow writing to it, return failure. - error_callback.Run("org.bluez.Error.NotPermitted", - "Writing to the Client Characteristic Configuration " - "descriptor not allowed"); -} - -dbus::ObjectPath FakeBluetoothGattDescriptorClient::ExposeDescriptor( - const dbus::ObjectPath& characteristic_path, - const std::string& uuid) { - if (uuid != kClientCharacteristicConfigurationUUID) { - VLOG(2) << "Unsupported UUID: " << uuid; - return dbus::ObjectPath(); - } - - // CCC descriptor is the only one supported at the moment. - DCHECK(characteristic_path.IsValid()); - dbus::ObjectPath object_path(characteristic_path.value() + "/" + - kClientCharacteristicConfigurationPathComponent); - DCHECK(object_path.IsValid()); - PropertiesMap::const_iterator iter = properties_.find(object_path); - if (iter != properties_.end()) { - VLOG(1) << "Descriptor already exposed: " << object_path.value(); - return dbus::ObjectPath(); - } - - Properties* properties = new Properties( - base::Bind(&FakeBluetoothGattDescriptorClient::OnPropertyChanged, - weak_ptr_factory_.GetWeakPtr(), object_path)); - properties->uuid.ReplaceValue(uuid); - properties->characteristic.ReplaceValue(characteristic_path); - - DescriptorData* data = new DescriptorData(); - data->properties.reset(properties); - - properties_[object_path] = data; - - NotifyDescriptorAdded(object_path); - - return object_path; -} - -void FakeBluetoothGattDescriptorClient::HideDescriptor( - const dbus::ObjectPath& descriptor_path) { - PropertiesMap::iterator iter = properties_.find(descriptor_path); - if (iter == properties_.end()) { - VLOG(1) << "Descriptor not exposed: " << descriptor_path.value(); - return; - } - - NotifyDescriptorRemoved(descriptor_path); - - delete iter->second; - properties_.erase(iter); -} - -void FakeBluetoothGattDescriptorClient::OnPropertyChanged( - const dbus::ObjectPath& object_path, - const std::string& property_name) { - VLOG(2) << "Descriptor property changed: " << object_path.value() << ": " - << property_name; - - FOR_EACH_OBSERVER(BluetoothGattDescriptorClient::Observer, observers_, - GattDescriptorPropertyChanged(object_path, property_name)); -} - -void FakeBluetoothGattDescriptorClient::NotifyDescriptorAdded( - const dbus::ObjectPath& object_path) { - FOR_EACH_OBSERVER(BluetoothGattDescriptorClient::Observer, observers_, - GattDescriptorAdded(object_path)); -} - -void FakeBluetoothGattDescriptorClient::NotifyDescriptorRemoved( - const dbus::ObjectPath& object_path) { - FOR_EACH_OBSERVER(BluetoothGattDescriptorClient::Observer, observers_, - GattDescriptorRemoved(object_path)); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h b/chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h deleted file mode 100644 index e6106c1a..0000000 --- a/chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h +++ /dev/null
@@ -1,103 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_ - -#include <map> -#include <string> - -#include "base/memory/weak_ptr.h" -#include "base/observer_list.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_gatt_descriptor_client.h" -#include "dbus/object_path.h" - -namespace chromeos { - -// FakeBluetoothGattDescriptorClient simulates the behavior of the Bluetooth -// Daemon GATT characteristic descriptor objects and is used in test cases in -// place of a mock and on the Linux desktop. -class CHROMEOS_EXPORT FakeBluetoothGattDescriptorClient - : public BluetoothGattDescriptorClient { - public: - struct Properties : public BluetoothGattDescriptorClient::Properties { - explicit Properties(const PropertyChangedCallback& callback); - ~Properties() override; - - // dbus::PropertySet override - void Get(dbus::PropertyBase* property, - dbus::PropertySet::GetCallback callback) override; - void GetAll() override; - void Set(dbus::PropertyBase* property, - dbus::PropertySet::SetCallback callback) override; - }; - - FakeBluetoothGattDescriptorClient(); - ~FakeBluetoothGattDescriptorClient() override; - - // DBusClient override. - void Init(dbus::Bus* bus) override; - - // BluetoothGattDescriptorClient overrides. - void AddObserver(Observer* observer) override; - void RemoveObserver(Observer* observer) override; - std::vector<dbus::ObjectPath> GetDescriptors() override; - Properties* GetProperties(const dbus::ObjectPath& object_path) override; - void ReadValue(const dbus::ObjectPath& object_path, - const ValueCallback& callback, - const ErrorCallback& error_callback) override; - void WriteValue(const dbus::ObjectPath& object_path, - const std::vector<uint8>& value, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - - // Makes the descriptor with the UUID |uuid| visible under the characteristic - // with object path |characteristic_path|. Descriptor object paths are - // hierarchical to their characteristics. |uuid| must belong to a descriptor - // for which there is a constant defined below, otherwise this method has no - // effect. Returns the object path of the created descriptor. In the no-op - // case, returns an invalid path. - dbus::ObjectPath ExposeDescriptor(const dbus::ObjectPath& characteristic_path, - const std::string& uuid); - void HideDescriptor(const dbus::ObjectPath& descriptor_path); - - // Object path components and UUIDs of GATT characteristic descriptors. - static const char kClientCharacteristicConfigurationPathComponent[]; - static const char kClientCharacteristicConfigurationUUID[]; - - private: - // Property callback passed when we create Properties structures. - void OnPropertyChanged(const dbus::ObjectPath& object_path, - const std::string& property_name); - - // Notifies observers. - void NotifyDescriptorAdded(const dbus::ObjectPath& object_path); - void NotifyDescriptorRemoved(const dbus::ObjectPath& object_path); - - // Mapping from object paths to Properties structures. - struct DescriptorData { - DescriptorData(); - ~DescriptorData(); - - scoped_ptr<Properties> properties; - }; - typedef std::map<dbus::ObjectPath, DescriptorData*> PropertiesMap; - PropertiesMap properties_; - - // List of observers interested in event notifications from us. - base::ObserverList<Observer> observers_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<FakeBluetoothGattDescriptorClient> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattDescriptorClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.cc b/chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.cc deleted file mode 100644 index ad002abb..0000000 --- a/chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.cc +++ /dev/null
@@ -1,121 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.h" - -#include "base/logging.h" -#include "base/strings/string_util.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.h" -#include "chromeos/dbus/fake_bluetooth_gatt_manager_client.h" - -namespace chromeos { - -FakeBluetoothGattDescriptorServiceProvider:: - FakeBluetoothGattDescriptorServiceProvider( - const dbus::ObjectPath& object_path, - Delegate* delegate, - const std::string& uuid, - const std::vector<std::string>& permissions, - const dbus::ObjectPath& characteristic_path) - : object_path_(object_path), - uuid_(uuid), - characteristic_path_(characteristic_path), - delegate_(delegate) { - VLOG(1) << "Creating Bluetooth GATT descriptor: " << object_path_.value(); - - DCHECK(object_path_.IsValid()); - DCHECK(characteristic_path_.IsValid()); - DCHECK(!uuid.empty()); - DCHECK(delegate_); - DCHECK(base::StartsWith(object_path_.value(), - characteristic_path_.value() + "/", - base::CompareCase::SENSITIVE)); - - // TODO(armansito): Do something with |permissions|. - - FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = - static_cast<FakeBluetoothGattManagerClient*>( - DBusThreadManager::Get()->GetBluetoothGattManagerClient()); - fake_bluetooth_gatt_manager_client->RegisterDescriptorServiceProvider(this); -} - -FakeBluetoothGattDescriptorServiceProvider:: - ~FakeBluetoothGattDescriptorServiceProvider() { - VLOG(1) << "Cleaning up Bluetooth GATT descriptor: " << object_path_.value(); - - FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = - static_cast<FakeBluetoothGattManagerClient*>( - DBusThreadManager::Get()->GetBluetoothGattManagerClient()); - fake_bluetooth_gatt_manager_client->UnregisterDescriptorServiceProvider(this); -} - -void FakeBluetoothGattDescriptorServiceProvider::SendValueChanged( - const std::vector<uint8>& value) { - VLOG(1) << "Sent descriptor value changed: " << object_path_.value() - << " UUID: " << uuid_; -} - -void FakeBluetoothGattDescriptorServiceProvider::GetValue( - const Delegate::ValueCallback& callback, - const Delegate::ErrorCallback& error_callback) { - VLOG(1) << "GATT descriptor value Get request: " << object_path_.value() - << " UUID: " << uuid_; - - // Check if this descriptor is registered. - FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = - static_cast<FakeBluetoothGattManagerClient*>( - DBusThreadManager::Get()->GetBluetoothGattManagerClient()); - FakeBluetoothGattCharacteristicServiceProvider* characteristic = - fake_bluetooth_gatt_manager_client->GetCharacteristicServiceProvider( - characteristic_path_); - if (!characteristic) { - VLOG(1) << "GATT characteristic for descriptor does not exist: " - << characteristic_path_.value(); - return; - } - if (!fake_bluetooth_gatt_manager_client->IsServiceRegistered( - characteristic->service_path())) { - VLOG(1) << "GATT descriptor not registered."; - error_callback.Run(); - return; - } - - // Pass on to the delegate. - DCHECK(delegate_); - delegate_->GetDescriptorValue(callback, error_callback); -} - -void FakeBluetoothGattDescriptorServiceProvider::SetValue( - const std::vector<uint8>& value, - const base::Closure& callback, - const Delegate::ErrorCallback& error_callback) { - VLOG(1) << "GATT descriptor value Set request: " << object_path_.value() - << " UUID: " << uuid_; - - // Check if this descriptor is registered. - FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = - static_cast<FakeBluetoothGattManagerClient*>( - DBusThreadManager::Get()->GetBluetoothGattManagerClient()); - FakeBluetoothGattCharacteristicServiceProvider* characteristic = - fake_bluetooth_gatt_manager_client->GetCharacteristicServiceProvider( - characteristic_path_); - if (!characteristic) { - VLOG(1) << "GATT characteristic for descriptor does not exist: " - << characteristic_path_.value(); - return; - } - if (!fake_bluetooth_gatt_manager_client->IsServiceRegistered( - characteristic->service_path())) { - VLOG(1) << "GATT descriptor not registered."; - error_callback.Run(); - return; - } - - // Pass on to the delegate. - DCHECK(delegate_); - delegate_->SetDescriptorValue(value, callback, error_callback); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.h b/chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.h deleted file mode 100644 index 054c21d..0000000 --- a/chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.h +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_ - -#include <string> -#include <vector> - -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_gatt_descriptor_service_provider.h" -#include "dbus/object_path.h" - -namespace chromeos { - -// FakeBluetoothGattDescriptorServiceProvider simulates behavior of a local -// GATT descriptor object and is used both in test cases in place of a mock -// and on the Linux desktop. -class CHROMEOS_EXPORT FakeBluetoothGattDescriptorServiceProvider - : public BluetoothGattDescriptorServiceProvider { - public: - FakeBluetoothGattDescriptorServiceProvider( - const dbus::ObjectPath& object_path, - Delegate* delegate, - const std::string& uuid, - const std::vector<std::string>& permissions, - const dbus::ObjectPath& characteristic_path); - ~FakeBluetoothGattDescriptorServiceProvider() override; - - // BluetoothGattDescriptorServiceProvider override. - void SendValueChanged(const std::vector<uint8>& value) override; - - // Methods to simulate value get/set requests issued from a remote device. The - // methods do nothing, if the associated service was not registered with the - // GATT manager. - void GetValue(const Delegate::ValueCallback& callback, - const Delegate::ErrorCallback& error_callback); - void SetValue(const std::vector<uint8>& value, - const base::Closure& callback, - const Delegate::ErrorCallback& error_callback); - - const dbus::ObjectPath& object_path() const { return object_path_; } - const std::string& uuid() const { return uuid_; } - const dbus::ObjectPath& characteristic_path() const { - return characteristic_path_; - } - - private: - // D-Bus object path of the fake GATT descriptor. - dbus::ObjectPath object_path_; - - // 128-bit GATT descriptor UUID. - std::string uuid_; - - // Object path of the characteristic that this descriptor belongs to. - dbus::ObjectPath characteristic_path_; - - // The delegate that method calls are passed on to. - Delegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattDescriptorServiceProvider); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/fake_bluetooth_gatt_manager_client.cc b/chromeos/dbus/fake_bluetooth_gatt_manager_client.cc deleted file mode 100644 index 1127eae..0000000 --- a/chromeos/dbus/fake_bluetooth_gatt_manager_client.cc +++ /dev/null
@@ -1,169 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/fake_bluetooth_gatt_manager_client.h" - -#include "base/logging.h" -#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.h" -#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.h" -#include "chromeos/dbus/fake_bluetooth_gatt_service_service_provider.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -FakeBluetoothGattManagerClient::FakeBluetoothGattManagerClient() {} - -FakeBluetoothGattManagerClient::~FakeBluetoothGattManagerClient() {} - -// DBusClient override. -void FakeBluetoothGattManagerClient::Init(dbus::Bus* bus) {} - -// BluetoothGattManagerClient overrides. -void FakeBluetoothGattManagerClient::RegisterService( - const dbus::ObjectPath& service_path, - const Options& options, - const base::Closure& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "Register GATT service: " << service_path.value(); - - // If a service provider wasn't created before, return error. - ServiceMap::iterator iter = service_map_.find(service_path); - if (iter == service_map_.end()) { - error_callback.Run(bluetooth_gatt_manager::kErrorInvalidArguments, - "GATT service doesn't exist: " + service_path.value()); - return; - } - - // Check to see if this GATT service was already registered. - ServiceProvider* provider = &iter->second; - if (provider->first) { - error_callback.Run( - bluetooth_gatt_manager::kErrorAlreadyExists, - "GATT service already registered: " + service_path.value()); - return; - } - - // Success! - provider->first = true; - callback.Run(); -} - -void FakeBluetoothGattManagerClient::UnregisterService( - const dbus::ObjectPath& service_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "Unregister GATT service: " << service_path.value(); - - // If a service provider wasn't created before, return error. - ServiceMap::iterator iter = service_map_.find(service_path); - if (iter == service_map_.end()) { - error_callback.Run(bluetooth_gatt_manager::kErrorInvalidArguments, - "GATT service doesn't exist: " + service_path.value()); - return; - } - - // Return error if the GATT service wasn't registered before. - ServiceProvider* provider = &iter->second; - if (!provider->first) { - error_callback.Run(bluetooth_gatt_manager::kErrorDoesNotExist, - "GATT service not registered: " + service_path.value()); - return; - } - - // Success! - provider->first = false; - callback.Run(); -} - -void FakeBluetoothGattManagerClient::RegisterServiceServiceProvider( - FakeBluetoothGattServiceServiceProvider* provider) { - // Ignore, if a service provider is already registered for the object path. - ServiceMap::iterator iter = service_map_.find(provider->object_path()); - if (iter != service_map_.end()) { - VLOG(1) << "GATT service service provider already registered for " - << "object path: " << provider->object_path().value(); - return; - } - service_map_[provider->object_path()] = std::make_pair(false, provider); -} - -void FakeBluetoothGattManagerClient::RegisterCharacteristicServiceProvider( - FakeBluetoothGattCharacteristicServiceProvider* provider) { - // Ignore, if a service provider is already registered for the object path. - CharacteristicMap::iterator iter = - characteristic_map_.find(provider->object_path()); - if (iter != characteristic_map_.end()) { - VLOG(1) << "GATT characteristic service provider already registered for " - << "object path: " << provider->object_path().value(); - return; - } - characteristic_map_[provider->object_path()] = provider; -} - -void FakeBluetoothGattManagerClient::RegisterDescriptorServiceProvider( - FakeBluetoothGattDescriptorServiceProvider* provider) { - // Ignore, if a service provider is already registered for the object path. - DescriptorMap::iterator iter = descriptor_map_.find(provider->object_path()); - if (iter != descriptor_map_.end()) { - VLOG(1) << "GATT descriptor service provider already registered for " - << "object path: " << provider->object_path().value(); - return; - } - descriptor_map_[provider->object_path()] = provider; -} - -void FakeBluetoothGattManagerClient::UnregisterServiceServiceProvider( - FakeBluetoothGattServiceServiceProvider* provider) { - ServiceMap::iterator iter = service_map_.find(provider->object_path()); - if (iter != service_map_.end() && iter->second.second == provider) - service_map_.erase(iter); -} - -void FakeBluetoothGattManagerClient::UnregisterCharacteristicServiceProvider( - FakeBluetoothGattCharacteristicServiceProvider* provider) { - characteristic_map_.erase(provider->object_path()); -} - -void FakeBluetoothGattManagerClient::UnregisterDescriptorServiceProvider( - FakeBluetoothGattDescriptorServiceProvider* provider) { - descriptor_map_.erase(provider->object_path()); -} - -FakeBluetoothGattServiceServiceProvider* -FakeBluetoothGattManagerClient::GetServiceServiceProvider( - const dbus::ObjectPath& object_path) const { - ServiceMap::const_iterator iter = service_map_.find(object_path); - if (iter == service_map_.end()) - return NULL; - return iter->second.second; -} - -FakeBluetoothGattCharacteristicServiceProvider* -FakeBluetoothGattManagerClient::GetCharacteristicServiceProvider( - const dbus::ObjectPath& object_path) const { - CharacteristicMap::const_iterator iter = - characteristic_map_.find(object_path); - if (iter == characteristic_map_.end()) - return NULL; - return iter->second; -} - -FakeBluetoothGattDescriptorServiceProvider* -FakeBluetoothGattManagerClient::GetDescriptorServiceProvider( - const dbus::ObjectPath& object_path) const { - DescriptorMap::const_iterator iter = descriptor_map_.find(object_path); - if (iter == descriptor_map_.end()) - return NULL; - return iter->second; -} - -bool FakeBluetoothGattManagerClient::IsServiceRegistered( - const dbus::ObjectPath& object_path) const { - ServiceMap::const_iterator iter = service_map_.find(object_path); - if (iter == service_map_.end()) - return false; - return iter->second.first; -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_gatt_manager_client.h b/chromeos/dbus/fake_bluetooth_gatt_manager_client.h deleted file mode 100644 index cd5d3b0..0000000 --- a/chromeos/dbus/fake_bluetooth_gatt_manager_client.h +++ /dev/null
@@ -1,100 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_MANAGER_CLIENT_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_MANAGER_CLIENT_H_ - -#include <map> -#include <string> -#include <utility> - -#include "base/callback.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_gatt_manager_client.h" -#include "dbus/object_path.h" - -namespace chromeos { - -class FakeBluetoothGattCharacteristicServiceProvider; -class FakeBluetoothGattDescriptorServiceProvider; -class FakeBluetoothGattServiceServiceProvider; - -// FakeBluetoothGattManagerClient simulates the behavior of the Bluetooth -// daemon's GATT manager object and is used both in test cases in place of a -// mock and on the Linux desktop. -class CHROMEOS_EXPORT FakeBluetoothGattManagerClient - : public BluetoothGattManagerClient { - public: - FakeBluetoothGattManagerClient(); - ~FakeBluetoothGattManagerClient() override; - - // DBusClient override. - void Init(dbus::Bus* bus) override; - - // BluetoothGattManagerClient overrides. - void RegisterService(const dbus::ObjectPath& service_path, - const Options& options, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - void UnregisterService(const dbus::ObjectPath& service_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - - // Register, unregister, and retrieve pointers to service, characteristic, and - // descriptor service providers. Automatically called from the service - // provider constructor and destructors. - void RegisterServiceServiceProvider( - FakeBluetoothGattServiceServiceProvider* provider); - void RegisterCharacteristicServiceProvider( - FakeBluetoothGattCharacteristicServiceProvider* provider); - void RegisterDescriptorServiceProvider( - FakeBluetoothGattDescriptorServiceProvider* provider); - - void UnregisterServiceServiceProvider( - FakeBluetoothGattServiceServiceProvider* provider); - void UnregisterCharacteristicServiceProvider( - FakeBluetoothGattCharacteristicServiceProvider* provider); - void UnregisterDescriptorServiceProvider( - FakeBluetoothGattDescriptorServiceProvider* provider); - - // Return a pointer to the service provider that corresponds to the object - // path |object_path| if it exists. - FakeBluetoothGattServiceServiceProvider* GetServiceServiceProvider( - const dbus::ObjectPath& object_path) const; - FakeBluetoothGattCharacteristicServiceProvider* - GetCharacteristicServiceProvider(const dbus::ObjectPath& object_path) const; - FakeBluetoothGattDescriptorServiceProvider* GetDescriptorServiceProvider( - const dbus::ObjectPath& object_path) const; - - // Returns true, if a GATT service with object path |object_path| was - // registered with the GATT manager using RegisterService. - bool IsServiceRegistered(const dbus::ObjectPath& object_path) const; - - private: - // Mappings for GATT service, characteristic, and descriptor service - // providers. The fake GATT manager stores references to all instances - // created so that they can be obtained by tests. - typedef std::map<dbus::ObjectPath, - FakeBluetoothGattCharacteristicServiceProvider*> - CharacteristicMap; - typedef std::map<dbus::ObjectPath, - FakeBluetoothGattDescriptorServiceProvider*> DescriptorMap; - - // The mapping for services is from object paths to pairs of boolean and - // service provider pointer, where the boolean denotes whether or not the - // service is already registered. - typedef std::pair<bool, FakeBluetoothGattServiceServiceProvider*> - ServiceProvider; - typedef std::map<dbus::ObjectPath, ServiceProvider> ServiceMap; - - ServiceMap service_map_; - CharacteristicMap characteristic_map_; - DescriptorMap descriptor_map_; - - DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattManagerClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_gatt_service_client.cc b/chromeos/dbus/fake_bluetooth_gatt_service_client.cc deleted file mode 100644 index 47b39b6..0000000 --- a/chromeos/dbus/fake_bluetooth_gatt_service_client.cc +++ /dev/null
@@ -1,187 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h" - -#include "base/bind.h" -#include "base/location.h" -#include "base/single_thread_task_runner.h" -#include "base/thread_task_runner_handle.h" -#include "base/time/time.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -namespace { - -const int kExposeCharacteristicsDelayIntervalMs = 100; - -} // namespace - -// static -const char FakeBluetoothGattServiceClient::kHeartRateServicePathComponent[] = - "service0000"; -const char FakeBluetoothGattServiceClient::kHeartRateServiceUUID[] = - "0000180d-0000-1000-8000-00805f9b34fb"; - -FakeBluetoothGattServiceClient::Properties::Properties( - const PropertyChangedCallback& callback) - : BluetoothGattServiceClient::Properties( - NULL, - bluetooth_gatt_service::kBluetoothGattServiceInterface, - callback) {} - -FakeBluetoothGattServiceClient::Properties::~Properties() {} - -void FakeBluetoothGattServiceClient::Properties::Get( - dbus::PropertyBase* property, - dbus::PropertySet::GetCallback callback) { - VLOG(1) << "Get " << property->name(); - callback.Run(false); -} - -void FakeBluetoothGattServiceClient::Properties::GetAll() { - VLOG(1) << "GetAll"; -} - -void FakeBluetoothGattServiceClient::Properties::Set( - dbus::PropertyBase* property, - dbus::PropertySet::GetCallback callback) { - VLOG(1) << "Set " << property->name(); - callback.Run(false); -} - -FakeBluetoothGattServiceClient::FakeBluetoothGattServiceClient() - : weak_ptr_factory_(this) {} - -FakeBluetoothGattServiceClient::~FakeBluetoothGattServiceClient() {} - -void FakeBluetoothGattServiceClient::Init(dbus::Bus* bus) {} - -void FakeBluetoothGattServiceClient::AddObserver(Observer* observer) { - observers_.AddObserver(observer); -} - -void FakeBluetoothGattServiceClient::RemoveObserver(Observer* observer) { - observers_.RemoveObserver(observer); -} - -std::vector<dbus::ObjectPath> FakeBluetoothGattServiceClient::GetServices() { - std::vector<dbus::ObjectPath> paths; - if (heart_rate_service_properties_.get()) { - DCHECK(!heart_rate_service_path_.empty()); - paths.push_back(dbus::ObjectPath(heart_rate_service_path_)); - } - return paths; -} - -FakeBluetoothGattServiceClient::Properties* -FakeBluetoothGattServiceClient::GetProperties( - const dbus::ObjectPath& object_path) { - if (object_path.value() == heart_rate_service_path_) - return heart_rate_service_properties_.get(); - return NULL; -} - -void FakeBluetoothGattServiceClient::ExposeHeartRateService( - const dbus::ObjectPath& device_path) { - if (IsHeartRateVisible()) { - DCHECK(!heart_rate_service_path_.empty()); - VLOG(1) << "Fake Heart Rate Service already exposed."; - return; - } - VLOG(2) << "Exposing fake Heart Rate Service."; - heart_rate_service_path_ = - device_path.value() + "/" + kHeartRateServicePathComponent; - heart_rate_service_properties_.reset(new Properties(base::Bind( - &FakeBluetoothGattServiceClient::OnPropertyChanged, - base::Unretained(this), dbus::ObjectPath(heart_rate_service_path_)))); - heart_rate_service_properties_->uuid.ReplaceValue(kHeartRateServiceUUID); - heart_rate_service_properties_->device.ReplaceValue(device_path); - heart_rate_service_properties_->primary.ReplaceValue(true); - - NotifyServiceAdded(dbus::ObjectPath(heart_rate_service_path_)); - - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind( - &FakeBluetoothGattServiceClient::ExposeHeartRateCharacteristics, - weak_ptr_factory_.GetWeakPtr()), - base::TimeDelta::FromMilliseconds(kExposeCharacteristicsDelayIntervalMs)); -} - -void FakeBluetoothGattServiceClient::HideHeartRateService() { - if (!IsHeartRateVisible()) { - DCHECK(heart_rate_service_path_.empty()); - VLOG(1) << "Fake Heart Rate Service already hidden."; - return; - } - VLOG(2) << "Hiding fake Heart Rate Service."; - FakeBluetoothGattCharacteristicClient* char_client = - static_cast<FakeBluetoothGattCharacteristicClient*>( - DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()); - char_client->HideHeartRateCharacteristics(); - - // Notify observers before deleting the properties structure so that it - // can be accessed from the observer method. - NotifyServiceRemoved(dbus::ObjectPath(heart_rate_service_path_)); - - heart_rate_service_properties_.reset(); - heart_rate_service_path_.clear(); -} - -bool FakeBluetoothGattServiceClient::IsHeartRateVisible() const { - return !!heart_rate_service_properties_.get(); -} - -dbus::ObjectPath FakeBluetoothGattServiceClient::GetHeartRateServicePath() - const { - return dbus::ObjectPath(heart_rate_service_path_); -} - -void FakeBluetoothGattServiceClient::OnPropertyChanged( - const dbus::ObjectPath& object_path, - const std::string& property_name) { - VLOG(2) << "Fake GATT Service property changed: " << object_path.value() - << ": " << property_name; - FOR_EACH_OBSERVER(BluetoothGattServiceClient::Observer, observers_, - GattServicePropertyChanged(object_path, property_name)); -} - -void FakeBluetoothGattServiceClient::NotifyServiceAdded( - const dbus::ObjectPath& object_path) { - VLOG(2) << "GATT service added: " << object_path.value(); - FOR_EACH_OBSERVER(BluetoothGattServiceClient::Observer, observers_, - GattServiceAdded(object_path)); -} - -void FakeBluetoothGattServiceClient::NotifyServiceRemoved( - const dbus::ObjectPath& object_path) { - VLOG(2) << "GATT service removed: " << object_path.value(); - FOR_EACH_OBSERVER(BluetoothGattServiceClient::Observer, observers_, - GattServiceRemoved(object_path)); -} - -void FakeBluetoothGattServiceClient::ExposeHeartRateCharacteristics() { - if (!IsHeartRateVisible()) { - VLOG(2) << "Heart Rate service not visible. Not exposing characteristics."; - return; - } - FakeBluetoothGattCharacteristicClient* char_client = - static_cast<FakeBluetoothGattCharacteristicClient*>( - DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()); - char_client->ExposeHeartRateCharacteristics( - dbus::ObjectPath(heart_rate_service_path_)); - - std::vector<dbus::ObjectPath> char_paths; - char_paths.push_back(char_client->GetHeartRateMeasurementPath()); - char_paths.push_back(char_client->GetBodySensorLocationPath()); - char_paths.push_back(char_client->GetHeartRateControlPointPath()); - - heart_rate_service_properties_->characteristics.ReplaceValue(char_paths); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_gatt_service_client.h b/chromeos/dbus/fake_bluetooth_gatt_service_client.h deleted file mode 100644 index f719727..0000000 --- a/chromeos/dbus/fake_bluetooth_gatt_service_client.h +++ /dev/null
@@ -1,106 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_SERVICE_CLIENT_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_SERVICE_CLIENT_H_ - -#include <string> -#include <vector> - -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/observer_list.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_gatt_service_client.h" -#include "dbus/object_path.h" -#include "dbus/property.h" - -namespace chromeos { - -// FakeBluetoothGattServiceClient simulates the behavior of the Bluetooth Daemon -// GATT service objects and is used in test cases in place of a mock and on the -// Linux desktop. -class CHROMEOS_EXPORT FakeBluetoothGattServiceClient - : public BluetoothGattServiceClient { - public: - struct Properties : public BluetoothGattServiceClient::Properties { - explicit Properties(const PropertyChangedCallback& callback); - ~Properties() override; - - // dbus::PropertySet override - void Get(dbus::PropertyBase* property, - dbus::PropertySet::GetCallback callback) override; - void GetAll() override; - void Set(dbus::PropertyBase* property, - dbus::PropertySet::SetCallback callback) override; - }; - - FakeBluetoothGattServiceClient(); - ~FakeBluetoothGattServiceClient() override; - - // DBusClient override. - void Init(dbus::Bus* bus) override; - - // BluetoothGattServiceClient overrides. - void AddObserver(Observer* observer) override; - void RemoveObserver(Observer* observer) override; - std::vector<dbus::ObjectPath> GetServices() override; - Properties* GetProperties(const dbus::ObjectPath& object_path) override; - - // Makes a service visible for device with object path |device_path|. Note - // that only one instance of a specific service is simulated at a time. Hence, - // this method will fail, if the service is already visible. - void ExposeHeartRateService(const dbus::ObjectPath& device_path); - void HideHeartRateService(); - - // Returns whether or not the Heart Rate Service is visible. - bool IsHeartRateVisible() const; - - // Returns the current object path of the visible Heart Rate service. If the - // service is not visible, returns an invalid empty path. - dbus::ObjectPath GetHeartRateServicePath() const; - - // Final object path components and the corresponding UUIDs of the GATT - // services that we emulate. Service paths are hierarchical to Bluetooth - // device paths, so if the path component is "service0000", and the device - // path is "/org/foo/device0", the service path is - // "/org/foo/device0/service0000". - static const char kHeartRateServicePathComponent[]; - static const char kHeartRateServiceUUID[]; - - private: - // Property callback passed when we create Properties structures. - void OnPropertyChanged(const dbus::ObjectPath& object_path, - const std::string& property_name); - - // Notifies observers. - void NotifyServiceAdded(const dbus::ObjectPath& object_path); - void NotifyServiceRemoved(const dbus::ObjectPath& object_path); - - // Tells FakeBluetoothGattCharacteristicClient to expose GATT characteristics. - // This is scheduled from ExposeHeartRateService to simulate asynchronous - // retrieval of characteristics. If the Heart Rate Service is hidden at the - // time this method is called, then it does nothing. - void ExposeHeartRateCharacteristics(); - - // Static properties we return. As long as a service is exposed, this will be - // non-null. Otherwise it will be null. - scoped_ptr<Properties> heart_rate_service_properties_; - std::string heart_rate_service_path_; - - // List of observers interested in event notifications from us. - base::ObserverList<Observer> observers_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than we do. - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<FakeBluetoothGattServiceClient> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattServiceClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_SERVICE_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_gatt_service_service_provider.cc b/chromeos/dbus/fake_bluetooth_gatt_service_service_provider.cc deleted file mode 100644 index f59cf98..0000000 --- a/chromeos/dbus/fake_bluetooth_gatt_service_service_provider.cc +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/fake_bluetooth_gatt_service_service_provider.h" - -#include "base/logging.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_gatt_manager_client.h" - -namespace chromeos { - -FakeBluetoothGattServiceServiceProvider:: - FakeBluetoothGattServiceServiceProvider( - const dbus::ObjectPath& object_path, - const std::string& uuid, - const std::vector<dbus::ObjectPath>& includes) - : object_path_(object_path), uuid_(uuid), includes_(includes) { - VLOG(1) << "Creating Bluetooth GATT service: " << object_path_.value(); - - FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = - static_cast<FakeBluetoothGattManagerClient*>( - DBusThreadManager::Get()->GetBluetoothGattManagerClient()); - fake_bluetooth_gatt_manager_client->RegisterServiceServiceProvider(this); -} - -FakeBluetoothGattServiceServiceProvider:: - ~FakeBluetoothGattServiceServiceProvider() { - VLOG(1) << "Cleaning up Bluetooth GATT service: " << object_path_.value(); - - FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = - static_cast<FakeBluetoothGattManagerClient*>( - DBusThreadManager::Get()->GetBluetoothGattManagerClient()); - fake_bluetooth_gatt_manager_client->UnregisterServiceServiceProvider(this); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_gatt_service_service_provider.h b/chromeos/dbus/fake_bluetooth_gatt_service_service_provider.h deleted file mode 100644 index 6b49d78..0000000 --- a/chromeos/dbus/fake_bluetooth_gatt_service_service_provider.h +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_ - -#include <string> -#include <vector> - -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_gatt_service_service_provider.h" -#include "dbus/object_path.h" - -namespace chromeos { - -// FakeBluetoothGattServiceServiceProvider simulates behavior of a local GATT -// service object and is used both in test cases in place of a mock and on the -// Linux desktop. -class CHROMEOS_EXPORT FakeBluetoothGattServiceServiceProvider - : public BluetoothGattServiceServiceProvider { - public: - FakeBluetoothGattServiceServiceProvider( - const dbus::ObjectPath& object_path, - const std::string& uuid, - const std::vector<dbus::ObjectPath>& includes); - ~FakeBluetoothGattServiceServiceProvider() override; - - const dbus::ObjectPath& object_path() const { return object_path_; } - const std::string& uuid() const { return uuid_; } - - private: - // D-Bus object path of the fake GATT service. - dbus::ObjectPath object_path_; - - // 128-bit GATT service UUID. - std::string uuid_; - - // List of included GATT services. - std::vector<dbus::ObjectPath> includes_; - - DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattServiceServiceProvider); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/fake_bluetooth_input_client.cc b/chromeos/dbus/fake_bluetooth_input_client.cc deleted file mode 100644 index ab2c66b3..0000000 --- a/chromeos/dbus/fake_bluetooth_input_client.cc +++ /dev/null
@@ -1,123 +0,0 @@ -// Copyright (c) 2013 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 "chromeos/dbus/fake_bluetooth_input_client.h" - -#include <map> - -#include "base/logging.h" -#include "base/stl_util.h" -#include "chromeos/dbus/fake_bluetooth_device_client.h" -#include "dbus/bus.h" -#include "dbus/message.h" -#include "dbus/object_manager.h" -#include "dbus/object_proxy.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -FakeBluetoothInputClient::Properties::Properties( - const PropertyChangedCallback& callback) - : BluetoothInputClient::Properties( - NULL, - bluetooth_input::kBluetoothInputInterface, - callback) {} - -FakeBluetoothInputClient::Properties::~Properties() {} - -void FakeBluetoothInputClient::Properties::Get( - dbus::PropertyBase* property, - dbus::PropertySet::GetCallback callback) { - VLOG(1) << "Get " << property->name(); - callback.Run(false); -} - -void FakeBluetoothInputClient::Properties::GetAll() { - VLOG(1) << "GetAll"; -} - -void FakeBluetoothInputClient::Properties::Set( - dbus::PropertyBase* property, - dbus::PropertySet::SetCallback callback) { - VLOG(1) << "Set " << property->name(); - callback.Run(false); -} - -FakeBluetoothInputClient::FakeBluetoothInputClient() {} - -FakeBluetoothInputClient::~FakeBluetoothInputClient() { - // Clean up Properties structures - STLDeleteValues(&properties_map_); -} - -void FakeBluetoothInputClient::Init(dbus::Bus* bus) {} - -void FakeBluetoothInputClient::AddObserver(Observer* observer) { - observers_.AddObserver(observer); -} - -void FakeBluetoothInputClient::RemoveObserver(Observer* observer) { - observers_.RemoveObserver(observer); -} - -FakeBluetoothInputClient::Properties* FakeBluetoothInputClient::GetProperties( - const dbus::ObjectPath& object_path) { - PropertiesMap::iterator iter = properties_map_.find(object_path); - if (iter != properties_map_.end()) - return iter->second; - return NULL; -} - -void FakeBluetoothInputClient::AddInputDevice( - const dbus::ObjectPath& object_path) { - if (properties_map_.find(object_path) != properties_map_.end()) - return; - - Properties* properties = - new Properties(base::Bind(&FakeBluetoothInputClient::OnPropertyChanged, - base::Unretained(this), object_path)); - - // The LegacyAutopair and DisplayPinCode devices represent a typical mouse - // and keyboard respectively, so mark them as ReconnectMode "any". The - // DisplayPasskey device represents a Bluetooth 2.1+ keyboard and the - // ConnectUnpairable device represents a pre-standardization mouse, so mark - // them as ReconnectMode "device". - if (object_path.value() == FakeBluetoothDeviceClient::kDisplayPasskeyPath || - object_path.value() == - FakeBluetoothDeviceClient::kConnectUnpairablePath) { - properties->reconnect_mode.ReplaceValue( - bluetooth_input::kDeviceReconnectModeProperty); - } else { - properties->reconnect_mode.ReplaceValue( - bluetooth_input::kAnyReconnectModeProperty); - } - - properties_map_[object_path] = properties; - - FOR_EACH_OBSERVER(BluetoothInputClient::Observer, observers_, - InputAdded(object_path)); -} - -void FakeBluetoothInputClient::RemoveInputDevice( - const dbus::ObjectPath& object_path) { - PropertiesMap::iterator it = properties_map_.find(object_path); - - if (it == properties_map_.end()) - return; - - FOR_EACH_OBSERVER(BluetoothInputClient::Observer, observers_, - InputRemoved(object_path)); - - delete it->second; - properties_map_.erase(it); -} - -void FakeBluetoothInputClient::OnPropertyChanged( - const dbus::ObjectPath& object_path, - const std::string& property_name) { - FOR_EACH_OBSERVER(BluetoothInputClient::Observer, observers_, - InputPropertyChanged(object_path, property_name)); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_input_client.h b/chromeos/dbus/fake_bluetooth_input_client.h deleted file mode 100644 index 22369eb..0000000 --- a/chromeos/dbus/fake_bluetooth_input_client.h +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright (c) 2013 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 CHROMEOS_DBUS_FAKE_BLUETOOTH_INPUT_CLIENT_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_INPUT_CLIENT_H_ - -#include "base/callback.h" -#include "base/observer_list.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_input_client.h" -#include "dbus/object_path.h" -#include "dbus/property.h" - -namespace chromeos { - -// FakeBluetoothInputClient simulates the behavior of the Bluetooth Daemon -// input device objects and is used both in test cases in place of a mock and on -// the Linux desktop. -class CHROMEOS_EXPORT FakeBluetoothInputClient : public BluetoothInputClient { - public: - struct Properties : public BluetoothInputClient::Properties { - explicit Properties(const PropertyChangedCallback& callback); - ~Properties() override; - - // dbus::PropertySet override - void Get(dbus::PropertyBase* property, - dbus::PropertySet::GetCallback callback) override; - void GetAll() override; - void Set(dbus::PropertyBase* property, - dbus::PropertySet::SetCallback callback) override; - }; - - FakeBluetoothInputClient(); - ~FakeBluetoothInputClient() override; - - // BluetoothInputClient overrides - void Init(dbus::Bus* bus) override; - void AddObserver(Observer* observer) override; - void RemoveObserver(Observer* observer) override; - Properties* GetProperties(const dbus::ObjectPath& object_path) override; - - // Simulate device addition/removal - void AddInputDevice(const dbus::ObjectPath& object_path); - void RemoveInputDevice(const dbus::ObjectPath& object_path); - - private: - // Property callback passed when we create Properties* structures. - void OnPropertyChanged(const dbus::ObjectPath& object_path, - const std::string& property_name); - - // Static properties we return. - typedef std::map<const dbus::ObjectPath, Properties*> PropertiesMap; - PropertiesMap properties_map_; - - // List of observers interested in event notifications from us. - base::ObserverList<Observer> observers_; - - DISALLOW_COPY_AND_ASSIGN(FakeBluetoothInputClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_INPUT_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.cc b/chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.cc deleted file mode 100644 index ce46e3d..0000000 --- a/chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.cc +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright 2015 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 "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.h" -#include "chromeos/dbus/fake_bluetooth_le_advertising_manager_client.h" - -namespace chromeos { - -FakeBluetoothLEAdvertisementServiceProvider:: - FakeBluetoothLEAdvertisementServiceProvider( - const dbus::ObjectPath& object_path, - Delegate* delegate) - : delegate_(delegate) { - object_path_ = object_path; - VLOG(1) << "Creating Bluetooth Advertisement: " << object_path_.value(); - - FakeBluetoothLEAdvertisingManagerClient* - fake_bluetooth_profile_manager_client = - static_cast<FakeBluetoothLEAdvertisingManagerClient*>( - DBusThreadManager::Get() - ->GetBluetoothLEAdvertisingManagerClient()); - fake_bluetooth_profile_manager_client->RegisterAdvertisementServiceProvider( - this); -} - -FakeBluetoothLEAdvertisementServiceProvider:: - ~FakeBluetoothLEAdvertisementServiceProvider() { - VLOG(1) << "Cleaning up Bluetooth Advertisement: " << object_path_.value(); - - FakeBluetoothLEAdvertisingManagerClient* - fake_bluetooth_profile_manager_client = - static_cast<FakeBluetoothLEAdvertisingManagerClient*>( - DBusThreadManager::Get() - ->GetBluetoothLEAdvertisingManagerClient()); - fake_bluetooth_profile_manager_client->UnregisterAdvertisementServiceProvider( - this); -} - -void FakeBluetoothLEAdvertisementServiceProvider::Release() { - VLOG(1) << object_path_.value() << ": Release"; - delegate_->Released(); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.h b/chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.h deleted file mode 100644 index 5a19aeee..0000000 --- a/chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.h +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2015 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 CHROMEOS_DBUS_FAKE_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_ - -#include "base/bind.h" -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_le_advertisement_service_provider.h" -#include "dbus/file_descriptor.h" -#include "dbus/object_path.h" - -namespace chromeos { - -// FakeBluetoothAdvertisementServiceProvider simulates the behavior of a local -// Bluetooth agent object and is used both in test cases in place of a -// mock and on the Linux desktop. -class CHROMEOS_EXPORT FakeBluetoothLEAdvertisementServiceProvider - : public BluetoothLEAdvertisementServiceProvider { - public: - FakeBluetoothLEAdvertisementServiceProvider( - const dbus::ObjectPath& object_path, - Delegate* delegate); - ~FakeBluetoothLEAdvertisementServiceProvider() override; - - // Each of these calls the equivalent - // BluetoothAdvertisementServiceProvider::Delegate method on the object passed - // on construction. - void Release(); - - const dbus::ObjectPath& object_path() { return object_path_; } - - private: - friend class FakeBluetoothLEAdvertisingManagerClient; - - // All incoming method calls are passed on to the Delegate and a callback - // passed to generate the reply. |delegate_| is generally the object that - // owns this one, and must outlive it. - Delegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(FakeBluetoothLEAdvertisementServiceProvider); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/fake_bluetooth_le_advertising_manager_client.cc b/chromeos/dbus/fake_bluetooth_le_advertising_manager_client.cc deleted file mode 100644 index 201fc42..0000000 --- a/chromeos/dbus/fake_bluetooth_le_advertising_manager_client.cc +++ /dev/null
@@ -1,101 +0,0 @@ -// Copyright 2015 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 "base/location.h" -#include "base/logging.h" -#include "base/single_thread_task_runner.h" -#include "base/thread_task_runner_handle.h" -#include "dbus/bus.h" -#include "dbus/message.h" -#include "dbus/object_proxy.h" -#include "fake_bluetooth_le_advertisement_service_provider.h" -#include "fake_bluetooth_le_advertising_manager_client.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -const char FakeBluetoothLEAdvertisingManagerClient::kAdvertisingManagerPath[] = - "/fake/hci0"; - -FakeBluetoothLEAdvertisingManagerClient:: - FakeBluetoothLEAdvertisingManagerClient() {} - -FakeBluetoothLEAdvertisingManagerClient:: - ~FakeBluetoothLEAdvertisingManagerClient() {} - -void FakeBluetoothLEAdvertisingManagerClient::Init(dbus::Bus* bus) {} - -void FakeBluetoothLEAdvertisingManagerClient::AddObserver(Observer* observer) {} - -void FakeBluetoothLEAdvertisingManagerClient::RemoveObserver( - Observer* observer) {} - -void FakeBluetoothLEAdvertisingManagerClient::RegisterAdvertisement( - const dbus::ObjectPath& manager_object_path, - const dbus::ObjectPath& advertisement_object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "RegisterAdvertisment: " << advertisement_object_path.value(); - - if (manager_object_path != dbus::ObjectPath(kAdvertisingManagerPath)) { - error_callback.Run(kNoResponseError, "Invalid Advertising Manager path."); - return; - } - - ServiceProviderMap::iterator iter = - service_provider_map_.find(advertisement_object_path); - if (iter == service_provider_map_.end()) { - error_callback.Run(bluetooth_advertising_manager::kErrorInvalidArguments, - "Advertisement object not registered"); - } else if (!currently_registered_.value().empty()) { - error_callback.Run(bluetooth_advertising_manager::kErrorFailed, - "Maximum advertisements reached"); - } else { - currently_registered_ = advertisement_object_path; - base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); - } -} - -void FakeBluetoothLEAdvertisingManagerClient::UnregisterAdvertisement( - const dbus::ObjectPath& manager_object_path, - const dbus::ObjectPath& advertisement_object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "UnregisterAdvertisment: " << advertisement_object_path.value(); - - if (manager_object_path != dbus::ObjectPath(kAdvertisingManagerPath)) { - error_callback.Run(kNoResponseError, "Invalid Advertising Manager path."); - return; - } - - ServiceProviderMap::iterator iter = - service_provider_map_.find(advertisement_object_path); - if (iter == service_provider_map_.end()) { - error_callback.Run(bluetooth_advertising_manager::kErrorDoesNotExist, - "Advertisement not registered"); - } else if (advertisement_object_path != currently_registered_) { - error_callback.Run(bluetooth_advertising_manager::kErrorDoesNotExist, - "Does not exist"); - } else { - currently_registered_ = dbus::ObjectPath(""); - base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); - } -} - -void FakeBluetoothLEAdvertisingManagerClient:: - RegisterAdvertisementServiceProvider( - FakeBluetoothLEAdvertisementServiceProvider* service_provider) { - service_provider_map_[service_provider->object_path_] = service_provider; -} - -void FakeBluetoothLEAdvertisingManagerClient:: - UnregisterAdvertisementServiceProvider( - FakeBluetoothLEAdvertisementServiceProvider* service_provider) { - ServiceProviderMap::iterator iter = - service_provider_map_.find(service_provider->object_path_); - if (iter != service_provider_map_.end() && iter->second == service_provider) - service_provider_map_.erase(iter); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_le_advertising_manager_client.h b/chromeos/dbus/fake_bluetooth_le_advertising_manager_client.h deleted file mode 100644 index 5df129c..0000000 --- a/chromeos/dbus/fake_bluetooth_le_advertising_manager_client.h +++ /dev/null
@@ -1,79 +0,0 @@ -// Copyright 2015 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 CHROMEOS_DBUS_FAKE_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_ - -#include <map> -#include <string> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/observer_list.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_le_advertising_manager_client.h" -#include "dbus/object_path.h" -#include "dbus/property.h" - -namespace chromeos { - -class FakeBluetoothLEAdvertisementServiceProvider; - -// FakeBluetoothAdvertisementManagerClient simulates the behavior of the -// Bluetooth -// Daemon's profile manager object and is used both in test cases in place of a -// mock and on the Linux desktop. -class CHROMEOS_EXPORT FakeBluetoothLEAdvertisingManagerClient - : public BluetoothLEAdvertisingManagerClient { - public: - FakeBluetoothLEAdvertisingManagerClient(); - ~FakeBluetoothLEAdvertisingManagerClient() override; - - // DBusClient overrides: - void Init(dbus::Bus* bus) override; - - // BluetoothAdvertisingManagerClient overrides: - void AddObserver(Observer* observer) override; - void RemoveObserver(Observer* observer) override; - void RegisterAdvertisement(const dbus::ObjectPath& manager_object_path, - const dbus::ObjectPath& advertisement_object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - void UnregisterAdvertisement( - const dbus::ObjectPath& manager_object_path, - const dbus::ObjectPath& advertisement_object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - - // Register, unregister and retrieve pointers to profile server providers. - void RegisterAdvertisementServiceProvider( - FakeBluetoothLEAdvertisementServiceProvider* service_provider); - void UnregisterAdvertisementServiceProvider( - FakeBluetoothLEAdvertisementServiceProvider* service_provider); - FakeBluetoothLEAdvertisementServiceProvider* GetAdvertisementServiceProvider( - const std::string& uuid); - - // Advertising manager path that we simulate. - static const char kAdvertisingManagerPath[]; - - private: - // Map of a D-Bus object path to the FakeBluetoothAdvertisementServiceProvider - // registered for it; maintained by RegisterAdvertisementServiceProvider() and - // UnregisterProfileServiceProvicer() called by the constructor and - // destructor of FakeBluetoothAdvertisementServiceProvider. - typedef std::map<dbus::ObjectPath, - FakeBluetoothLEAdvertisementServiceProvider*> - ServiceProviderMap; - ServiceProviderMap service_provider_map_; - - // Holds the currently registered advertisement. If there is no advertisement - // registered, this path is empty. - dbus::ObjectPath currently_registered_; - - DISALLOW_COPY_AND_ASSIGN(FakeBluetoothLEAdvertisingManagerClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_media_client.cc b/chromeos/dbus/fake_bluetooth_media_client.cc deleted file mode 100644 index f9cfb5aa..0000000 --- a/chromeos/dbus/fake_bluetooth_media_client.cc +++ /dev/null
@@ -1,134 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/fake_bluetooth_media_client.h" - -#include <string> - -#include "base/stl_util.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_adapter_client.h" -#include "chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h" -#include "chromeos/dbus/fake_bluetooth_media_transport_client.h" - -using dbus::ObjectPath; - -namespace { - -// Except for |kFailedError|, the other error is defined in BlueZ D-Bus Media -// API. -const char kFailedError[] = "org.chromium.Error.Failed"; -const char kInvalidArgumentsError[] = "org.chromium.Error.InvalidArguments"; - -} // namespace - -namespace chromeos { - -// static -const uint8_t FakeBluetoothMediaClient::kDefaultCodec = 0x00; - -FakeBluetoothMediaClient::FakeBluetoothMediaClient() - : visible_(true), - object_path_(ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)) {} - -FakeBluetoothMediaClient::~FakeBluetoothMediaClient() {} - -void FakeBluetoothMediaClient::Init(dbus::Bus* bus) {} - -void FakeBluetoothMediaClient::AddObserver( - BluetoothMediaClient::Observer* observer) { - DCHECK(observer); - observers_.AddObserver(observer); -} - -void FakeBluetoothMediaClient::RemoveObserver( - BluetoothMediaClient::Observer* observer) { - DCHECK(observer); - observers_.RemoveObserver(observer); -} - -void FakeBluetoothMediaClient::RegisterEndpoint( - const ObjectPath& object_path, - const ObjectPath& endpoint_path, - const EndpointProperties& properties, - const base::Closure& callback, - const ErrorCallback& error_callback) { - if (!visible_) - return; - - VLOG(1) << "RegisterEndpoint: " << endpoint_path.value(); - - // The media client and adapter client should have the same object path. - if (object_path != object_path_ || - properties.uuid != BluetoothMediaClient::kBluetoothAudioSinkUUID || - properties.codec != kDefaultCodec || properties.capabilities.empty()) { - error_callback.Run(kInvalidArgumentsError, ""); - return; - } - - callback.Run(); -} - -void FakeBluetoothMediaClient::UnregisterEndpoint( - const ObjectPath& object_path, - const ObjectPath& endpoint_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - // TODO(mcchou): Come up with some corresponding actions. - VLOG(1) << "UnregisterEndpoint: " << endpoint_path.value(); - - if (!ContainsKey(endpoints_, endpoint_path)) { - error_callback.Run(kFailedError, "Unknown media endpoint"); - return; - } - - SetEndpointRegistered(endpoints_[endpoint_path], false); - callback.Run(); -} - -void FakeBluetoothMediaClient::SetVisible(bool visible) { - visible_ = visible; - - if (visible_) - return; - - // If the media object becomes invisible, an update chain will unregister all - // endpoints and set the associated transport objects to be invalid. - // SetEndpointRegistered will remove the endpoint entry from |endpoints_|. - while (endpoints_.begin() != endpoints_.end()) - SetEndpointRegistered(endpoints_.begin()->second, false); - - // Notifies observers about the change on |visible_|. - FOR_EACH_OBSERVER(BluetoothMediaClient::Observer, observers_, - MediaRemoved(object_path_)); -} - -void FakeBluetoothMediaClient::SetEndpointRegistered( - FakeBluetoothMediaEndpointServiceProvider* endpoint, - bool registered) { - if (registered) { - endpoints_[endpoint->object_path()] = endpoint; - return; - } - - if (!IsRegistered(endpoint->object_path())) - return; - - // Once a media endpoint object becomes invalid, invalidate the associated - // transport. - FakeBluetoothMediaTransportClient* transport = - static_cast<FakeBluetoothMediaTransportClient*>( - DBusThreadManager::Get()->GetBluetoothMediaTransportClient()); - transport->SetValid(endpoint, false); - - endpoints_.erase(endpoint->object_path()); - endpoint->Released(); -} - -bool FakeBluetoothMediaClient::IsRegistered( - const dbus::ObjectPath& endpoint_path) { - return ContainsKey(endpoints_, endpoint_path); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_media_client.h b/chromeos/dbus/fake_bluetooth_media_client.h deleted file mode 100644 index 3b4f4a7..0000000 --- a/chromeos/dbus/fake_bluetooth_media_client.h +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_MEDIA_CLIENT_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_MEDIA_CLIENT_H_ - -#include <map> - -#include "base/callback.h" -#include "base/observer_list.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_media_client.h" -#include "dbus/object_path.h" - -namespace chromeos { - -class FakeBluetoothMediaEndpointServiceProvider; - -class CHROMEOS_EXPORT FakeBluetoothMediaClient : public BluetoothMediaClient { - public: - // The default codec is SBC(0x00). - static const uint8_t kDefaultCodec; - - FakeBluetoothMediaClient(); - ~FakeBluetoothMediaClient() override; - - // DBusClient override. - void Init(dbus::Bus* bus) override; - - // BluetoothMediaClient overrides. - void AddObserver(BluetoothMediaClient::Observer* observer) override; - void RemoveObserver(BluetoothMediaClient::Observer* observer) override; - void RegisterEndpoint(const dbus::ObjectPath& object_path, - const dbus::ObjectPath& endpoint_path, - const EndpointProperties& properties, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - void UnregisterEndpoint(const dbus::ObjectPath& object_path, - const dbus::ObjectPath& endpoint_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - - // Makes the media object visible/invisible to emulate the addition/removal - // events. - void SetVisible(bool visible); - - // Sets the registration state for a given media endpoint. - void SetEndpointRegistered( - FakeBluetoothMediaEndpointServiceProvider* endpoint, - bool registered); - - // Indicates whether the given endpoint path is registered or not. - bool IsRegistered(const dbus::ObjectPath& endpoint_path); - - private: - // Indicates whether the media object is visible or not. - bool visible_; - - // The path of the media object. - dbus::ObjectPath object_path_; - - // Map of registered endpoints. Each pair is composed of an endpoint path as - // key and a pointer to the endpoint as value. - std::map<dbus::ObjectPath, FakeBluetoothMediaEndpointServiceProvider*> - endpoints_; - - // List of observers interested in event notifications from us. - base::ObserverList<BluetoothMediaClient::Observer> observers_; - - DISALLOW_COPY_AND_ASSIGN(FakeBluetoothMediaClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_MEDIA_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.cc b/chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.cc deleted file mode 100644 index a275374..0000000 --- a/chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.cc +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h" - -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_media_client.h" -#include "chromeos/dbus/fake_bluetooth_media_transport_client.h" - -using dbus::ObjectPath; - -namespace chromeos { - -FakeBluetoothMediaEndpointServiceProvider:: - FakeBluetoothMediaEndpointServiceProvider(const ObjectPath& object_path, - Delegate* delegate) - : visible_(false), object_path_(object_path), delegate_(delegate) { - VLOG(1) << "Create Bluetooth Media Endpoint: " << object_path_.value(); -} - -FakeBluetoothMediaEndpointServiceProvider:: - ~FakeBluetoothMediaEndpointServiceProvider() { - VLOG(1) << "Cleaning up Bluetooth Media Endpoint: " << object_path_.value(); -} - -void FakeBluetoothMediaEndpointServiceProvider::SetConfiguration( - const ObjectPath& transport_path, - const Delegate::TransportProperties& properties) { - VLOG(1) << object_path_.value() << ": SetConfiguration for " - << transport_path.value(); - - delegate_->SetConfiguration(transport_path, properties); -} - -void FakeBluetoothMediaEndpointServiceProvider::SelectConfiguration( - const std::vector<uint8_t>& capabilities, - const Delegate::SelectConfigurationCallback& callback) { - VLOG(1) << object_path_.value() << ": SelectConfiguration"; - - delegate_->SelectConfiguration(capabilities, callback); - - // Makes the transport object valid for the given endpoint path. - FakeBluetoothMediaTransportClient* transport = - static_cast<FakeBluetoothMediaTransportClient*>( - DBusThreadManager::Get()->GetBluetoothMediaTransportClient()); - DCHECK(transport); - transport->SetValid(this, true); -} - -void FakeBluetoothMediaEndpointServiceProvider::ClearConfiguration( - const ObjectPath& transport_path) { - VLOG(1) << object_path_.value() << ": ClearConfiguration on " - << transport_path.value(); - - delegate_->ClearConfiguration(transport_path); -} - -void FakeBluetoothMediaEndpointServiceProvider::Released() { - VLOG(1) << object_path_.value() << ": Released"; - - delegate_->Released(); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h b/chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h deleted file mode 100644 index 5efe14f..0000000 --- a/chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_ - -#include <vector> - -#include "base/logging.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_media_endpoint_service_provider.h" -#include "dbus/object_path.h" -#include "testing/gtest/include/gtest/gtest_prod.h" - -namespace chromeos { - -// FakeBluetoothMediaEndpointServiceProvider simulates the behavior of a local -// Bluetooth Media Endpoint object. -class CHROMEOS_EXPORT FakeBluetoothMediaEndpointServiceProvider - : public BluetoothMediaEndpointServiceProvider { - public: - FakeBluetoothMediaEndpointServiceProvider(const dbus::ObjectPath& object_path, - Delegate* delegate); - ~FakeBluetoothMediaEndpointServiceProvider() override; - - // Each of these calls the equivalent BluetoothMediaEnpointServiceProvider:: - // Delegate method on the object passed on construction. - void SetConfiguration(const dbus::ObjectPath& transport_path, - const Delegate::TransportProperties& properties); - void SelectConfiguration( - const std::vector<uint8_t>& capabilities, - const Delegate::SelectConfigurationCallback& callback); - void ClearConfiguration(const dbus::ObjectPath& transport_path); - void Released(); - - // Gets the path of the media endpoint object. - const dbus::ObjectPath& object_path() const { return object_path_; } - - private: - // Indicates whether the endpoint object is visible or not. - bool visible_; - - // The path of the media endpoint object. - dbus::ObjectPath object_path_; - - // All incoming method calls are passed to |delegate_|. |callback| passed to - // |delegate_| will generate the response for those methods which have - // non-void return. - Delegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(FakeBluetoothMediaEndpointServiceProvider); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/fake_bluetooth_media_transport_client.cc b/chromeos/dbus/fake_bluetooth_media_transport_client.cc deleted file mode 100644 index ae8f89b..0000000 --- a/chromeos/dbus/fake_bluetooth_media_transport_client.cc +++ /dev/null
@@ -1,328 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/dbus/fake_bluetooth_media_transport_client.h" - -#include <unistd.h> -#include <sys/socket.h> - -#include <sstream> - -#include "base/bind.h" -#include "base/stl_util.h" -#include "chromeos/dbus/bluetooth_media_client.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_adapter_client.h" -#include "chromeos/dbus/fake_bluetooth_media_client.h" -#include "chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h" -#include "dbus/file_descriptor.h" - -using dbus::ObjectPath; - -namespace { - -// TODO(mcchou): Remove this constants once it is in cros_system_api. -const char kBluetoothMediaTransportInterface[] = "org.bluez.MediaTransport1"; -const char kNotImplemented[] = "org.bluez.NotImplemented"; -const char kNotAuthorized[] = "org.bluez.NotAuthorized"; -const char kFailed[] = "org.bluez.Failed"; -const char kNotAvailable[] = "org.bluez.NotAvailable"; - -const int kInvalidFd = -1; - -ObjectPath GenerateTransportPath() { - static unsigned int sequence_number = 0; - ++sequence_number; - std::stringstream path; - path << chromeos::FakeBluetoothAdapterClient::kAdapterPath - << chromeos::FakeBluetoothMediaTransportClient::kTransportDevicePath - << "/fd" << sequence_number; - return ObjectPath(path.str()); -} - -#define UINT8_VECTOR_FROM_ARRAY(array) \ - std::vector<uint8_t>(array, array + arraysize(array)) - -} // namespace - -namespace chromeos { - -// static -const char FakeBluetoothMediaTransportClient::kTransportDevicePath[] = - "/fake_audio_source"; -const uint8_t FakeBluetoothMediaTransportClient::kTransportCodec = 0x00; -const uint8_t FakeBluetoothMediaTransportClient::kTransportConfiguration[] = { - 0x21, 0x15, 0x33, 0x2C}; -const uint8_t FakeBluetoothMediaTransportClient::kTransportConfigurationLength = - arraysize(FakeBluetoothMediaTransportClient::kTransportConfiguration); -const uint16_t FakeBluetoothMediaTransportClient::kTransportDelay = 5; -const uint16_t FakeBluetoothMediaTransportClient::kTransportVolume = 50; -const uint16_t FakeBluetoothMediaTransportClient::kDefaultReadMtu = 20; -const uint16_t FakeBluetoothMediaTransportClient::kDefaultWriteMtu = 25; - -FakeBluetoothMediaTransportClient::Properties::Properties( - const PropertyChangedCallback& callback) - : BluetoothMediaTransportClient::Properties( - nullptr, - kBluetoothMediaTransportInterface, - callback) {} - -FakeBluetoothMediaTransportClient::Properties::~Properties() {} - -void FakeBluetoothMediaTransportClient::Properties::Get( - dbus::PropertyBase* property, - dbus::PropertySet::GetCallback callback) { - VLOG(1) << "Get " << property->name(); - callback.Run(false); -} - -void FakeBluetoothMediaTransportClient::Properties::GetAll() { - VLOG(1) << "GetAll called."; -} - -void FakeBluetoothMediaTransportClient::Properties::Set( - dbus::PropertyBase* property, - dbus::PropertySet::SetCallback callback) { - VLOG(1) << "Set " << property->name(); - callback.Run(false); -} - -FakeBluetoothMediaTransportClient::Transport::Transport( - const ObjectPath& transport_path, - Properties* transport_properties) - : path(transport_path) { - properties.reset(transport_properties); -} - -FakeBluetoothMediaTransportClient::Transport::~Transport() {} - -FakeBluetoothMediaTransportClient::FakeBluetoothMediaTransportClient() {} - -FakeBluetoothMediaTransportClient::~FakeBluetoothMediaTransportClient() { - STLDeleteValues(&endpoint_to_transport_map_); -} - -// DBusClient override. -void FakeBluetoothMediaTransportClient::Init(dbus::Bus* bus) {} - -void FakeBluetoothMediaTransportClient::AddObserver( - BluetoothMediaTransportClient::Observer* observer) { - observers_.AddObserver(observer); -} - -void FakeBluetoothMediaTransportClient::RemoveObserver( - BluetoothMediaTransportClient::Observer* observer) { - observers_.RemoveObserver(observer); -} - -FakeBluetoothMediaTransportClient::Properties* -FakeBluetoothMediaTransportClient::GetProperties( - const ObjectPath& object_path) { - const ObjectPath& endpoint_path = GetEndpointPath(object_path); - Transport* transport = GetTransport(endpoint_path); - if (!transport) - return nullptr; - return transport->properties.get(); -} - -void FakeBluetoothMediaTransportClient::Acquire( - const ObjectPath& object_path, - const AcquireCallback& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "Acquire - transport path: " << object_path.value(); - AcquireInternal(false, object_path, callback, error_callback); -} - -void FakeBluetoothMediaTransportClient::TryAcquire( - const ObjectPath& object_path, - const AcquireCallback& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "TryAcquire - transport path: " << object_path.value(); - AcquireInternal(true, object_path, callback, error_callback); -} - -void FakeBluetoothMediaTransportClient::Release( - const ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - error_callback.Run(kNotImplemented, ""); -} - -void FakeBluetoothMediaTransportClient::SetValid( - FakeBluetoothMediaEndpointServiceProvider* endpoint, - bool valid) { - FakeBluetoothMediaClient* media = static_cast<FakeBluetoothMediaClient*>( - DBusThreadManager::Get()->GetBluetoothMediaClient()); - DCHECK(media); - - ObjectPath endpoint_path(endpoint->object_path()); - if (!media->IsRegistered(endpoint_path)) - return; - - if (valid) { - ObjectPath transport_path = GenerateTransportPath(); - VLOG(1) << "New transport, " << transport_path.value() - << " is created for endpoint " << endpoint_path.value(); - - // Sets the fake property set with default values. - scoped_ptr<Properties> properties(new Properties( - base::Bind(&FakeBluetoothMediaTransportClient::OnPropertyChanged, - base::Unretained(this)))); - properties->device.ReplaceValue(ObjectPath(kTransportDevicePath)); - properties->uuid.ReplaceValue( - BluetoothMediaClient::kBluetoothAudioSinkUUID); - properties->codec.ReplaceValue(kTransportCodec); - properties->configuration.ReplaceValue( - UINT8_VECTOR_FROM_ARRAY(kTransportConfiguration)); - properties->state.ReplaceValue(BluetoothMediaTransportClient::kStateIdle); - properties->delay.ReplaceValue(kTransportDelay); - properties->volume.ReplaceValue(kTransportVolume); - - endpoint_to_transport_map_[endpoint_path] = - new Transport(transport_path, properties.release()); - transport_to_endpoint_map_[transport_path] = endpoint_path; - return; - } - - Transport* transport = GetTransport(endpoint_path); - if (!transport) - return; - ObjectPath transport_path = transport->path; - - // Notifies observers about the state change of the transport. - FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, - MediaTransportRemoved(transport_path)); - - endpoint->ClearConfiguration(transport_path); - delete transport; - endpoint_to_transport_map_.erase(endpoint_path); - transport_to_endpoint_map_.erase(transport_path); -} - -void FakeBluetoothMediaTransportClient::SetState( - const ObjectPath& endpoint_path, - const std::string& state) { - VLOG(1) << "SetState - state: " << state; - - Transport* transport = GetTransport(endpoint_path); - if (!transport) - return; - - transport->properties->state.ReplaceValue(state); - FOR_EACH_OBSERVER( - BluetoothMediaTransportClient::Observer, observers_, - MediaTransportPropertyChanged( - transport->path, BluetoothMediaTransportClient::kStateProperty)); -} - -void FakeBluetoothMediaTransportClient::SetVolume( - const ObjectPath& endpoint_path, - const uint16_t& volume) { - Transport* transport = GetTransport(endpoint_path); - if (!transport) - return; - - transport->properties->volume.ReplaceValue(volume); - FOR_EACH_OBSERVER( - BluetoothMediaTransportClient::Observer, observers_, - MediaTransportPropertyChanged( - transport->path, BluetoothMediaTransportClient::kVolumeProperty)); -} - -void FakeBluetoothMediaTransportClient::WriteData( - const ObjectPath& endpoint_path, - const std::vector<char>& bytes) { - VLOG(1) << "WriteData - write " << bytes.size() << " bytes"; - - Transport* transport = GetTransport(endpoint_path); - - if (!transport || transport->properties->state.value() != "active") { - VLOG(1) << "WriteData - write operation rejected, since the state isn't " - "active for endpoint: " - << endpoint_path.value(); - return; - } - - if (!transport->input_fd.get()) { - VLOG(1) << "WriteData - invalid input file descriptor"; - return; - } - - ssize_t written_len = - write(transport->input_fd->GetPlatformFile(), bytes.data(), bytes.size()); - if (written_len < 0) { - VLOG(1) << "WriteData - failed to write to the socket"; - return; - } - - VLOG(1) << "WriteData - wrote " << written_len << " bytes to the socket"; -} - -ObjectPath FakeBluetoothMediaTransportClient::GetTransportPath( - const ObjectPath& endpoint_path) { - Transport* transport = GetTransport(endpoint_path); - return transport ? transport->path : ObjectPath(""); -} - -void FakeBluetoothMediaTransportClient::OnPropertyChanged( - const std::string& property_name) { - VLOG(1) << "Property " << property_name << " changed"; -} - -ObjectPath FakeBluetoothMediaTransportClient::GetEndpointPath( - const ObjectPath& transport_path) { - const auto& it = transport_to_endpoint_map_.find(transport_path); - return it != transport_to_endpoint_map_.end() ? it->second : ObjectPath(""); -} - -FakeBluetoothMediaTransportClient::Transport* -FakeBluetoothMediaTransportClient::GetTransport( - const ObjectPath& endpoint_path) { - const auto& it = endpoint_to_transport_map_.find(endpoint_path); - return (it != endpoint_to_transport_map_.end()) ? it->second : nullptr; -} - -FakeBluetoothMediaTransportClient::Transport* -FakeBluetoothMediaTransportClient::GetTransportByPath( - const dbus::ObjectPath& transport_path) { - return GetTransport(GetEndpointPath(transport_path)); -} - -void FakeBluetoothMediaTransportClient::AcquireInternal( - bool try_flag, - const ObjectPath& object_path, - const AcquireCallback& callback, - const ErrorCallback& error_callback) { - const ObjectPath& endpoint_path = GetEndpointPath(object_path); - Transport* transport = GetTransport(endpoint_path); - if (!transport) { - error_callback.Run(kFailed, ""); - return; - } - - std::string state = transport->properties->state.value(); - if (state == "active") { - error_callback.Run(kNotAuthorized, ""); - return; - } - if (state != "pending") { - error_callback.Run(try_flag ? kNotAvailable : kFailed, ""); - return; - } - - int fds[2]; - if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { - transport->input_fd.reset(); - error_callback.Run(kFailed, ""); - return; - } - DCHECK((fds[0] > kInvalidFd) && (fds[1] > kInvalidFd)); - transport->input_fd.reset(new base::File(fds[0])); - - dbus::FileDescriptor out_fd(fds[1]); - callback.Run(&out_fd, kDefaultReadMtu, kDefaultWriteMtu); - SetState(endpoint_path, "active"); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_media_transport_client.h b/chromeos/dbus/fake_bluetooth_media_transport_client.h deleted file mode 100644 index bbf30a5..0000000 --- a/chromeos/dbus/fake_bluetooth_media_transport_client.h +++ /dev/null
@@ -1,148 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_ - -#include <map> -#include <string> -#include <vector> - -#include "base/files/file.h" -#include "base/memory/scoped_ptr.h" -#include "base/observer_list.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_media_transport_client.h" -#include "dbus/object_path.h" - -namespace chromeos { - -class FakeBluetoothMediaEndpointServiceProvider; - -class CHROMEOS_EXPORT FakeBluetoothMediaTransportClient - : public BluetoothMediaTransportClient { - public: - struct Properties : public BluetoothMediaTransportClient::Properties { - explicit Properties(const PropertyChangedCallback& callback); - ~Properties() override; - - void Get(dbus::PropertyBase* property, - dbus::PropertySet::GetCallback callback) override; - void GetAll() override; - void Set(dbus::PropertyBase* property, - dbus::PropertySet::SetCallback callback) override; - }; - - // The default path of the transport object. - static const char kTransportPath[]; - - // The default properties including device, codec, configuration, state, delay - // and volume, owned by a fake media transport object we emulate. - static const char kTransportDevicePath[]; - static const uint8_t kTransportCodec; - static const uint8_t kTransportConfiguration[]; - static const uint8_t kTransportConfigurationLength; - static const uint16_t kTransportDelay; - static const uint16_t kTransportVolume; - - // The default MTUs for read and write. - static const uint16_t kDefaultReadMtu; - static const uint16_t kDefaultWriteMtu; - - FakeBluetoothMediaTransportClient(); - ~FakeBluetoothMediaTransportClient() override; - - // DBusClient override. - void Init(dbus::Bus* bus) override; - - // BluetoothMediaTransportClient override. - void AddObserver(Observer* observer) override; - void RemoveObserver(Observer* observer) override; - Properties* GetProperties(const dbus::ObjectPath& object_path) override; - void Acquire(const dbus::ObjectPath& object_path, - const AcquireCallback& callback, - const ErrorCallback& error_callback) override; - void TryAcquire(const dbus::ObjectPath& object_path, - const AcquireCallback& callback, - const ErrorCallback& error_callback) override; - void Release(const dbus::ObjectPath& object_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - - // Makes the transport valid/invalid for a given media endpoint. The transport - // object is assigned to the given endpoint if valid is true, false - // otherwise. - void SetValid(FakeBluetoothMediaEndpointServiceProvider* endpoint, - bool valid); - - // Set state/volume property to a certain value. - void SetState(const dbus::ObjectPath& endpoint_path, - const std::string& state); - void SetVolume(const dbus::ObjectPath& endpoint_path, const uint16_t& volume); - - // Writes bytes to the input file descriptor, |input_fd|, associated with a - // transport object which is bound to |endpoint_path|. - void WriteData(const dbus::ObjectPath& endpoint_path, - const std::vector<char>& bytes); - - // Retrieves the transport object path bound to |endpoint_path|. - dbus::ObjectPath GetTransportPath(const dbus::ObjectPath& endpoint_path); - - private: - // This class is used for simulating the scenario where each media endpoint - // has a corresponding transport path and properties. Once an endpoint is - // assigned with a transport path, an object of Transport is created. - struct Transport { - Transport(const dbus::ObjectPath& transport_path, - Properties* transport_properties); - ~Transport(); - - // An unique transport path. - dbus::ObjectPath path; - - // The property set bound with |path|. - scoped_ptr<Properties> properties; - - // This is the internal end of socketpair created for simulation purposes. - // |input_fd| will be initialized when Acquire/TryAcquire is called. - scoped_ptr<base::File> input_fd; - }; - - // Property callback passed while a Properties structure is created. - void OnPropertyChanged(const std::string& property_name); - - // Gets the endpoint path associated with the given transport_path. - dbus::ObjectPath GetEndpointPath(const dbus::ObjectPath& transport_path); - - // Retrieves the transport structure bound to |endpoint_path|. - Transport* GetTransport(const dbus::ObjectPath& endpoint_path); - - // Retrieves the transport structure with |transport_path|. - Transport* GetTransportByPath(const dbus::ObjectPath& transport_path); - - // Helper function used by Acquire and TryAcquire to set up the sockpair and - // invoke callback/error_callback. - void AcquireInternal(bool try_flag, - const dbus::ObjectPath& object_path, - const AcquireCallback& callback, - const ErrorCallback& error_callback); - - // Map of endpoints with valid transport. Each pair is composed of an endpoint - // path and a Transport structure containing a transport path and its - // properties. - std::map<dbus::ObjectPath, Transport*> endpoint_to_transport_map_; - - // Map of valid transports. Each pair is composed of a transport path as the - // key and an endpoint path as the value. This map is used to get the - // corresponding endpoint path when GetProperties() is called. - std::map<dbus::ObjectPath, dbus::ObjectPath> transport_to_endpoint_map_; - - base::ObserverList<BluetoothMediaTransportClient::Observer> observers_; - - DISALLOW_COPY_AND_ASSIGN(FakeBluetoothMediaTransportClient); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_profile_manager_client.cc b/chromeos/dbus/fake_bluetooth_profile_manager_client.cc deleted file mode 100644 index 1a06d41..0000000 --- a/chromeos/dbus/fake_bluetooth_profile_manager_client.cc +++ /dev/null
@@ -1,111 +0,0 @@ -// Copyright (c) 2013 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 "chromeos/dbus/fake_bluetooth_profile_manager_client.h" - -#include "base/location.h" -#include "base/logging.h" -#include "base/single_thread_task_runner.h" -#include "base/thread_task_runner_handle.h" -#include "chromeos/dbus/fake_bluetooth_profile_service_provider.h" -#include "dbus/bus.h" -#include "dbus/message.h" -#include "dbus/object_proxy.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -const char FakeBluetoothProfileManagerClient::kL2capUuid[] = - "4d995052-33cc-4fdf-b446-75f32942a076"; -const char FakeBluetoothProfileManagerClient::kRfcommUuid[] = - "3f6d6dbf-a6ad-45fc-9653-47dc912ef70e"; -const char FakeBluetoothProfileManagerClient::kUnregisterableUuid[] = - "00000000-0000-0000-0000-000000000000"; - -FakeBluetoothProfileManagerClient::FakeBluetoothProfileManagerClient() {} - -FakeBluetoothProfileManagerClient::~FakeBluetoothProfileManagerClient() {} - -void FakeBluetoothProfileManagerClient::Init(dbus::Bus* bus) {} - -void FakeBluetoothProfileManagerClient::RegisterProfile( - const dbus::ObjectPath& profile_path, - const std::string& uuid, - const Options& options, - const base::Closure& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "RegisterProfile: " << profile_path.value() << ": " << uuid; - - if (uuid == kUnregisterableUuid) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(error_callback, - bluetooth_profile_manager::kErrorInvalidArguments, - "Can't register this UUID")); - return; - } - - // TODO(jamuraa): check options for channel & psm - - ServiceProviderMap::iterator iter = service_provider_map_.find(profile_path); - if (iter == service_provider_map_.end()) { - error_callback.Run(bluetooth_profile_manager::kErrorInvalidArguments, - "No profile created"); - } else { - ProfileMap::iterator piter = profile_map_.find(uuid); - if (piter != profile_map_.end()) { - error_callback.Run(bluetooth_profile_manager::kErrorAlreadyExists, - "Profile already registered"); - } else { - profile_map_[uuid] = profile_path; - base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); - } - } -} - -void FakeBluetoothProfileManagerClient::UnregisterProfile( - const dbus::ObjectPath& profile_path, - const base::Closure& callback, - const ErrorCallback& error_callback) { - VLOG(1) << "UnregisterProfile: " << profile_path.value(); - - ServiceProviderMap::iterator iter = service_provider_map_.find(profile_path); - if (iter == service_provider_map_.end()) { - error_callback.Run(bluetooth_profile_manager::kErrorInvalidArguments, - "Profile not registered"); - } else { - for (ProfileMap::iterator piter = profile_map_.begin(); - piter != profile_map_.end(); ++piter) { - if (piter->second == profile_path) { - profile_map_.erase(piter); - break; - } - } - - base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); - } -} - -void FakeBluetoothProfileManagerClient::RegisterProfileServiceProvider( - FakeBluetoothProfileServiceProvider* service_provider) { - service_provider_map_[service_provider->object_path_] = service_provider; -} - -void FakeBluetoothProfileManagerClient::UnregisterProfileServiceProvider( - FakeBluetoothProfileServiceProvider* service_provider) { - ServiceProviderMap::iterator iter = - service_provider_map_.find(service_provider->object_path_); - if (iter != service_provider_map_.end() && iter->second == service_provider) - service_provider_map_.erase(iter); -} - -FakeBluetoothProfileServiceProvider* -FakeBluetoothProfileManagerClient::GetProfileServiceProvider( - const std::string& uuid) { - ProfileMap::iterator iter = profile_map_.find(uuid); - if (iter == profile_map_.end()) - return nullptr; - return service_provider_map_[iter->second]; -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_profile_manager_client.h b/chromeos/dbus/fake_bluetooth_profile_manager_client.h deleted file mode 100644 index c142606..0000000 --- a/chromeos/dbus/fake_bluetooth_profile_manager_client.h +++ /dev/null
@@ -1,74 +0,0 @@ -// Copyright (c) 2013 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 CHROMEOS_DBUS_FAKE_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_ - -#include <map> -#include <string> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/observer_list.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_profile_manager_client.h" -#include "dbus/object_path.h" -#include "dbus/property.h" - -namespace chromeos { - -class FakeBluetoothProfileServiceProvider; - -// FakeBluetoothProfileManagerClient simulates the behavior of the Bluetooth -// Daemon's profile manager object and is used both in test cases in place of a -// mock and on the Linux desktop. -class CHROMEOS_EXPORT FakeBluetoothProfileManagerClient - : public BluetoothProfileManagerClient { - public: - FakeBluetoothProfileManagerClient(); - ~FakeBluetoothProfileManagerClient() override; - - // BluetoothProfileManagerClient overrides - void Init(dbus::Bus* bus) override; - void RegisterProfile(const dbus::ObjectPath& profile_path, - const std::string& uuid, - const Options& options, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - void UnregisterProfile(const dbus::ObjectPath& profile_path, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - - // Register, unregister and retrieve pointers to profile server providers. - void RegisterProfileServiceProvider( - FakeBluetoothProfileServiceProvider* service_provider); - void UnregisterProfileServiceProvider( - FakeBluetoothProfileServiceProvider* service_provider); - FakeBluetoothProfileServiceProvider* GetProfileServiceProvider( - const std::string& uuid); - - // UUIDs recognised for testing. - static const char kL2capUuid[]; - static const char kRfcommUuid[]; - static const char kUnregisterableUuid[]; - - private: - // Map of a D-Bus object path to the FakeBluetoothProfileServiceProvider - // registered for it; maintained by RegisterProfileServiceProvider() and - // UnregisterProfileServiceProvicer() called by the constructor and - // destructor of FakeBluetoothProfileServiceProvider. - typedef std::map<dbus::ObjectPath, FakeBluetoothProfileServiceProvider*> - ServiceProviderMap; - ServiceProviderMap service_provider_map_; - - // Map of Profile UUID to the D-Bus object path of the service provider - // in |service_provider_map_|. Maintained by RegisterProfile() and - // UnregisterProfile() in response to BluetoothProfile methods. - typedef std::map<std::string, dbus::ObjectPath> ProfileMap; - ProfileMap profile_map_; -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_profile_service_provider.cc b/chromeos/dbus/fake_bluetooth_profile_service_provider.cc deleted file mode 100644 index 6f9c345..0000000 --- a/chromeos/dbus/fake_bluetooth_profile_service_provider.cc +++ /dev/null
@@ -1,61 +0,0 @@ -// Copyright (c) 2013 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 "chromeos/dbus/fake_bluetooth_profile_service_provider.h" - -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h" - -namespace chromeos { - -FakeBluetoothProfileServiceProvider::FakeBluetoothProfileServiceProvider( - const dbus::ObjectPath& object_path, - Delegate* delegate) - : object_path_(object_path), delegate_(delegate) { - VLOG(1) << "Creating Bluetooth Profile: " << object_path_.value(); - - FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = - static_cast<FakeBluetoothProfileManagerClient*>( - DBusThreadManager::Get()->GetBluetoothProfileManagerClient()); - fake_bluetooth_profile_manager_client->RegisterProfileServiceProvider(this); -} - -FakeBluetoothProfileServiceProvider::~FakeBluetoothProfileServiceProvider() { - VLOG(1) << "Cleaning up Bluetooth Profile: " << object_path_.value(); - - FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = - static_cast<FakeBluetoothProfileManagerClient*>( - DBusThreadManager::Get()->GetBluetoothProfileManagerClient()); - fake_bluetooth_profile_manager_client->UnregisterProfileServiceProvider(this); -} - -void FakeBluetoothProfileServiceProvider::Released() { - VLOG(1) << object_path_.value() << ": Released"; - delegate_->Released(); -} - -void FakeBluetoothProfileServiceProvider::NewConnection( - const dbus::ObjectPath& device_path, - scoped_ptr<dbus::FileDescriptor> fd, - const Delegate::Options& options, - const Delegate::ConfirmationCallback& callback) { - VLOG(1) << object_path_.value() << ": NewConnection for " - << device_path.value(); - delegate_->NewConnection(device_path, fd.Pass(), options, callback); -} - -void FakeBluetoothProfileServiceProvider::RequestDisconnection( - const dbus::ObjectPath& device_path, - const Delegate::ConfirmationCallback& callback) { - VLOG(1) << object_path_.value() << ": RequestDisconnection for " - << device_path.value(); - delegate_->RequestDisconnection(device_path, callback); -} - -void FakeBluetoothProfileServiceProvider::Cancel() { - VLOG(1) << object_path_.value() << ": Cancel"; - delegate_->Cancel(); -} - -} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_profile_service_provider.h b/chromeos/dbus/fake_bluetooth_profile_service_provider.h deleted file mode 100644 index 2c98048..0000000 --- a/chromeos/dbus/fake_bluetooth_profile_service_provider.h +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright (c) 2013 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 CHROMEOS_DBUS_FAKE_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_ -#define CHROMEOS_DBUS_FAKE_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_ - -#include "base/bind.h" -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_profile_service_provider.h" -#include "dbus/file_descriptor.h" -#include "dbus/object_path.h" - -namespace chromeos { - -// FakeBluetoothProfileServiceProvider simulates the behavior of a local -// Bluetooth agent object and is used both in test cases in place of a -// mock and on the Linux desktop. -// -// This class is only called from the dbus origin thread and is not thread-safe. -class CHROMEOS_EXPORT FakeBluetoothProfileServiceProvider - : public BluetoothProfileServiceProvider { - public: - FakeBluetoothProfileServiceProvider(const dbus::ObjectPath& object_path, - Delegate* delegate); - ~FakeBluetoothProfileServiceProvider() override; - - // Each of these calls the equivalent - // BluetoothProfileServiceProvider::Delegate method on the object passed on - // construction. - void Released(); - void NewConnection(const dbus::ObjectPath& device_path, - scoped_ptr<dbus::FileDescriptor> fd, - const Delegate::Options& options, - const Delegate::ConfirmationCallback& callback); - void RequestDisconnection(const dbus::ObjectPath& device_path, - const Delegate::ConfirmationCallback& callback); - void Cancel(); - - const dbus::ObjectPath& object_path() const { return object_path_; } - - private: - friend class FakeBluetoothProfileManagerClient; - - // D-Bus object path we are faking. - dbus::ObjectPath object_path_; - - // All incoming method calls are passed on to the Delegate and a callback - // passed to generate the reply. |delegate_| is generally the object that - // owns this one, and must outlive it. - Delegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(FakeBluetoothProfileServiceProvider); -}; - -} // namespace chromeos - -#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_
diff --git a/components/BUILD.gn b/components/BUILD.gn index 2fdd4ce..b5a5541 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -125,7 +125,7 @@ "//components/security_interstitials/core", "//components/signin/core/browser", "//components/ssl_config", - "//components/startup_metric_utils", + "//components/startup_metric_utils/browser", "//components/sync_driver", "//components/sync_sessions", "//components/tracing", @@ -435,6 +435,7 @@ "//components/feedback:unit_tests", "//components/proximity_auth:unit_tests", "//components/storage_monitor:unit_tests", + "//components/web_modal:unit_tests", "//components/webusb:unit_tests", ] } @@ -610,8 +611,8 @@ test("components_perftests") { sources = [ - "scheduler/base/nestable_task_runner_for_test.cc", - "scheduler/base/nestable_task_runner_for_test.h", + "scheduler/base/task_queue_manager_delegate_for_test.cc", + "scheduler/base/task_queue_manager_delegate_for_test.h", "scheduler/base/task_queue_manager_perftest.cc", "visitedlink/test/visitedlink_perftest.cc", ]
diff --git a/components/bookmarks.gypi b/components/bookmarks.gypi index 4894b69..69d5b589 100644 --- a/components/bookmarks.gypi +++ b/components/bookmarks.gypi
@@ -26,7 +26,6 @@ 'keyed_service_core', 'pref_registry', 'query_parser', - 'startup_metric_utils', 'url_formatter/url_formatter.gyp:url_formatter', ], 'sources': [
diff --git a/components/bookmarks/DEPS b/components/bookmarks/DEPS index 75997b1..1871065 100644 --- a/components/bookmarks/DEPS +++ b/components/bookmarks/DEPS
@@ -3,7 +3,6 @@ "+components/keyed_service", "+components/pref_registry", "+components/query_parser", - "+components/startup_metric_utils", "+components/url_formatter", "+grit/components_strings.h", "+jni",
diff --git a/components/bookmarks/browser/BUILD.gn b/components/bookmarks/browser/BUILD.gn index 97f5065..c0ec3b2 100644 --- a/components/bookmarks/browser/BUILD.gn +++ b/components/bookmarks/browser/BUILD.gn
@@ -50,7 +50,6 @@ "//components/keyed_service/core", "//components/pref_registry", "//components/query_parser", - "//components/startup_metric_utils", "//components/strings", "//components/url_formatter", "//net",
diff --git a/components/bookmarks/browser/bookmark_utils.cc b/components/bookmarks/browser/bookmark_utils.cc index 6d60a4f8..0b7117b 100644 --- a/components/bookmarks/browser/bookmark_utils.cc +++ b/components/bookmarks/browser/bookmark_utils.cc
@@ -415,8 +415,8 @@ std::vector<const BookmarkNode*> url_matched_nodes; if (url.is_valid()) model->GetNodesByURL(url, &url_matched_nodes); - bookmarks::VectorIterator iterator(&url_matched_nodes); - GetBookmarksMatchingPropertiesImpl<bookmarks::VectorIterator>( + VectorIterator iterator(&url_matched_nodes); + GetBookmarksMatchingPropertiesImpl<VectorIterator>( iterator, model, query, query_words, max_count, languages, nodes); } else { ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node());
diff --git a/components/bookmarks/managed/managed_bookmark_service.h b/components/bookmarks/managed/managed_bookmark_service.h index 8841c0d..db24b2b 100644 --- a/components/bookmarks/managed/managed_bookmark_service.h +++ b/components/bookmarks/managed/managed_bookmark_service.h
@@ -68,7 +68,7 @@ void BookmarkModelChanged() override; // BookmarkModelObserver implementation. - void BookmarkModelLoaded(bookmarks::BookmarkModel* bookmark_model, + void BookmarkModelLoaded(BookmarkModel* bookmark_model, bool ids_reassigned) override; void BookmarkModelBeingDeleted(BookmarkModel* bookmark_model) override;
diff --git a/components/bookmarks/managed/managed_bookmarks_tracker.h b/components/bookmarks/managed/managed_bookmarks_tracker.h index ecd157d..041100cd 100644 --- a/components/bookmarks/managed/managed_bookmarks_tracker.h +++ b/components/bookmarks/managed/managed_bookmarks_tracker.h
@@ -38,7 +38,7 @@ // If |is_supervised| is true, this will track supervised bookmarks rather // than managed bookmarks. - ManagedBookmarksTracker(bookmarks::BookmarkModel* model, + ManagedBookmarksTracker(BookmarkModel* model, PrefService* prefs, bool is_supervised, const GetManagementDomainCallback& callback); @@ -51,13 +51,13 @@ // Loads the initial managed/supervised bookmarks in |list| into |folder|. // New nodes will be assigned IDs starting at |next_node_id|. // Returns the next node ID to use. - static int64 LoadInitial(bookmarks::BookmarkNode* folder, + static int64 LoadInitial(BookmarkNode* folder, const base::ListValue* list, int64 next_node_id); // Starts tracking the pref for updates to the managed/supervised bookmarks. // Should be called after loading the initial bookmarks. - void Init(bookmarks::BookmarkPermanentNode* managed_node); + void Init(BookmarkPermanentNode* managed_node); bool is_supervised() const { return is_supervised_; } @@ -70,17 +70,16 @@ void ReloadManagedBookmarks(); - void UpdateBookmarks(const bookmarks::BookmarkNode* folder, - const base::ListValue* list); + void UpdateBookmarks(const BookmarkNode* folder, const base::ListValue* list); static bool LoadBookmark(const base::ListValue* list, size_t index, base::string16* title, GURL* url, const base::ListValue** children); - bookmarks::BookmarkModel* model_; + BookmarkModel* model_; const bool is_supervised_; - bookmarks::BookmarkPermanentNode* managed_node_; + BookmarkPermanentNode* managed_node_; PrefService* prefs_; PrefChangeRegistrar registrar_; GetManagementDomainCallback get_management_domain_callback_;
diff --git a/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc b/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc index 3a8c8b8..07b1238 100644 --- a/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc +++ b/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc
@@ -36,10 +36,9 @@ ~ManagedBookmarksTrackerTest() override {} void SetUp() override { - prefs_.registry()->RegisterListPref(bookmarks::prefs::kManagedBookmarks); - prefs_.registry()->RegisterListPref(bookmarks::prefs::kSupervisedBookmarks); - prefs_.registry()->RegisterListPref( - bookmarks::prefs::kBookmarkEditorExpandedNodes); + prefs_.registry()->RegisterListPref(prefs::kManagedBookmarks); + prefs_.registry()->RegisterListPref(prefs::kSupervisedBookmarks); + prefs_.registry()->RegisterListPref(prefs::kBookmarkEditorExpandedNodes); } void TearDown() override { @@ -60,7 +59,7 @@ is_supervised ? IDS_BOOKMARK_BAR_SUPERVISED_FOLDER_DEFAULT_NAME : IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME)); - bookmarks::BookmarkPermanentNodeList extra_nodes; + BookmarkPermanentNodeList extra_nodes; extra_nodes.push_back(managed_node); client_.SetExtraNodesToLoad(extra_nodes.Pass()); @@ -70,7 +69,7 @@ model_->Load(&prefs_, std::string(), base::FilePath(), base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get()); - bookmarks::test::WaitForBookmarkModelToLoad(model_.get()); + test::WaitForBookmarkModelToLoad(model_.get()); Mock::VerifyAndClearExpectations(&observer_); ASSERT_EQ(1u, client_.extra_nodes().size()); @@ -167,9 +166,9 @@ base::MessageLoop loop_; TestingPrefServiceSimple prefs_; - bookmarks::TestBookmarkClient client_; + TestBookmarkClient client_; scoped_ptr<BookmarkModel> model_; - bookmarks::MockBookmarkModelObserver observer_; + MockBookmarkModelObserver observer_; BookmarkPermanentNode* managed_node_; scoped_ptr<ManagedBookmarksTracker> managed_bookmarks_tracker_; }; @@ -184,7 +183,7 @@ TEST_F(ManagedBookmarksTrackerTest, LoadInitial) { // Set a policy before loading the model. - prefs_.SetManagedPref(bookmarks::prefs::kManagedBookmarks, CreateTestTree()); + prefs_.SetManagedPref(prefs::kManagedBookmarks, CreateTestTree()); CreateModel(false /* is_supervised */); EXPECT_TRUE(model_->bookmark_bar_node()->empty()); EXPECT_TRUE(model_->other_node()->empty()); @@ -196,15 +195,14 @@ } TEST_F(ManagedBookmarksTrackerTest, SupervisedTrackerIgnoresManagedPref) { - prefs_.SetManagedPref(bookmarks::prefs::kManagedBookmarks, CreateTestTree()); + prefs_.SetManagedPref(prefs::kManagedBookmarks, CreateTestTree()); CreateModel(true /* is_supervised */); EXPECT_TRUE(managed_node()->empty()); EXPECT_FALSE(managed_node()->IsVisible()); } TEST_F(ManagedBookmarksTrackerTest, SupervisedTrackerHandlesSupervisedPref) { - prefs_.SetManagedPref(bookmarks::prefs::kSupervisedBookmarks, - CreateTestTree()); + prefs_.SetManagedPref(prefs::kSupervisedBookmarks, CreateTestTree()); CreateModel(true /* is_supervised */); EXPECT_FALSE(managed_node()->empty()); EXPECT_TRUE(managed_node()->IsVisible()); @@ -213,7 +211,7 @@ } TEST_F(ManagedBookmarksTrackerTest, SwapNodes) { - prefs_.SetManagedPref(bookmarks::prefs::kManagedBookmarks, CreateTestTree()); + prefs_.SetManagedPref(prefs::kManagedBookmarks, CreateTestTree()); CreateModel(false /* is_supervised */); // Swap the Google bookmark with the Folder. @@ -225,8 +223,7 @@ // These two nodes should just be swapped. const BookmarkNode* parent = managed_node(); EXPECT_CALL(observer_, BookmarkNodeMoved(model_.get(), parent, 1, parent, 0)); - prefs_.SetManagedPref(bookmarks::prefs::kManagedBookmarks, - updated->DeepCopy()); + prefs_.SetManagedPref(prefs::kManagedBookmarks, updated->DeepCopy()); Mock::VerifyAndClearExpectations(&observer_); // Verify the final tree. @@ -236,7 +233,7 @@ } TEST_F(ManagedBookmarksTrackerTest, RemoveNode) { - prefs_.SetManagedPref(bookmarks::prefs::kManagedBookmarks, CreateTestTree()); + prefs_.SetManagedPref(prefs::kManagedBookmarks, CreateTestTree()); CreateModel(false /* is_supervised */); // Remove the Folder. @@ -245,8 +242,7 @@ const BookmarkNode* parent = managed_node(); EXPECT_CALL(observer_, BookmarkNodeRemoved(model_.get(), parent, 1, _, _)); - prefs_.SetManagedPref(bookmarks::prefs::kManagedBookmarks, - updated->DeepCopy()); + prefs_.SetManagedPref(prefs::kManagedBookmarks, updated->DeepCopy()); Mock::VerifyAndClearExpectations(&observer_); // Verify the final tree. @@ -256,7 +252,7 @@ } TEST_F(ManagedBookmarksTrackerTest, CreateNewNodes) { - prefs_.SetManagedPref(bookmarks::prefs::kManagedBookmarks, CreateTestTree()); + prefs_.SetManagedPref(prefs::kManagedBookmarks, CreateTestTree()); CreateModel(false /* is_supervised */); // Put all the nodes inside another folder. @@ -269,8 +265,7 @@ const BookmarkNode* parent = managed_node(); EXPECT_CALL(observer_, BookmarkNodeRemoved(model_.get(), parent, 1, _, _)) .Times(2); - prefs_.SetManagedPref(bookmarks::prefs::kManagedBookmarks, - updated->DeepCopy()); + prefs_.SetManagedPref(prefs::kManagedBookmarks, updated->DeepCopy()); Mock::VerifyAndClearExpectations(&observer_); // Verify the final tree. @@ -280,7 +275,7 @@ } TEST_F(ManagedBookmarksTrackerTest, RemoveAll) { - prefs_.SetManagedPref(bookmarks::prefs::kManagedBookmarks, CreateTestTree()); + prefs_.SetManagedPref(prefs::kManagedBookmarks, CreateTestTree()); CreateModel(false /* is_supervised */); EXPECT_TRUE(managed_node()->IsVisible()); @@ -288,7 +283,7 @@ const BookmarkNode* parent = managed_node(); EXPECT_CALL(observer_, BookmarkNodeRemoved(model_.get(), parent, 0, _, _)) .Times(2); - prefs_.RemoveManagedPref(bookmarks::prefs::kManagedBookmarks); + prefs_.RemoveManagedPref(prefs::kManagedBookmarks); Mock::VerifyAndClearExpectations(&observer_); EXPECT_TRUE(managed_node()->empty()); @@ -296,7 +291,7 @@ } TEST_F(ManagedBookmarksTrackerTest, IsManaged) { - prefs_.SetManagedPref(bookmarks::prefs::kManagedBookmarks, CreateTestTree()); + prefs_.SetManagedPref(prefs::kManagedBookmarks, CreateTestTree()); CreateModel(false /* is_supervised */); EXPECT_FALSE(IsManaged(model_->root_node())); @@ -317,7 +312,7 @@ } TEST_F(ManagedBookmarksTrackerTest, RemoveAllUserBookmarksDoesntRemoveManaged) { - prefs_.SetManagedPref(bookmarks::prefs::kManagedBookmarks, CreateTestTree()); + prefs_.SetManagedPref(prefs::kManagedBookmarks, CreateTestTree()); CreateModel(false /* is_supervised */); EXPECT_EQ(2, managed_node()->child_count());
diff --git a/components/components_tests.gyp b/components/components_tests.gyp index 5ef7bd8e..82e668e1 100644 --- a/components/components_tests.gyp +++ b/components/components_tests.gyp
@@ -538,6 +538,7 @@ 'proximity_auth/cryptauth/cryptauth_gcm_manager_impl_unittest.cc', 'proximity_auth/cryptauth/fake_secure_message_delegate_unittest.cc', 'proximity_auth/cryptauth/sync_scheduler_impl_unittest.cc', + 'proximity_auth/device_to_device_authenticator_unittest.cc', 'proximity_auth/device_to_device_operations_unittest.cc', 'proximity_auth/device_to_device_operations_unittest.cc', 'proximity_auth/device_to_device_secure_context_unittest.cc', @@ -577,14 +578,14 @@ ], 'safe_browsing_db_unittest_sources': [ 'safe_browsing_db/prefix_set_unittest.cc', - 'safe_browsing_db/safe_browsing_db_util_unittest.cc', + 'safe_browsing_db/util_unittest.cc', ], 'safe_json_unittest_sources': [ 'safe_json/json_sanitizer_unittest.cc', ], 'scheduler_unittest_sources': [ - 'scheduler/base/nestable_task_runner_for_test.cc', - 'scheduler/base/nestable_task_runner_for_test.h', + 'scheduler/base/task_queue_manager_delegate_for_test.cc', + 'scheduler/base/task_queue_manager_delegate_for_test.h', 'scheduler/base/task_queue_manager_unittest.cc', 'scheduler/base/task_queue_selector_unittest.cc', 'scheduler/base/task_queue_sets_unittest.cc', @@ -594,9 +595,10 @@ 'scheduler/base/test_time_source.h', 'scheduler/child/idle_helper_unittest.cc', 'scheduler/child/scheduler_helper_unittest.cc', - 'scheduler/child/scheduler_task_runner_delegate_for_test.cc', - 'scheduler/child/scheduler_task_runner_delegate_for_test.h', - 'scheduler/child/scheduler_task_runner_delegate_impl_unittest.cc', + 'scheduler/child/scheduler_tqm_delegate_for_test.cc', + 'scheduler/child/scheduler_tqm_delegate_for_test.h', + 'scheduler/child/scheduler_tqm_delegate_impl_unittest.cc', + 'scheduler/child/virtual_time_tqm_delegate_unittest.cc', 'scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc', 'scheduler/child/worker_scheduler_impl_unittest.cc', 'scheduler/renderer/deadline_task_runner_unittest.cc', @@ -676,6 +678,10 @@ 'sync_driver/device_info_sync_service_unittest.cc', 'sync_driver/frontend_data_type_controller_unittest.cc', 'sync_driver/generic_change_processor_unittest.cc', + 'sync_driver/glue/browser_thread_model_worker_unittest.cc', + 'sync_driver/glue/sync_backend_registrar_unittest.cc', + 'sync_driver/glue/ui_model_worker_unittest.cc', + 'sync_driver/local_device_info_provider_unittest.cc', 'sync_driver/model_association_manager_unittest.cc', 'sync_driver/non_blocking_data_type_controller_unittest.cc', 'sync_driver/non_frontend_data_type_controller_unittest.cc', @@ -693,8 +699,10 @@ 'sync_sessions/revisit/bookmarks_page_revisit_observer_unittest.cc', 'sync_sessions/revisit/current_tab_matcher_unittest.cc', 'sync_sessions/revisit/offset_tab_matcher_unittest.cc', + 'sync_sessions/revisit/page_revisit_broadcaster_unittest.cc', 'sync_sessions/revisit/sessions_page_revisit_observer_unittest.cc', 'sync_sessions/revisit/typed_url_page_revisit_task_unittest.cc', + 'sync_sessions/session_data_type_controller_unittest.cc', 'sync_sessions/synced_session_tracker_unittest.cc', ], 'syncable_prefs_unittest_sources': [ @@ -1464,14 +1472,9 @@ '<(PRODUCT_DIR)/icudtl.dat', ], }], - ['v8_use_external_startup_data==1', { - 'components_browsertests_pak_input_resources': [ - '<(PRODUCT_DIR)/natives_blob.bin', - '<(PRODUCT_DIR)/snapshot_blob.bin', - ], - }], ], }, + 'includes': ['../build/android/v8_external_startup_data_arch_suffix.gypi'], 'targets': [ { 'target_name': 'components_browsertests_paks_copy', @@ -1485,6 +1488,18 @@ '<@(components_browsertests_pak_input_resources)', ], 'clear': 1, + 'conditions': [ + ['v8_use_external_startup_data==1', { + 'renaming_sources': [ + '<(PRODUCT_DIR)/natives_blob.bin', + '<(PRODUCT_DIR)/snapshot_blob.bin', + ], + 'renaming_destinations': [ + 'natives_blob_<(arch_suffix).bin', + 'snapshot_blob_<(arch_suffix).bin', + ], + }], + ], }, 'includes': ['../build/android/copy_ex.gypi'], }, @@ -1524,8 +1539,8 @@ }], ['v8_use_external_startup_data==1', { 'additional_input_paths': [ - '<(asset_location)/natives_blob.bin', - '<(asset_location)/snapshot_blob.bin', + '<(asset_location)/natives_blob_<(arch_suffix).bin', + '<(asset_location)/snapshot_blob_<(arch_suffix).bin', ], }], ], @@ -1626,8 +1641,8 @@ '..', ], 'sources': [ - 'scheduler/base/nestable_task_runner_for_test.cc', - 'scheduler/base/nestable_task_runner_for_test.h', + 'scheduler/base/task_queue_manager_delegate_for_test.cc', + 'scheduler/base/task_queue_manager_delegate_for_test.h', 'scheduler/base/task_queue_manager_perftest.cc', 'visitedlink/test/visitedlink_perftest.cc', ],
diff --git a/components/copresence/proto/enums.proto b/components/copresence/proto/enums.proto index e76eee1..6570e4b 100644 --- a/components/copresence/proto/enums.proto +++ b/components/copresence/proto/enums.proto
@@ -5,7 +5,7 @@ IDENTITY_TYPE_UNKNOWN = 0; GAIA_USER = 1; CHROMECAST = 2; - ANDROID = 3; + ANDROIDOS = 3; CHROME = 4; UNREGISTERED = 5; }
diff --git a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequest.java b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequest.java index 390b88b9..6ec5b8d 100644 --- a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequest.java +++ b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequest.java
@@ -188,7 +188,6 @@ } if (!nativeAddRequestHeader( mUrlRequestAdapter, header.getKey(), header.getValue())) { - destroyRequestAdapter(false); throw new IllegalArgumentException( "Invalid header " + header.getKey() + "=" + header.getValue()); }
diff --git a/components/cronet/android/test/quic_test_server.cc b/components/cronet/android/test/quic_test_server.cc index dcb70dc91..20a45143 100644 --- a/components/cronet/android/test/quic_test_server.cc +++ b/components/cronet/android/test/quic_test_server.cc
@@ -50,7 +50,8 @@ net::ProofSourceChromium* proof_source = new net::ProofSourceChromium(); CHECK(proof_source->Initialize( directory.Append("quic_test.example.com.crt"), - directory.Append("quic_test.example.com.key.pkcs8"))); + directory.Append("quic_test.example.com.key.pkcs8"), + directory.Append("quic_test.example.com.key.sct"))); g_quic_server = new net::tools::QuicSimpleServer( proof_source, config, net::QuicSupportedVersions());
diff --git a/components/data_reduction_proxy/content/browser/BUILD.gn b/components/data_reduction_proxy/content/browser/BUILD.gn index b242c45..c618dd1e 100644 --- a/components/data_reduction_proxy/content/browser/BUILD.gn +++ b/components/data_reduction_proxy/content/browser/BUILD.gn
@@ -45,6 +45,7 @@ source_set("unit_tests") { testonly = true sources = [ + "content_lofi_decider_unittest.cc", "data_reduction_proxy_message_filter_unittest.cc", ] @@ -63,7 +64,6 @@ if (is_android) { sources += [ - "content_lofi_decider_unittest.cc", "data_reduction_proxy_debug_blocking_page_unittest.cc", "data_reduction_proxy_debug_resource_throttle_unittest.cc", "data_reduction_proxy_debug_ui_manager_unittest.cc",
diff --git a/components/font_service/public/cpp/BUILD.gn b/components/font_service/public/cpp/BUILD.gn index 52359b7..31458096 100644 --- a/components/font_service/public/cpp/BUILD.gn +++ b/components/font_service/public/cpp/BUILD.gn
@@ -19,7 +19,7 @@ "//mojo/application/public/interfaces", "//mojo/common", "//mojo/message_pump", - "//mojo/platform_handle", + "//mojo/platform_handle:defs", "//skia", "//third_party/mojo/src/mojo/public/cpp/bindings", "//third_party/mojo/src/mojo/public/cpp/system",
diff --git a/components/gcm_driver.gypi b/components/gcm_driver.gypi index de43bb5..fbf61c4 100644 --- a/components/gcm_driver.gypi +++ b/components/gcm_driver.gypi
@@ -75,10 +75,14 @@ 'gcm_driver/gcm_driver.h', 'gcm_driver/gcm_driver_android.cc', 'gcm_driver/gcm_driver_android.h', + 'gcm_driver/gcm_driver_constants.cc', + 'gcm_driver/gcm_driver_constants.h', 'gcm_driver/gcm_driver_desktop.cc', 'gcm_driver/gcm_driver_desktop.h', 'gcm_driver/gcm_internals_constants.cc', 'gcm_driver/gcm_internals_constants.h', + 'gcm_driver/gcm_profile_service.cc', + 'gcm_driver/gcm_profile_service.h', 'gcm_driver/gcm_stats_recorder_impl.cc', 'gcm_driver/gcm_stats_recorder_impl.h', 'gcm_driver/registration_info.cc',
diff --git a/components/gcm_driver/BUILD.gn b/components/gcm_driver/BUILD.gn index b009eac..2e852433 100644 --- a/components/gcm_driver/BUILD.gn +++ b/components/gcm_driver/BUILD.gn
@@ -39,10 +39,14 @@ "gcm_driver.h", "gcm_driver_android.cc", "gcm_driver_android.h", + "gcm_driver_constants.cc", + "gcm_driver_constants.h", "gcm_driver_desktop.cc", "gcm_driver_desktop.h", "gcm_internals_constants.cc", "gcm_internals_constants.h", + "gcm_profile_service.cc", + "gcm_profile_service.h", "gcm_stats_recorder_impl.cc", "gcm_stats_recorder_impl.h", "registration_info.cc",
diff --git a/components/gcm_driver/DEPS b/components/gcm_driver/DEPS index de2e4cc..964bdca 100644 --- a/components/gcm_driver/DEPS +++ b/components/gcm_driver/DEPS
@@ -1,6 +1,8 @@ include_rules = [ "+components/os_crypt", + "+components/keyed_service", "+components/pref_registry", + "+components/signin", "+components/sync_driver", "+components/timers", # Only used for Chrome OS builds. "+components/version_info",
diff --git a/components/gcm_driver/gcm_driver_constants.cc b/components/gcm_driver/gcm_driver_constants.cc new file mode 100644 index 0000000..1b3675d5 --- /dev/null +++ b/components/gcm_driver/gcm_driver_constants.cc
@@ -0,0 +1,15 @@ +// Copyright 2015 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/gcm_driver/gcm_driver_constants.h" + +#define FPL FILE_PATH_LITERAL + +namespace gcm_driver { + +const base::FilePath::CharType kGCMStoreDirname[] = FPL("GCM Store"); + +} // namespace gcm_driver + +#undef FPL
diff --git a/components/gcm_driver/gcm_driver_constants.h b/components/gcm_driver/gcm_driver_constants.h new file mode 100644 index 0000000..0bf6ed2 --- /dev/null +++ b/components/gcm_driver/gcm_driver_constants.h
@@ -0,0 +1,19 @@ +// Copyright 2015 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. + +// A handful of resource-like constants related to the GCM(Google Cloud +// Messaging) Driver. + +#ifndef COMPONENTS_GCM_DRIVER_GCM_DRIVER_CONSTANTS_H_ + +#include "base/files/file_path.h" + +namespace gcm_driver { + +// File path for GCM Store. +extern const base::FilePath::CharType kGCMStoreDirname[]; + +} // namespace gcm_driver + +#endif // COMPONENTS_GCM_DRIVER_GCM_DRIVER_CONSTANTS_H_
diff --git a/components/gcm_driver/gcm_profile_service.cc b/components/gcm_driver/gcm_profile_service.cc new file mode 100644 index 0000000..b6d340b --- /dev/null +++ b/components/gcm_driver/gcm_profile_service.cc
@@ -0,0 +1,183 @@ +// Copyright (c) 2013 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/gcm_driver/gcm_profile_service.h" + +#include <vector> + +#include "base/logging.h" +#include "base/prefs/pref_service.h" +#include "components/gcm_driver/gcm_driver.h" +#include "components/gcm_driver/gcm_driver_constants.h" +#include "components/pref_registry/pref_registry_syncable.h" + +#if defined(OS_ANDROID) +#include "base/sequenced_task_runner.h" +#include "base/threading/sequenced_worker_pool.h" +#include "components/gcm_driver/gcm_driver_android.h" +#else +#include "base/bind.h" +#include "base/files/file_path.h" +#include "base/memory/weak_ptr.h" +#include "components/gcm_driver/gcm_account_tracker.h" +#include "components/gcm_driver/gcm_channel_status_syncer.h" +#include "components/gcm_driver/gcm_client_factory.h" +#include "components/gcm_driver/gcm_desktop_utils.h" +#include "components/gcm_driver/gcm_driver_desktop.h" +#include "components/signin/core/browser/signin_manager.h" +#include "google_apis/gaia/account_tracker.h" +#include "google_apis/gaia/identity_provider.h" +#include "net/url_request/url_request_context_getter.h" +#endif + +namespace gcm { + +#if !defined(OS_ANDROID) +// Identity observer only has actual work to do when the user is actually signed +// in. It ensures that account tracker is taking +class GCMProfileService::IdentityObserver : public IdentityProvider::Observer { + public: + IdentityObserver(ProfileIdentityProvider* identity_provider, + net::URLRequestContextGetter* request_context, + GCMDriver* driver); + ~IdentityObserver() override; + + // IdentityProvider::Observer: + void OnActiveAccountLogin() override; + void OnActiveAccountLogout() override; + + private: + void StartAccountTracker(net::URLRequestContextGetter* request_context); + + GCMDriver* driver_; + IdentityProvider* identity_provider_; + scoped_ptr<GCMAccountTracker> gcm_account_tracker_; + + // The account ID that this service is responsible for. Empty when the service + // is not running. + std::string account_id_; + + base::WeakPtrFactory<GCMProfileService::IdentityObserver> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(IdentityObserver); +}; + +GCMProfileService::IdentityObserver::IdentityObserver( + ProfileIdentityProvider* identity_provider, + net::URLRequestContextGetter* request_context, + GCMDriver* driver) + : driver_(driver), + identity_provider_(identity_provider), + weak_ptr_factory_(this) { + identity_provider_->AddObserver(this); + + OnActiveAccountLogin(); + StartAccountTracker(request_context); +} + +GCMProfileService::IdentityObserver::~IdentityObserver() { + if (gcm_account_tracker_) + gcm_account_tracker_->Shutdown(); + identity_provider_->RemoveObserver(this); +} + +void GCMProfileService::IdentityObserver::OnActiveAccountLogin() { + // This might be called multiple times when the password changes. + const std::string account_id = identity_provider_->GetActiveAccountId(); + if (account_id == account_id_) + return; + account_id_ = account_id; + + // Still need to notify GCMDriver for UMA purpose. + driver_->OnSignedIn(); +} + +void GCMProfileService::IdentityObserver::OnActiveAccountLogout() { + account_id_.clear(); + + // Still need to notify GCMDriver for UMA purpose. + driver_->OnSignedOut(); +} + +void GCMProfileService::IdentityObserver::StartAccountTracker( + net::URLRequestContextGetter* request_context) { + if (gcm_account_tracker_) + return; + + scoped_ptr<gaia::AccountTracker> gaia_account_tracker( + new gaia::AccountTracker(identity_provider_, request_context)); + + gcm_account_tracker_.reset( + new GCMAccountTracker(gaia_account_tracker.Pass(), driver_)); + + gcm_account_tracker_->Start(); +} + +#endif // !defined(OS_ANDROID) + +// static +bool GCMProfileService::IsGCMEnabled(PrefService* prefs) { +#if defined(OS_ANDROID) + return true; +#else + return prefs->GetBoolean(gcm::prefs::kGCMChannelStatus); +#endif // defined(OS_ANDROID) +} + +#if defined(OS_ANDROID) +GCMProfileService::GCMProfileService( + base::FilePath path, + scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner) { + driver_.reset(new GCMDriverAndroid(path.Append(gcm_driver::kGCMStoreDirname), + blocking_task_runner)); +} +#else +GCMProfileService::GCMProfileService( + PrefService* prefs, + base::FilePath path, + net::URLRequestContextGetter* request_context, + version_info::Channel channel, + scoped_ptr<ProfileIdentityProvider> identity_provider, + scoped_ptr<GCMClientFactory> gcm_client_factory, + const scoped_refptr<base::SequencedTaskRunner>& ui_task_runner, + const scoped_refptr<base::SequencedTaskRunner>& io_task_runner, + scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner) + : request_context_(request_context), + profile_identity_provider_(identity_provider.Pass()) { + driver_ = CreateGCMDriverDesktop(gcm_client_factory.Pass(), prefs, + path.Append(gcm_driver::kGCMStoreDirname), + request_context_, channel, ui_task_runner, + io_task_runner, blocking_task_runner); + + identity_observer_.reset(new IdentityObserver( + profile_identity_provider_.get(), request_context_, driver_.get())); +} +#endif // defined(OS_ANDROID) + +GCMProfileService::GCMProfileService() : request_context_(nullptr) {} + +GCMProfileService::~GCMProfileService() {} + +void GCMProfileService::Shutdown() { +#if !defined(OS_ANDROID) + identity_observer_.reset(); +#endif // !defined(OS_ANDROID) + if (driver_) { + driver_->Shutdown(); + driver_.reset(); + } +} + +void GCMProfileService::SetDriverForTesting(const base::Closure& login_callback, + GCMDriver* driver) { + driver_.reset(driver); +#if !defined(OS_ANDROID) + if (identity_observer_) { + identity_observer_.reset(new IdentityObserver( + profile_identity_provider_.get(), request_context_, driver)); + } +#endif // !defined(OS_ANDROID) +} + +} // namespace gcm
diff --git a/components/gcm_driver/gcm_profile_service.h b/components/gcm_driver/gcm_profile_service.h new file mode 100644 index 0000000..e286022 --- /dev/null +++ b/components/gcm_driver/gcm_profile_service.h
@@ -0,0 +1,100 @@ +// Copyright (c) 2013 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_GCM_DRIVER_GCM_PROFILE_SERVICE_H_ +#define COMPONENTS_GCM_DRIVER_GCM_PROFILE_SERVICE_H_ + +#include <string> + +#include "base/callback_forward.h" +#include "base/compiler_specific.h" +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "components/keyed_service/core/keyed_service.h" +#include "components/signin/core/browser/profile_identity_provider.h" +#include "components/version_info/version_info.h" + +class PrefService; +class ProfileOAuth2TokenService; +class SigninManagerBase; + +namespace base { +class SequencedTaskRunner; +} + +namespace net { +class URLRequestContextGetter; +} + +namespace user_prefs { +class PrefRegistrySyncable; +} + +namespace gcm { + +class GCMClientFactory; +class GCMDriver; + +#if defined(OS_CHROMEOS) +class GCMConnectionObserver; +#endif + +// Providing GCM service, via GCMDriver. +class GCMProfileService : public KeyedService { + public: +#if defined(OS_ANDROID) + GCMProfileService( + base::FilePath path, + scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner); +#else + GCMProfileService( + PrefService* prefs, + base::FilePath path, + net::URLRequestContextGetter* request_context, + version_info::Channel channel, + scoped_ptr<ProfileIdentityProvider> identity_provider, + scoped_ptr<GCMClientFactory> gcm_client_factory, + const scoped_refptr<base::SequencedTaskRunner>& ui_task_runner, + const scoped_refptr<base::SequencedTaskRunner>& io_task_runner, + scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner); +#endif + ~GCMProfileService() override; + + // Returns whether GCM is enabled. + static bool IsGCMEnabled(PrefService* prefs); + + // KeyedService: + void Shutdown() override; + + // For testing purpose. + void SetDriverForTesting(const base::Closure& login_callback, + GCMDriver* driver); + + GCMDriver* driver() const { return driver_.get(); } + + protected: + // Used for constructing fake GCMProfileService for testing purpose. + GCMProfileService(); + + private: + net::URLRequestContextGetter* request_context_; + scoped_ptr<ProfileIdentityProvider> profile_identity_provider_; + + scoped_ptr<GCMDriver> driver_; + +// Used for both account tracker and GCM.UserSignedIn UMA. +#if !defined(OS_ANDROID) + class IdentityObserver; + scoped_ptr<IdentityObserver> identity_observer_; +#endif + + DISALLOW_COPY_AND_ASSIGN(GCMProfileService); +}; + +} // namespace gcm + +#endif // COMPONENTS_GCM_DRIVER_GCM_PROFILE_SERVICE_H_ +
diff --git a/components/html_viewer/BUILD.gn b/components/html_viewer/BUILD.gn index 894d6b3..d88dd51d 100644 --- a/components/html_viewer/BUILD.gn +++ b/components/html_viewer/BUILD.gn
@@ -161,7 +161,7 @@ "//components/resource_provider/public/cpp", "//components/resource_provider/public/interfaces", "//components/scheduler:scheduler", - "//components/startup_metric_utils", + "//components/startup_metric_utils/browser", "//components/webcrypto", "//components/web_view:switches", "//components/web_view/public/interfaces", @@ -302,9 +302,9 @@ sources = [ "$root_build_dir/html_viewer.pak", "$root_build_dir/icudtl.dat", - "$root_out_dir/natives_blob.bin", - "$root_out_dir/snapshot_blob.bin", ] + renaming_sources = v8_external_startup_data_renaming_sources + renaming_destinations = v8_external_startup_data_renaming_destinations } generate_mojo_shell_assets_list("build_unittest_assets") { @@ -329,6 +329,7 @@ "//components/scheduler", "//gin", "//mojo/converters/input_events", + "//mojo/gles2", "//testing/gtest:gtest", "//third_party/mojo/src/mojo/edk/system", "//ui/base",
diff --git a/components/html_viewer/DEPS b/components/html_viewer/DEPS index e87124c6..3ba0df9 100644 --- a/components/html_viewer/DEPS +++ b/components/html_viewer/DEPS
@@ -10,7 +10,7 @@ "+components/mus", "+components/resource_provider/public", "+components/scheduler", - "+components/startup_metric_utils", + "+components/startup_metric_utils/browser", "+components/webcrypto", "+components/web_view/public/interfaces", "+components/web_view/test_runner/public/interfaces",
diff --git a/components/html_viewer/stats_collection_controller.cc b/components/html_viewer/stats_collection_controller.cc index 70ab672..8abc09a7 100644 --- a/components/html_viewer/stats_collection_controller.cc +++ b/components/html_viewer/stats_collection_controller.cc
@@ -9,7 +9,7 @@ #include "base/metrics/histogram.h" #include "base/metrics/statistics_recorder.h" #include "base/time/time.h" -#include "components/startup_metric_utils/startup_metric_utils.h" +#include "components/startup_metric_utils/browser/startup_metric_utils.h" #include "gin/handle.h" #include "gin/object_template_builder.h" #include "mojo/application/public/cpp/application_impl.h"
diff --git a/components/html_viewer/web_layer_tree_view_impl.cc b/components/html_viewer/web_layer_tree_view_impl.cc index fcb9a70..c5e9850 100644 --- a/components/html_viewer/web_layer_tree_view_impl.cc +++ b/components/html_viewer/web_layer_tree_view_impl.cc
@@ -67,8 +67,9 @@ gpu_service->CreateOffscreenGLES2Context(GetProxy(&cb)); scoped_refptr<cc::ContextProvider> context_provider( new mus::ContextProvider(cb.PassInterface().PassHandle())); - output_surface_.reset( - new mus::OutputSurface(context_provider, window_->RequestSurface())); + output_surface_.reset(new mus::OutputSurface( + context_provider, + window_->RequestSurface(mus::mojom::SURFACE_TYPE_DEFAULT))); } layer_tree_host_->SetVisible(window_->visible()); }
diff --git a/components/invalidation/impl/BUILD.gn b/components/invalidation/impl/BUILD.gn index a358cef..3045d67d9 100644 --- a/components/invalidation/impl/BUILD.gn +++ b/components/invalidation/impl/BUILD.gn
@@ -213,7 +213,7 @@ ] DEPRECATED_java_in_dir = "android/javatests/src" } - junit_binary("junit_tests") { + junit_binary("components_invalidation_impl_junit_tests") { java_files = [ "android/junit/src/org/chromium/components/invalidation/PendingInvalidationTest.java" ] deps = [ ":java",
diff --git a/components/mus/example/BUILD.gn b/components/mus/example/BUILD.gn index f1c5192b..e1f46ab 100644 --- a/components/mus/example/BUILD.gn +++ b/components/mus/example/BUILD.gn
@@ -23,6 +23,7 @@ "//components/mus/example/views_examples", "//components/mus/example/window_type_launcher", "//components/mus/example/wm", + "//mojo/runner", ] }
diff --git a/components/mus/example/main/main_application_delegate.cc b/components/mus/example/main/main_application_delegate.cc index 322017f8..864340b 100644 --- a/components/mus/example/main/main_application_delegate.cc +++ b/components/mus/example/main/main_application_delegate.cc
@@ -15,7 +15,7 @@ connections_.push_back(app->ConnectToApplication("mojo:mock_sysui")); connections_.push_back(app->ConnectToApplication("mojo:views_examples")); connections_.push_back( - app->ConnectToApplication("mojo:window_type_launcher")); + app->ConnectToApplication("exe:window_type_launcher_exe")); } bool MainApplicationDelegate::ConfigureIncomingConnection(
diff --git a/components/mus/example/mock_sysui/mock_sysui.cc b/components/mus/example/mock_sysui/mock_sysui.cc index 6f58a4b..5b39a905 100644 --- a/components/mus/example/mock_sysui/mock_sysui.cc +++ b/components/mus/example/mock_sysui/mock_sysui.cc
@@ -30,7 +30,8 @@ ash::mojom::CONTAINER_USER_BACKGROUND); mus::Window* window = views::WindowManagerConnection::Get()->CreateWindow(properties); - params.native_widget = new views::NativeWidgetMus(widget, shell, window); + params.native_widget = new views::NativeWidgetMus( + widget, shell, window, mus::mojom::SURFACE_TYPE_DEFAULT); widget->Init(params); widget->Show(); } @@ -64,7 +65,8 @@ ash::mojom::CONTAINER_USER_SHELF); mus::Window* window = views::WindowManagerConnection::Get()->CreateWindow(properties); - params.native_widget = new views::NativeWidgetMus(widget, shell, window); + params.native_widget = new views::NativeWidgetMus( + widget, shell, window, mus::mojom::SURFACE_TYPE_DEFAULT); widget->Init(params); widget->Show(); }
diff --git a/components/mus/example/window_type_launcher/BUILD.gn b/components/mus/example/window_type_launcher/BUILD.gn index 776419e..bdf6224 100644 --- a/components/mus/example/window_type_launcher/BUILD.gn +++ b/components/mus/example/window_type_launcher/BUILD.gn
@@ -7,8 +7,8 @@ import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") import("//tools/grit/repack.gni") -mojo_native_application("window_type_launcher") { - output_name = "window_type_launcher" +executable("window_type_launcher") { + output_name = "window_type_launcher_exe" testonly = true sources = [ @@ -18,12 +18,18 @@ ] deps = [ + ":window_type_launcher_resources", "//base", "//mojo/application/public/cpp", - "//mojo/application/public/cpp:sources", + "//mojo/application/public/interfaces", + "//mojo/common:common_base", "//mojo/converters/geometry", "//mojo/converters/network", + "//mojo/message_pump", + "//mojo/runner/child:lib", + "//mojo/runner:init", "//skia", + "//third_party/mojo/src/mojo/edk/embedder", "//third_party/mojo/src/mojo/public/cpp/bindings", "//ui/aura", "//ui/gfx", @@ -32,9 +38,19 @@ "//ui/views/mus", ] - resources = [ "$root_out_dir/views_mus_resources.pak" ] - data_deps = [ "//components/mus", ] } + +copy("window_type_launcher_resources") { + sources = [ + "$root_out_dir/views_mus_resources.pak", + ] + outputs = [ + "$root_out_dir/window_type_launcher_exe_res/resources/views_mus_resources.pak", + ] + deps = [ + "//ui/views/mus:resources", + ] +}
diff --git a/components/mus/example/window_type_launcher/DEPS b/components/mus/example/window_type_launcher/DEPS new file mode 100644 index 0000000..68bd9754 --- /dev/null +++ b/components/mus/example/window_type_launcher/DEPS
@@ -0,0 +1,5 @@ +include_rules = [ + "+mojo/message_pump", + "+mojo/runner", + "+third_party/mojo/src/mojo/edk/embedder", +]
diff --git a/components/mus/example/window_type_launcher/main.cc b/components/mus/example/window_type_launcher/main.cc index 38337c88..f0bd9c093 100644 --- a/components/mus/example/window_type_launcher/main.cc +++ b/components/mus/example/window_type_launcher/main.cc
@@ -2,11 +2,81 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/at_exit.h" +#include "base/command_line.h" +#include "base/debug/stack_trace.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/process/launch.h" +#include "base/threading/thread.h" +#include "build/build_config.h" #include "components/mus/example/window_type_launcher/window_type_launcher.h" -#include "mojo/application/public/cpp/application_runner.h" -#include "third_party/mojo/src/mojo/public/c/system/main.h" +#include "mojo/application/public/cpp/application_impl.h" +#include "mojo/application/public/interfaces/application.mojom.h" +#include "mojo/message_pump/message_pump_mojo.h" +#include "mojo/runner/child/runner_connection.h" +#include "mojo/runner/init.h" +#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "third_party/mojo/src/mojo/edk/embedder/process_delegate.h" -MojoResult MojoMain(MojoHandle shell_handle) { - mojo::ApplicationRunner runner(new WindowTypeLauncher); - return runner.Run(shell_handle); +namespace { + +class ProcessDelegate : public mojo::embedder::ProcessDelegate { + public: + ProcessDelegate() {} + ~ProcessDelegate() override {} + + private: + void OnShutdownComplete() override {} + + DISALLOW_COPY_AND_ASSIGN(ProcessDelegate); +}; + +} + +int main(int argc, char** argv) { + base::AtExitManager at_exit; + base::CommandLine::Init(argc, argv); + + mojo::runner::InitializeLogging(); + mojo::runner::WaitForDebuggerIfNecessary(); + +#if !defined(OFFICIAL_BUILD) + base::debug::EnableInProcessStackDumping(); +#if defined(OS_WIN) + base::RouteStdioToConsole(false); +#endif +#endif + + { + mojo::embedder::Init(); + + ProcessDelegate process_delegate; + base::Thread io_thread("io_thread"); + base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0); + CHECK(io_thread.StartWithOptions(io_thread_options)); + + mojo::embedder::InitIPCSupport(mojo::embedder::ProcessType::NONE, + io_thread.task_runner().get(), + &process_delegate, + io_thread.task_runner().get(), + mojo::embedder::ScopedPlatformHandle()); + + mojo::InterfaceRequest<mojo::Application> application_request; + scoped_ptr<mojo::runner::RunnerConnection> connection( + mojo::runner::RunnerConnection::ConnectToRunner(&application_request)); + + WindowTypeLauncher delegate; + { + base::MessageLoop loop(mojo::common::MessagePumpMojo::Create()); + mojo::ApplicationImpl impl(&delegate, application_request.Pass()); + loop.Run(); + } + + connection.reset(); + + mojo::embedder::ShutdownIPCSupport(); + } + + return 0; }
diff --git a/components/mus/example/wm/BUILD.gn b/components/mus/example/wm/BUILD.gn index 81dc305..faf1b6c 100644 --- a/components/mus/example/wm/BUILD.gn +++ b/components/mus/example/wm/BUILD.gn
@@ -102,9 +102,11 @@ "//components/mus/public/cpp/tests:unittest_support", "//mojo/converters/geometry", "//mojo/converters/input_events", + "//mojo/gles2", + "//mojo/platform_handle", "//testing/gtest", - "//third_party/mojo/src/mojo/public/cpp/system", "//third_party/mojo/src/mojo/edk/system", + "//third_party/mojo/src/mojo/public/cpp/system", "//ui/events", "//ui/gfx/geometry", "//ui/gfx:test_support",
diff --git a/components/mus/public/cpp/lib/window.cc b/components/mus/public/cpp/lib/window.cc index 647e12d..761bf20f 100644 --- a/components/mus/public/cpp/lib/window.cc +++ b/components/mus/public/cpp/lib/window.cc
@@ -234,13 +234,13 @@ LocalSetVisible(value); } -scoped_ptr<WindowSurface> Window::RequestSurface() { +scoped_ptr<WindowSurface> Window::RequestSurface(mojom::SurfaceType type) { mojom::SurfacePtr surface; mojom::SurfaceClientPtr client; mojo::InterfaceRequest<mojom::SurfaceClient> client_request = GetProxy(&client); static_cast<WindowTreeClientImpl*>(connection_) - ->RequestSurface(id_, GetProxy(&surface), client.Pass()); + ->RequestSurface(id_, type, GetProxy(&surface), client.Pass()); return make_scoped_ptr( new WindowSurface(surface.PassInterface(), client_request.Pass())); }
diff --git a/components/mus/public/cpp/lib/window_tree_client_impl.cc b/components/mus/public/cpp/lib/window_tree_client_impl.cc index 9922a73..2191af55 100644 --- a/components/mus/public/cpp/lib/window_tree_client_impl.cc +++ b/components/mus/public/cpp/lib/window_tree_client_impl.cc
@@ -219,10 +219,11 @@ void WindowTreeClientImpl::RequestSurface( Id window_id, + mojom::SurfaceType type, mojo::InterfaceRequest<mojom::Surface> surface, mojom::SurfaceClientPtr client) { DCHECK(tree_); - tree_->RequestSurface(window_id, surface.Pass(), client.Pass()); + tree_->RequestSurface(window_id, type, surface.Pass(), client.Pass()); } void WindowTreeClientImpl::AddWindow(Window* window) {
diff --git a/components/mus/public/cpp/lib/window_tree_client_impl.h b/components/mus/public/cpp/lib/window_tree_client_impl.h index 634047f..38a8c41 100644 --- a/components/mus/public/cpp/lib/window_tree_client_impl.h +++ b/components/mus/public/cpp/lib/window_tree_client_impl.h
@@ -69,6 +69,7 @@ const mus::mojom::WindowTree::EmbedCallback& callback); void RequestSurface(Id window_id, + mojom::SurfaceType type, mojo::InterfaceRequest<mojom::Surface> surface, mojom::SurfaceClientPtr client);
diff --git a/components/mus/public/cpp/tests/BUILD.gn b/components/mus/public/cpp/tests/BUILD.gn index 9db2d6da..ac9fa94 100644 --- a/components/mus/public/cpp/tests/BUILD.gn +++ b/components/mus/public/cpp/tests/BUILD.gn
@@ -48,6 +48,8 @@ "//base/test:test_support", "//components/mus/public/cpp", "//mojo/application/public/cpp", + "//mojo/gles2", + "//mojo/runner:platform_handle", "//testing/gtest", "//third_party/mojo/src/mojo/public/cpp/system", "//third_party/mojo/src/mojo/edk/system",
diff --git a/components/mus/public/cpp/window.h b/components/mus/public/cpp/window.h index c12fb08b..eb7b146 100644 --- a/components/mus/public/cpp/window.h +++ b/components/mus/public/cpp/window.h
@@ -74,7 +74,7 @@ return *viewport_metrics_; } - scoped_ptr<WindowSurface> RequestSurface(); + scoped_ptr<WindowSurface> RequestSurface(mojom::SurfaceType type); // The template-ized versions of the following methods rely on the presence // of a mojo::TypeConverter<const std::vector<uint8_t>, T>.
diff --git a/components/mus/public/interfaces/compositor_frame.mojom b/components/mus/public/interfaces/compositor_frame.mojom index 50c2ea8..b5f1a33 100644 --- a/components/mus/public/interfaces/compositor_frame.mojom +++ b/components/mus/public/interfaces/compositor_frame.mojom
@@ -17,10 +17,30 @@ ETC1, }; +// See src/gpu/command_buffer/common/constants.h +enum CommandBufferNamespace { + INVALID = -1, + + GPU_IO, + IN_PROCESS, + MOJO, + OLD_SYNC_POINTS, + + NUM_COMMAND_BUFFER_NAMESPACES +}; + +// See src/gpu/command_buffer/common/sync_token.h +struct SyncToken { + bool verified_flush; + CommandBufferNamespace namespace_id; + uint64 command_buffer_id; + uint64 release_count; +}; + // See src/cc/resources/returned_resource.h. struct ReturnedResource { uint32 id; - uint32 sync_point; + SyncToken sync_token; int32 count; bool lost; }; @@ -33,8 +53,8 @@ // See src/gpu/command_buffer/common/mailbox_holder.h. struct MailboxHolder { Mailbox mailbox; + SyncToken sync_token; uint32 texture_target; - uint32 sync_point; }; // A TransferableResource is a graphics resource such as a texture or a bitmap
diff --git a/components/mus/public/interfaces/window_tree.mojom b/components/mus/public/interfaces/window_tree.mojom index 485eb49..b30afbe 100644 --- a/components/mus/public/interfaces/window_tree.mojom +++ b/components/mus/public/interfaces/window_tree.mojom
@@ -38,6 +38,19 @@ ILLEGAL_ARGUMENT, }; +// Each Window has support for two surfaces. Generally the |DEFAULT| surface +// is used. The |UNDERLAY| surface is useful if the owner of a window wants to +// to Embed() another client and at the same time draw something under the +// embedded apps representation. +enum SurfaceType { + // Only the owner of a window may obtain this surface. + UNDERLAY, + + // Only the embedded app may obtain this surface. If an app is not embedded + // in the Window than the owner may also render to this surface as well. + DEFAULT, +}; + // Windows are identified by a uint32. The upper 16 bits are the connection id, // and the lower 16 the id assigned by the client. // @@ -93,7 +106,10 @@ array<uint8>? value) => (bool success); // Requests a Surface for a particular window. - RequestSurface(uint32 window_id, Surface& surface, SurfaceClient client); + RequestSurface(uint32 window_id, + SurfaceType type, + Surface& surface, + SurfaceClient client); // Reparents a window. // This fails for any of the following reasons:
diff --git a/components/mus/ws/BUILD.gn b/components/mus/ws/BUILD.gn index 4d1f519..4fa7f94 100644 --- a/components/mus/ws/BUILD.gn +++ b/components/mus/ws/BUILD.gn
@@ -36,6 +36,11 @@ "server_window_observer.h", "server_window_surface.cc", "server_window_surface.h", + "server_window_surface_manager.cc", + "server_window_surface_manager.h", + "transient_window_manager.cc", + "transient_window_manager.h", + "transient_window_observer.h", "window_coordinate_conversions.cc", "window_coordinate_conversions.h", "window_finder.cc", @@ -114,6 +119,7 @@ "server_window_drawn_tracker_unittest.cc", "test_server_window_delegate.cc", "test_server_window_delegate.h", + "transient_window_manager_unittest.cc", "window_coordinate_conversions_unittest.cc", "window_tree_unittest.cc", ] @@ -132,6 +138,7 @@ "//mojo/converters/input_events", "//mojo/converters/transform", "//mojo/environment:chromium", + "//mojo/gles2", "//mojo/platform_handle", "//third_party/mojo/src/mojo/edk/test:run_all_unittests", "//third_party/mojo/src/mojo/public/cpp/bindings:bindings",
diff --git a/components/mus/ws/access_policy.h b/components/mus/ws/access_policy.h index 2a754c46..e1065e7 100644 --- a/components/mus/ws/access_policy.h +++ b/components/mus/ws/access_policy.h
@@ -6,6 +6,7 @@ #define COMPONENTS_MUS_WS_ACCESS_POLICY_H_ #include "components/mus/public/interfaces/mus_constants.mojom.h" +#include "components/mus/public/interfaces/window_tree.mojom.h" #include "components/mus/ws/ids.h" namespace mus { @@ -38,7 +39,8 @@ virtual bool CanEmbed(const ServerWindow* window, uint32_t policy_bitmask) const = 0; virtual bool CanChangeWindowVisibility(const ServerWindow* window) const = 0; - virtual bool CanSetWindowSurfaceId(const ServerWindow* window) const = 0; + virtual bool CanSetWindowSurface(const ServerWindow* window, + mojom::SurfaceType surface_type) const = 0; virtual bool CanSetWindowBounds(const ServerWindow* window) const = 0; virtual bool CanSetWindowProperties(const ServerWindow* window) const = 0; virtual bool CanSetWindowTextInputState(const ServerWindow* window) const = 0;
diff --git a/components/mus/ws/default_access_policy.cc b/components/mus/ws/default_access_policy.cc index 5adbf4a..b6d7494 100644 --- a/components/mus/ws/default_access_policy.cc +++ b/components/mus/ws/default_access_policy.cc
@@ -76,8 +76,12 @@ delegate_->IsRootForAccessPolicy(window->id()); } -bool DefaultAccessPolicy::CanSetWindowSurfaceId( - const ServerWindow* window) const { +bool DefaultAccessPolicy::CanSetWindowSurface( + const ServerWindow* window, + mojom::SurfaceType surface_type) const { + if (surface_type == mojom::SURFACE_TYPE_UNDERLAY) + return WasCreatedByThisConnection(window); + // Once a window embeds another app, the embedder app is no longer able to // call SetWindowSurfaceId() - this ability is transferred to the embedded // app.
diff --git a/components/mus/ws/default_access_policy.h b/components/mus/ws/default_access_policy.h index c004d7a..c1af8f2 100644 --- a/components/mus/ws/default_access_policy.h +++ b/components/mus/ws/default_access_policy.h
@@ -35,7 +35,8 @@ bool CanEmbed(const ServerWindow* window, uint32_t policy_bitmask) const override; bool CanChangeWindowVisibility(const ServerWindow* window) const override; - bool CanSetWindowSurfaceId(const ServerWindow* window) const override; + bool CanSetWindowSurface(const ServerWindow* window, + mus::mojom::SurfaceType surface_type) const override; bool CanSetWindowBounds(const ServerWindow* window) const override; bool CanSetWindowProperties(const ServerWindow* window) const override; bool CanSetWindowTextInputState(const ServerWindow* window) const override;
diff --git a/components/mus/ws/display_manager.cc b/components/mus/ws/display_manager.cc index 25d390d..d40e78f 100644 --- a/components/mus/ws/display_manager.cc +++ b/components/mus/ws/display_manager.cc
@@ -16,6 +16,8 @@ #include "components/mus/surfaces/surfaces_state.h" #include "components/mus/ws/display_manager_factory.h" #include "components/mus/ws/server_window.h" +#include "components/mus/ws/server_window_surface.h" +#include "components/mus/ws/server_window_surface_manager.h" #include "components/mus/ws/window_coordinate_conversions.h" #include "mojo/application/public/cpp/application_connection.h" #include "mojo/application/public/cpp/application_impl.h" @@ -62,12 +64,15 @@ if (!window->visible()) return; - ServerWindowSurface* surface = window->surface(); + ServerWindowSurface* default_surface = + window->surface_manager() ? window->surface_manager()->GetDefaultSurface() + : nullptr; - if (surface) { + if (default_surface) { // Accumulate referenced windows in each ServerWindow's CompositorFrame. - referenced_window_ids->insert(surface->referenced_window_ids().begin(), - surface->referenced_window_ids().end()); + referenced_window_ids->insert( + default_surface->referenced_window_ids().begin(), + default_surface->referenced_window_ids().end()); } const gfx::Rect absolute_bounds = @@ -82,12 +87,20 @@ // If an ancestor has already referenced this window, then we do not need // to create a SurfaceDrawQuad for it. - if (referenced_window_ids->count(window->id()) || !surface) + const bool draw_default_surface = + default_surface && (referenced_window_ids->count(window->id()) == 0); + + ServerWindowSurface* underlay_surface = + window->surface_manager() + ? window->surface_manager()->GetUnderlaySurface() + : nullptr; + if (!draw_default_surface && !underlay_surface) return; + const gfx::Rect bounds_at_origin(window->bounds().size()); + gfx::Transform quad_to_target_transform; quad_to_target_transform.Translate(absolute_bounds.x(), absolute_bounds.y()); - gfx::Rect bounds_at_origin(window->bounds().size()); cc::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState(); // TODO(fsamuel): These clipping and visible rects are incorrect. They need @@ -98,9 +111,20 @@ bounds_at_origin /* clip_rect */, false /* is_clipped */, window->opacity(), SkXfermode::kSrc_Mode, 0 /* sorting-context_id */); - auto surface_quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); - surface_quad->SetNew(sqs, bounds_at_origin /* rect */, - bounds_at_origin /* visible_rect */, surface->id()); + if (draw_default_surface) { + auto quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); + quad->SetAll(sqs, bounds_at_origin /* rect */, + gfx::Rect() /* opaque_rect */, + bounds_at_origin /* visible_rect */, true /* needs_blending*/, + default_surface->id()); + } + if (underlay_surface) { + auto quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); + quad->SetAll(sqs, bounds_at_origin /* rect */, + gfx::Rect() /* opaque_rect */, + bounds_at_origin /* visible_rect */, true /* needs_blending*/, + underlay_surface->id()); + } } } // namespace
diff --git a/components/mus/ws/server_window.cc b/components/mus/ws/server_window.cc index 947a4ef..49a4d91 100644 --- a/components/mus/ws/server_window.cc +++ b/components/mus/ws/server_window.cc
@@ -9,6 +9,7 @@ #include "base/strings/stringprintf.h" #include "components/mus/ws/server_window_delegate.h" #include "components/mus/ws/server_window_observer.h" +#include "components/mus/ws/server_window_surface_manager.h" #include "mojo/converters/geometry/geometry_type_converters.h" namespace mus { @@ -50,9 +51,11 @@ observers_.RemoveObserver(observer); } -void ServerWindow::Bind(mojo::InterfaceRequest<mojom::Surface> request, - mojom::SurfaceClientPtr client) { - GetOrCreateSurface()->Bind(request.Pass(), client.Pass()); +void ServerWindow::CreateSurface(mojom::SurfaceType surface_type, + mojo::InterfaceRequest<mojom::Surface> request, + mojom::SurfaceClientPtr client) { + GetOrCreateSurfaceManager()->CreateSurface(surface_type, request.Pass(), + client.Pass()); } void ServerWindow::Add(ServerWindow* child) { @@ -248,10 +251,10 @@ return root == window; } -ServerWindowSurface* ServerWindow::GetOrCreateSurface() { - if (!surface_) - surface_.reset(new ServerWindowSurface(this)); - return surface_.get(); +ServerWindowSurfaceManager* ServerWindow::GetOrCreateSurfaceManager() { + if (!surface_manager_.get()) + surface_manager_.reset(new ServerWindowSurfaceManager(this)); + return surface_manager_.get(); } #if !defined(NDEBUG)
diff --git a/components/mus/ws/server_window.h b/components/mus/ws/server_window.h index 0f1eb24c..0fa7810c 100644 --- a/components/mus/ws/server_window.h +++ b/components/mus/ws/server_window.h
@@ -25,6 +25,7 @@ class ServerWindowDelegate; class ServerWindowObserver; +class ServerWindowSurfaceManager; // Server side representation of a window. Delegate is informed of interesting // events. @@ -39,16 +40,18 @@ // from the parent. class ServerWindow { public: + using Windows = std::vector<ServerWindow*>; + ServerWindow(ServerWindowDelegate* delegate, const WindowId& id); ~ServerWindow(); void AddObserver(ServerWindowObserver* observer); void RemoveObserver(ServerWindowObserver* observer); - // Binds the provided |request| to |this| object. If an interface is already - // bound to this ServerWindow then the old connection is closed first. - void Bind(mojo::InterfaceRequest<mojom::Surface> request, - mojom::SurfaceClientPtr client); + // Creates a new surface of the specified type, replacing the existing. + void CreateSurface(mojom::SurfaceType surface_type, + mojo::InterfaceRequest<mojom::Surface> request, + mojom::SurfaceClientPtr client); const WindowId& id() const { return id_; } @@ -77,6 +80,7 @@ std::vector<const ServerWindow*> GetChildren() const; std::vector<ServerWindow*> GetChildren(); + const Windows& children() const { return children_; } // Returns the ServerWindow object with the provided |id| if it lies in a // subtree of |this|. @@ -85,8 +89,8 @@ // Returns true if this contains |window| or is |window|. bool Contains(const ServerWindow* window) const; - // Returns true if the window is visible. This does not consider visibility - // of any ancestors. + // Returns the visibility requested by this window. IsDrawn() returns whether + // the window is actually visible on screen. bool visible() const { return visible_; } void SetVisible(bool value); @@ -110,10 +114,10 @@ // visible. bool IsDrawn() const; - // Returns the surface associated with this window. If a surface has not - // yet been allocated for this window, then one is allocated upon invocation. - ServerWindowSurface* GetOrCreateSurface(); - ServerWindowSurface* surface() { return surface_.get(); } + ServerWindowSurfaceManager* GetOrCreateSurfaceManager(); + ServerWindowSurfaceManager* surface_manager() { + return surface_manager_.get(); + } ServerWindowDelegate* delegate() { return delegate_; } @@ -123,7 +127,6 @@ #endif private: - typedef std::vector<ServerWindow*> Windows; // Implementation of removing a window. Doesn't send any notification. void RemoveImpl(ServerWindow* window); @@ -135,7 +138,7 @@ bool visible_; gfx::Rect bounds_; gfx::Rect client_area_; - scoped_ptr<ServerWindowSurface> surface_; + scoped_ptr<ServerWindowSurfaceManager> surface_manager_; float opacity_; gfx::Transform transform_; ui::TextInputState text_input_state_;
diff --git a/components/mus/ws/server_window_surface.cc b/components/mus/ws/server_window_surface.cc index 577cfdaf..8d70cded 100644 --- a/components/mus/ws/server_window_surface.cc +++ b/components/mus/ws/server_window_surface.cc
@@ -10,6 +10,7 @@ #include "components/mus/surfaces/surfaces_state.h" #include "components/mus/ws/server_window.h" #include "components/mus/ws/server_window_delegate.h" +#include "components/mus/ws/server_window_surface_manager.h" #include "mojo/converters/geometry/geometry_type_converters.h" #include "mojo/converters/surfaces/surfaces_type_converters.h" @@ -25,13 +26,21 @@ } // namespace -ServerWindowSurface::ServerWindowSurface(ServerWindow* window) - : window_(window), - surface_id_allocator_(WindowIdToTransportId(window->id())), - surface_factory_(window_->delegate()->GetSurfacesState()->manager(), +ServerWindowSurface::ServerWindowSurface( + ServerWindowSurfaceManager* manager, + mojom::SurfaceType surface_type, + mojo::InterfaceRequest<Surface> request, + mojom::SurfaceClientPtr client) + : manager_(manager), + surface_type_(surface_type), + surface_id_(manager->GenerateId()), + surface_factory_(manager_->window() + ->delegate() + ->GetSurfacesState() + ->manager(), this), - binding_(this) { - surface_id_ = surface_id_allocator_.GenerateId(); + client_(client.Pass()), + binding_(this, request.Pass()) { surface_factory_.Create(surface_id_); } @@ -42,18 +51,6 @@ surface_factory_.DestroyAll(); } -void ServerWindowSurface::Bind(mojo::InterfaceRequest<Surface> request, - mojom::SurfaceClientPtr client) { - if (binding_.is_bound()) { - // Destroy frame surfaces submitted by the old client before replacing - // client_, so those surfaces will be returned to the old client. - surface_factory_.DestroyAll(); - binding_.Close(); - } - binding_.Bind(request.Pass()); - client_ = client.Pass(); -} - void ServerWindowSurface::SubmitCompositorFrame( mojom::CompositorFramePtr frame, const SubmitCompositorFrameCallback& callback) { @@ -63,18 +60,22 @@ // Surface and create a new one of the appropriate size. if (frame_size != last_submitted_frame_size_) { surface_factory_.Destroy(surface_id_); - surface_id_ = surface_id_allocator_.GenerateId(); + surface_id_ = manager_->GenerateId(); surface_factory_.Create(surface_id_); } } surface_factory_.SubmitCompositorFrame(surface_id_, ConvertCompositorFrame(frame), base::Bind(&CallCallback, callback)); - window_->delegate()->GetSurfacesState()->scheduler()->SetNeedsDraw(); - window_->delegate()->OnScheduleWindowPaint(window_); + window()->delegate()->GetSurfacesState()->scheduler()->SetNeedsDraw(); + window()->delegate()->OnScheduleWindowPaint(window()); last_submitted_frame_size_ = frame_size; } +ServerWindow* ServerWindowSurface::window() { + return manager_->window(); +} + scoped_ptr<cc::CompositorFrame> ServerWindowSurface::ConvertCompositorFrame( const mojom::CompositorFramePtr& input) { referenced_window_ids_.clear(); @@ -88,18 +89,37 @@ cc::RenderPass* render_pass) { Id id = static_cast<Id>( input->surface_quad_state->surface.To<cc::SurfaceId>().id); - WindowId window_id = WindowIdFromTransportId(id); - ServerWindow* window = window_->GetChildWindow(window_id); - if (!window) + WindowId other_window_id = WindowIdFromTransportId(id); + ServerWindow* other_window = window()->GetChildWindow(other_window_id); + if (!other_window) return false; - referenced_window_ids_.insert(window_id); + referenced_window_ids_.insert(other_window_id); + + ServerWindowSurface* default_surface = + other_window->GetOrCreateSurfaceManager()->GetDefaultSurface(); + ServerWindowSurface* underlay_surface = + other_window->GetOrCreateSurfaceManager()->GetUnderlaySurface(); + + if (!default_surface && !underlay_surface) + return true; + cc::SurfaceDrawQuad* surface_quad = render_pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); - surface_quad->SetAll( - sqs, input->rect.To<gfx::Rect>(), input->opaque_rect.To<gfx::Rect>(), - input->visible_rect.To<gfx::Rect>(), input->needs_blending, - window->GetOrCreateSurface()->id()); + if (default_surface) { + surface_quad->SetAll(sqs, input->rect.To<gfx::Rect>(), + input->opaque_rect.To<gfx::Rect>(), + input->visible_rect.To<gfx::Rect>(), + input->needs_blending, default_surface->id()); + } + if (underlay_surface) { + cc::SurfaceDrawQuad* underlay_quad = + render_pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); + underlay_quad->SetAll(sqs, input->rect.To<gfx::Rect>(), + input->opaque_rect.To<gfx::Rect>(), + input->visible_rect.To<gfx::Rect>(), + input->needs_blending, underlay_surface->id()); + } return true; }
diff --git a/components/mus/ws/server_window_surface.h b/components/mus/ws/server_window_surface.h index bdf24a1..a9be778b 100644 --- a/components/mus/ws/server_window_surface.h +++ b/components/mus/ws/server_window_surface.h
@@ -5,12 +5,15 @@ #ifndef COMPONENTS_MUS_WS_SERVER_WINDOW_SURFACE_H_ #define COMPONENTS_MUS_WS_SERVER_WINDOW_SURFACE_H_ +#include <set> + #include "base/macros.h" #include "cc/surfaces/surface_factory.h" #include "cc/surfaces/surface_factory_client.h" #include "cc/surfaces/surface_id.h" #include "cc/surfaces/surface_id_allocator.h" #include "components/mus/public/interfaces/compositor_frame.mojom.h" +#include "components/mus/public/interfaces/window_tree.mojom.h" #include "components/mus/ws/ids.h" #include "mojo/converters/surfaces/custom_surface_converter.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h" @@ -22,19 +25,20 @@ namespace ws { class ServerWindow; +class ServerWindowSurfaceManager; // Server side representation of a WindowSurface. class ServerWindowSurface : public mojom::Surface, public cc::SurfaceFactoryClient, public mojo::CustomSurfaceConverter { public: - explicit ServerWindowSurface(ServerWindow* window); + ServerWindowSurface(ServerWindowSurfaceManager* manager, + mojom::SurfaceType surface_type, + mojo::InterfaceRequest<mojom::Surface> request, + mojom::SurfaceClientPtr client); ~ServerWindowSurface() override; - void Bind(mojo::InterfaceRequest<Surface> request, - mojom::SurfaceClientPtr client); - // mojom::Surface: void SubmitCompositorFrame( mojom::CompositorFramePtr frame, @@ -49,6 +53,8 @@ const cc::SurfaceId& id() const { return surface_id_; } private: + ServerWindow* window(); + // Takes a mojom::CompositorFrame |input|, and converts it into a // cc::CompositorFrame. Along the way, this conversion ensures that a // CompositorFrame of this window can only refer to windows within its @@ -68,18 +74,15 @@ void SetBeginFrameSource(cc::SurfaceId surface_id, cc::BeginFrameSource* begin_frame_source) override; - // |window_| owns |this|. - ServerWindow* const window_; + ServerWindowSurfaceManager* manager_; // Owns this. + + const mojom::SurfaceType surface_type_; // The set of Windows referenced in the last submitted CompositorFrame. std::set<WindowId> referenced_window_ids_; gfx::Size last_submitted_frame_size_; cc::SurfaceId surface_id_; - // TODO(fsamuel): As an optimization, we may want to move SurfaceIdAllocator - // and SurfaceFactory to a separate class so that we don't keep destroying - // them and creating new ones on navigation. - cc::SurfaceIdAllocator surface_id_allocator_; cc::SurfaceFactory surface_factory_; mojom::SurfaceClientPtr client_;
diff --git a/components/mus/ws/server_window_surface_manager.cc b/components/mus/ws/server_window_surface_manager.cc new file mode 100644 index 0000000..320ea555 --- /dev/null +++ b/components/mus/ws/server_window_surface_manager.cc
@@ -0,0 +1,48 @@ +// Copyright 2015 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/mus/ws/server_window_surface_manager.h" + +#include "components/mus/ws/server_window.h" +#include "components/mus/ws/server_window_delegate.h" +#include "components/mus/ws/server_window_surface.h" + +namespace mus { +namespace ws { + +ServerWindowSurfaceManager::ServerWindowSurfaceManager(ServerWindow* window) + : window_(window), + surface_id_allocator_(WindowIdToTransportId(window->id())) {} + +ServerWindowSurfaceManager::~ServerWindowSurfaceManager() {} + +void ServerWindowSurfaceManager::CreateSurface( + mojom::SurfaceType surface_type, + mojo::InterfaceRequest<mojom::Surface> request, + mojom::SurfaceClientPtr client) { + type_to_surface_map_.set( + surface_type, make_scoped_ptr(new ServerWindowSurface( + this, surface_type, request.Pass(), client.Pass()))); +} + +ServerWindowSurface* ServerWindowSurfaceManager::GetDefaultSurface() { + return GetSurfaceByType(mojom::SURFACE_TYPE_DEFAULT); +} + +ServerWindowSurface* ServerWindowSurfaceManager::GetUnderlaySurface() { + return GetSurfaceByType(mojom::SURFACE_TYPE_UNDERLAY); +} + +ServerWindowSurface* ServerWindowSurfaceManager::GetSurfaceByType( + mojom::SurfaceType type) { + auto iter = type_to_surface_map_.find(type); + return iter == type_to_surface_map_.end() ? nullptr : iter->second; +} + +cc::SurfaceId ServerWindowSurfaceManager::GenerateId() { + return surface_id_allocator_.GenerateId(); +} + +} // namespace ws +} // namespace mus
diff --git a/components/mus/ws/server_window_surface_manager.h b/components/mus/ws/server_window_surface_manager.h new file mode 100644 index 0000000..7bc52a8aef --- /dev/null +++ b/components/mus/ws/server_window_surface_manager.h
@@ -0,0 +1,62 @@ +// Copyright 2015 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_MUS_WS_SERVER_WINDOW_SURFACE_MANAGER_H_ +#define COMPONENTS_MUS_WS_SERVER_WINDOW_SURFACE_MANAGER_H_ + +#include "base/containers/scoped_ptr_map.h" +#include "base/macros.h" +#include "cc/surfaces/surface_factory.h" +#include "cc/surfaces/surface_id.h" +#include "cc/surfaces/surface_id_allocator.h" +#include "components/mus/public/interfaces/compositor_frame.mojom.h" +#include "components/mus/public/interfaces/window_tree.mojom.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h" + +namespace mus { +namespace ws { + +class ServerWindow; +class ServerWindowSurface; + +// ServerWindowSurfaceManager tracks the surfaces associated with a +// ServerWindow. +class ServerWindowSurfaceManager { + public: + explicit ServerWindowSurfaceManager(ServerWindow* window); + ~ServerWindowSurfaceManager(); + + // Creates a new surface of the specified type, replacing the existing one of + // the specified type. + void CreateSurface(mojom::SurfaceType surface_type, + mojo::InterfaceRequest<mojom::Surface> request, + mojom::SurfaceClientPtr client); + + ServerWindow* window() { return window_; } + + ServerWindowSurface* GetDefaultSurface(); + ServerWindowSurface* GetUnderlaySurface(); + ServerWindowSurface* GetSurfaceByType(mojom::SurfaceType type); + + private: + friend class ServerWindowSurface; + + cc::SurfaceId GenerateId(); + + ServerWindow* window_; + + cc::SurfaceIdAllocator surface_id_allocator_; + + using TypeToSurfaceMap = + base::ScopedPtrMap<mojom::SurfaceType, scoped_ptr<ServerWindowSurface>>; + + TypeToSurfaceMap type_to_surface_map_; + + DISALLOW_COPY_AND_ASSIGN(ServerWindowSurfaceManager); +}; + +} // namespace ws +} // namespace mus + +#endif // COMPONENTS_MUS_WS_SERVER_WINDOW_SURFACE_MANAGER_H_
diff --git a/components/mus/ws/transient_window_manager.cc b/components/mus/ws/transient_window_manager.cc new file mode 100644 index 0000000..29c7d39 --- /dev/null +++ b/components/mus/ws/transient_window_manager.cc
@@ -0,0 +1,108 @@ +// Copyright 2015 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/mus/ws/transient_window_manager.h" + +#include "base/auto_reset.h" +#include "base/lazy_instance.h" +#include "base/stl_util.h" +#include "components/mus/ws/server_window.h" +#include "components/mus/ws/transient_window_observer.h" + +namespace mus { +namespace ws { + +namespace { +using TransientWindowManagerMap = + std::map<const ServerWindow*, TransientWindowManager*>; + +static base::LazyInstance<TransientWindowManagerMap> + transient_window_manager_map = LAZY_INSTANCE_INITIALIZER; +} + +TransientWindowManager::~TransientWindowManager() {} + +// static +TransientWindowManager* TransientWindowManager::GetOrCreate( + ServerWindow* window) { + TransientWindowManagerMap* map = transient_window_manager_map.Pointer(); + auto it = map->find(window); + if (it != map->end()) + return it->second; + TransientWindowManager* manager = new TransientWindowManager(window); + transient_window_manager_map.Get().insert(std::make_pair(window, manager)); + return manager; +} + +// static +TransientWindowManager* TransientWindowManager::Get(ServerWindow* window) { + TransientWindowManagerMap* map = transient_window_manager_map.Pointer(); + auto it = map->find(window); + return it == map->end() ? nullptr : it->second; +} + +void TransientWindowManager::AddObserver(TransientWindowObserver* observer) { + observers_.AddObserver(observer); +} + +void TransientWindowManager::RemoveObserver(TransientWindowObserver* observer) { + observers_.RemoveObserver(observer); +} + +void TransientWindowManager::AddTransientChild(ServerWindow* child) { + TransientWindowManager* child_manager = GetOrCreate(child); + if (child_manager->transient_parent_) + Get(child_manager->transient_parent_)->RemoveTransientChild(child); + DCHECK(std::find(transient_children_.begin(), transient_children_.end(), + child) == transient_children_.end()); + transient_children_.push_back(child); + child_manager->transient_parent_ = window_; + + FOR_EACH_OBSERVER(TransientWindowObserver, observers_, + OnTransientChildAdded(window_, child)); +} + +void TransientWindowManager::RemoveTransientChild(ServerWindow* child) { + Windows::iterator i = + std::find(transient_children_.begin(), transient_children_.end(), child); + DCHECK(i != transient_children_.end()); + transient_children_.erase(i); + TransientWindowManager* child_manager = Get(child); + DCHECK(child_manager); + DCHECK_EQ(window_, child_manager->transient_parent_); + child_manager->transient_parent_ = nullptr; + + FOR_EACH_OBSERVER(TransientWindowObserver, observers_, + OnTransientChildRemoved(window_, child)); +} + +TransientWindowManager::TransientWindowManager(ServerWindow* window) + : window_(window), + transient_parent_(nullptr) { + window_->AddObserver(this); +} + +void TransientWindowManager::OnWillDestroyWindow(ServerWindow* window) { + // Removes ourselves from our transient parent (if it hasn't been done by the + // RootWindow). + if (transient_parent_) { + TransientWindowManager::Get(transient_parent_) + ->RemoveTransientChild(window_); + } + + // Destroy transient children, only after we've removed ourselves from our + // parent, as destroying an active transient child may otherwise attempt to + // refocus us. + Windows transient_children(transient_children_); + STLDeleteElements(&transient_children); + DCHECK(transient_children_.empty()); +} + +void TransientWindowManager::OnWindowDestroyed(ServerWindow* window) { + transient_window_manager_map.Get().erase(window_); + delete this; +} + +} // namespace ws +} // namespace mus
diff --git a/components/mus/ws/transient_window_manager.h b/components/mus/ws/transient_window_manager.h new file mode 100644 index 0000000..4c78ee9 --- /dev/null +++ b/components/mus/ws/transient_window_manager.h
@@ -0,0 +1,71 @@ +// Copyright 2015 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_MUS_WS_TRANSIENT_WINDOW_MANAGER_H_ +#define COMPONENTS_MUS_WS_TRANSIENT_WINDOW_MANAGER_H_ + +#include "base/macros.h" +#include "base/observer_list.h" +#include "components/mus/ws/server_window_observer.h" + +namespace mus { +namespace ws { + +class TransientWindowObserver; + +// TransientWindowManager manages the set of transient children for a window +// along with the transient parent. Transient children get the following +// behavior: +// . The transient parent destroys any transient children when it is +// destroyed. This means a transient child is destroyed if either its parent +// or transient parent is destroyed. +// . TODO(fsamuel): If a transient child and its transient parent share the same +// parent, then transient children are always ordered above the transient +// parent. +// Transient windows are typically used for popups and menus. +class TransientWindowManager : public ServerWindowObserver { + public: + using Windows = std::vector<ServerWindow*>; + + ~TransientWindowManager() override; + + // Returns the TransientWindowManager for |window|. This never returns + // nullptr. + static TransientWindowManager* GetOrCreate(ServerWindow* window); + + // Returns the TransientWindowManager for |window| only if it already exists. + // WARNING: this may return nullptr. + static TransientWindowManager* Get(ServerWindow* window); + + void AddObserver(TransientWindowObserver* observer); + void RemoveObserver(TransientWindowObserver* observer); + + void AddTransientChild(ServerWindow* child); + void RemoveTransientChild(ServerWindow* child); + + const Windows& transient_children() const { return transient_children_; } + + ServerWindow* transient_parent() { return transient_parent_; } + const ServerWindow* transient_parent() const { return transient_parent_; } + + private: + explicit TransientWindowManager(ServerWindow* window); + + // ServerWindowObserver: + void OnWillDestroyWindow(ServerWindow* window) override; + void OnWindowDestroyed(ServerWindow* window) override; + + ServerWindow* window_; + ServerWindow* transient_parent_; + Windows transient_children_; + + base::ObserverList<TransientWindowObserver> observers_; + + DISALLOW_COPY_AND_ASSIGN(TransientWindowManager); +}; + +} // namespace ws +} // namespace mus + +#endif // COMPONENTS_MUS_WS_TRANSIENT_WINDOW_MANAGER_H_
diff --git a/components/mus/ws/transient_window_manager_unittest.cc b/components/mus/ws/transient_window_manager_unittest.cc new file mode 100644 index 0000000..c923a9fc --- /dev/null +++ b/components/mus/ws/transient_window_manager_unittest.cc
@@ -0,0 +1,96 @@ +// Copyright 2015 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/mus/ws/server_window.h" +#include "components/mus/ws/test_server_window_delegate.h" +#include "components/mus/ws/transient_window_manager.h" +#include "components/mus/ws/transient_window_observer.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mus { + +namespace ws { + +namespace { + +class TestTransientWindowObserver : public TransientWindowObserver { + public: + TestTransientWindowObserver() : add_count_(0), remove_count_(0) {} + + ~TestTransientWindowObserver() override {} + + int add_count() const { return add_count_; } + int remove_count() const { return remove_count_; } + + // TransientWindowObserver overrides: + void OnTransientChildAdded(ServerWindow* window, + ServerWindow* transient) override { + add_count_++; + } + void OnTransientChildRemoved(ServerWindow* window, + ServerWindow* transient) override { + remove_count_++; + } + + private: + int add_count_; + int remove_count_; + + DISALLOW_COPY_AND_ASSIGN(TestTransientWindowObserver); +}; + +ServerWindow* CreateTestWindow(TestServerWindowDelegate* delegate, + const WindowId& window_id, + ServerWindow* parent) { + ServerWindow* window = new ServerWindow(delegate, window_id); + window->SetVisible(true); + if (parent) + parent->Add(window); + else + delegate->set_root_window(window); + return window; +} + +void AddTransientChild(ServerWindow* parent, ServerWindow* child) { + TransientWindowManager::GetOrCreate(parent)->AddTransientChild(child); +} + +} // namespace + +class TransientWindowManagerTest : public testing::Test { + public: + TransientWindowManagerTest() {} + ~TransientWindowManagerTest() override {} + + private: + DISALLOW_COPY_AND_ASSIGN(TransientWindowManagerTest); +}; + +TEST(TransientWindowManagerTest, TransientChildren) { + TestServerWindowDelegate server_window_delegate; + + scoped_ptr<ServerWindow> parent( + CreateTestWindow(&server_window_delegate, WindowId(), nullptr)); + scoped_ptr<ServerWindow> w1( + CreateTestWindow(&server_window_delegate, WindowId(1, 1), parent.get())); + scoped_ptr<ServerWindow> w3( + CreateTestWindow(&server_window_delegate, WindowId(1, 2), parent.get())); + + ServerWindow* w2 = + CreateTestWindow(&server_window_delegate, WindowId(1, 3), parent.get()); + // w2 is now owned by w1. + AddTransientChild(w1.get(), w2); + ASSERT_EQ(3u, parent->children().size()); + EXPECT_EQ(w2, parent->children().back()); + + // Destroy w1, which should also destroy w3 (since it's a transient child). + w1.reset(); + w2 = nullptr; + ASSERT_EQ(1u, parent->children().size()); + EXPECT_EQ(w3.get(), parent->children()[0]); +} + +} // namespace ws + +} // namespace mus
diff --git a/components/mus/ws/transient_window_observer.h b/components/mus/ws/transient_window_observer.h new file mode 100644 index 0000000..8485250 --- /dev/null +++ b/components/mus/ws/transient_window_observer.h
@@ -0,0 +1,28 @@ +// Copyright 2015 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_MUS_WS_TRANSIENT_WINDOW_OBSERVER_H_ +#define COMPONENTS_MUS_WS_TRANSIENT_WINDOW_OBSERVER_H_ + +namespace mus { +namespace ws { + +class TransientWindowObserver { + public: + // Called when a transient child is added to |window|. + virtual void OnTransientChildAdded(ServerWindow* window, + ServerWindow* transient_child) = 0; + + // Called when a transient child is removed from |window|. + virtual void OnTransientChildRemoved(ServerWindow* window, + ServerWindow* transient_child) = 0; + + protected: + virtual ~TransientWindowObserver() {} +}; + +} // namespace ws +} // namespace mus + +#endif // COMPONENTS_MUS_WS_TRANSIENT_WINDOW_OBSERVER_H_
diff --git a/components/mus/ws/window_finder.cc b/components/mus/ws/window_finder.cc index 422d2ff5..5f41121 100644 --- a/components/mus/ws/window_finder.cc +++ b/components/mus/ws/window_finder.cc
@@ -8,6 +8,8 @@ #include "components/mus/surfaces/surfaces_state.h" #include "components/mus/ws/server_window.h" #include "components/mus/ws/server_window_delegate.h" +#include "components/mus/ws/server_window_surface.h" +#include "components/mus/ws/server_window_surface_manager.h" #include "components/mus/ws/window_coordinate_conversions.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point_f.h" @@ -46,6 +48,21 @@ return transform; } +bool HitTestSurfaceOfType(cc::SurfaceId display_surface_id, + ServerWindow* window, + mus::mojom::SurfaceType surface_type, + gfx::Transform* transform) { + *transform = gfx::Transform(); + ServerWindowSurface* surface = + window->GetOrCreateSurfaceManager()->GetSurfaceByType(surface_type); + return surface && + window->delegate() + ->GetSurfacesState() + ->hit_tester() + ->GetTransformToTargetSurface(display_surface_id, surface->id(), + transform); +} + } // namespace ServerWindow* FindDeepestVisibleWindow(ServerWindow* root_window, @@ -76,14 +93,14 @@ gfx::Transform GetTransformToWindow(cc::SurfaceId display_surface_id, ServerWindow* window) { - gfx::Transform transform; - if (!display_surface_id.is_null() && - window->delegate() - ->GetSurfacesState() - ->hit_tester() - ->GetTransformToTargetSurface(display_surface_id, - window->surface()->id(), &transform)) { - return transform; + if (!display_surface_id.is_null()) { + gfx::Transform transform; + if (HitTestSurfaceOfType(display_surface_id, window, + mus::mojom::SURFACE_TYPE_DEFAULT, &transform) || + HitTestSurfaceOfType(display_surface_id, window, + mus::mojom::SURFACE_TYPE_UNDERLAY, &transform)) { + return transform; + } } return GetTransformToWindowNonSurface(window);
diff --git a/components/mus/ws/window_manager_access_policy.cc b/components/mus/ws/window_manager_access_policy.cc index fa1ebd4..ce5b600 100644 --- a/components/mus/ws/window_manager_access_policy.cc +++ b/components/mus/ws/window_manager_access_policy.cc
@@ -65,8 +65,12 @@ (window->GetRoot() == window); } -bool WindowManagerAccessPolicy::CanSetWindowSurfaceId( - const ServerWindow* window) const { +bool WindowManagerAccessPolicy::CanSetWindowSurface( + const ServerWindow* window, + mus::mojom::SurfaceType surface_type) const { + if (surface_type == mojom::SURFACE_TYPE_UNDERLAY) + return window->id().connection_id == connection_id_; + if (delegate_->IsWindowRootOfAnotherConnectionForAccessPolicy(window)) return false; return window->id().connection_id == connection_id_ ||
diff --git a/components/mus/ws/window_manager_access_policy.h b/components/mus/ws/window_manager_access_policy.h index 0476ff0de..ddeccdd 100644 --- a/components/mus/ws/window_manager_access_policy.h +++ b/components/mus/ws/window_manager_access_policy.h
@@ -34,7 +34,8 @@ bool CanEmbed(const ServerWindow* window, uint32_t policy_bitmask) const override; bool CanChangeWindowVisibility(const ServerWindow* window) const override; - bool CanSetWindowSurfaceId(const ServerWindow* window) const override; + bool CanSetWindowSurface(const ServerWindow* window, + mus::mojom::SurfaceType surface_type) const override; bool CanSetWindowBounds(const ServerWindow* window) const override; bool CanSetWindowProperties(const ServerWindow* window) const override; bool CanSetWindowTextInputState(const ServerWindow* window) const override;
diff --git a/components/mus/ws/window_tree_impl.cc b/components/mus/ws/window_tree_impl.cc index 08a8ca4..e4eca337c 100644 --- a/components/mus/ws/window_tree_impl.cc +++ b/components/mus/ws/window_tree_impl.cc
@@ -634,13 +634,15 @@ void WindowTreeImpl::RequestSurface( Id window_id, + mojom::SurfaceType type, mojo::InterfaceRequest<mojom::Surface> surface, mojom::SurfaceClientPtr client) { ServerWindow* window = GetWindow(WindowIdFromTransportId(window_id)); - const bool success = window && access_policy_->CanSetWindowSurfaceId(window); + const bool success = + window && access_policy_->CanSetWindowSurface(window, type); if (!success) return; - window->Bind(surface.Pass(), client.Pass()); + window->CreateSurface(type, surface.Pass(), client.Pass()); } void WindowTreeImpl::SetWindowTextInputState(uint32_t window_id,
diff --git a/components/mus/ws/window_tree_impl.h b/components/mus/ws/window_tree_impl.h index 100bd38..9b45197 100644 --- a/components/mus/ws/window_tree_impl.h +++ b/components/mus/ws/window_tree_impl.h
@@ -205,6 +205,7 @@ mojo::Array<uint8_t> value, const mojo::Callback<void(bool)>& callback) override; void RequestSurface(Id window_id, + mojom::SurfaceType type, mojo::InterfaceRequest<mojom::Surface> surface, mojom::SurfaceClientPtr client) override; void Embed(Id transport_window_id,
diff --git a/components/omnibox/browser/shortcuts_backend.cc b/components/omnibox/browser/shortcuts_backend.cc index 4fbd7dc..99d6f84 100644 --- a/components/omnibox/browser/shortcuts_backend.cc +++ b/components/omnibox/browser/shortcuts_backend.cc
@@ -12,6 +12,7 @@ #include "base/bind_helpers.h" #include "base/guid.h" #include "base/i18n/case_conversion.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" #include "base/thread_task_runner_handle.h" #include "components/history/core/browser/history_service.h" @@ -221,6 +222,8 @@ temp_shortcuts_map_->swap(shortcuts_map_); temp_shortcuts_map_.reset(NULL); temp_guid_map_.reset(NULL); + UMA_HISTOGRAM_COUNTS_10000("ShortcutsProvider.DatabaseSize", + shortcuts_map_.size()); current_state_ = INITIALIZED; FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_, OnShortcutsLoaded());
diff --git a/components/password_manager.gypi b/components/password_manager.gypi index 4349303..8db288e8 100644 --- a/components/password_manager.gypi +++ b/components/password_manager.gypi
@@ -227,6 +227,8 @@ # Note: sources list duplicated in GN build. 'password_manager/sync/browser/password_data_type_controller.cc', 'password_manager/sync/browser/password_data_type_controller.h', + 'password_manager/sync/browser/password_manager_setting_migrator_service.cc', + 'password_manager/sync/browser/password_manager_setting_migrator_service.h', 'password_manager/sync/browser/password_model_worker.cc', 'password_manager/sync/browser/password_model_worker.h', 'password_manager/sync/browser/password_sync_util.cc',
diff --git a/components/password_manager/content/browser/content_password_manager_driver_factory.cc b/components/password_manager/content/browser/content_password_manager_driver_factory.cc index c3e6e1f4..ae8478bf 100644 --- a/components/password_manager/content/browser/content_password_manager_driver_factory.cc +++ b/components/password_manager/content/browser/content_password_manager_driver_factory.cc
@@ -82,7 +82,7 @@ void ContentPasswordManagerDriverFactory::RenderFrameCreated( content::RenderFrameHost* render_frame_host) { // This is called twice for the main frame. - if (!frame_driver_map_[render_frame_host]) + if (!ContainsKey(frame_driver_map_, render_frame_host)) CreateDriverForFrame(render_frame_host); } @@ -107,6 +107,8 @@ void ContentPasswordManagerDriverFactory::CreateDriverForFrame( content::RenderFrameHost* render_frame_host) { + if (!render_frame_host->IsRenderFrameLive()) + return; DCHECK(!frame_driver_map_[render_frame_host]); frame_driver_map_[render_frame_host] = new ContentPasswordManagerDriver( render_frame_host, password_client_, autofill_client_);
diff --git a/components/password_manager/sync/browser/BUILD.gn b/components/password_manager/sync/browser/BUILD.gn index 7975208..ca53977a0 100644 --- a/components/password_manager/sync/browser/BUILD.gn +++ b/components/password_manager/sync/browser/BUILD.gn
@@ -6,6 +6,8 @@ sources = [ "password_data_type_controller.cc", "password_data_type_controller.h", + "password_manager_setting_migrator_service.cc", + "password_manager_setting_migrator_service.h", "password_model_worker.cc", "password_model_worker.h", "password_sync_util.cc", @@ -29,6 +31,7 @@ source_set("unit_tests") { testonly = true sources = [ + "password_manager_setting_migrator_service_unittest.cc", "password_sync_util_unittest.cc", "sync_store_result_filter_unittest.cc", "sync_username_test_base.cc", @@ -38,6 +41,8 @@ ":browser", "//components/pref_registry", "//components/signin/core/common", + "//components/syncable_prefs", + "//components/syncable_prefs:test_support", "//sync", "//testing/gmock", "//testing/gtest",
diff --git a/components/password_manager/sync/browser/DEPS b/components/password_manager/sync/browser/DEPS index eb06dfc..e57a4e1c 100644 --- a/components/password_manager/sync/browser/DEPS +++ b/components/password_manager/sync/browser/DEPS
@@ -1,8 +1,10 @@ include_rules = [ + "+components/keyed_service/core", "+components/pref_registry", "+components/signin/core/browser", "+components/signin/core/common", "+components/sync_driver", + "+components/syncable_prefs", "+google_apis/gaia", "+sync/internal_api/public", ]
diff --git a/components/password_manager/sync/browser/password_manager_setting_migrator_service.cc b/components/password_manager/sync/browser/password_manager_setting_migrator_service.cc new file mode 100644 index 0000000..84d2956 --- /dev/null +++ b/components/password_manager/sync/browser/password_manager_setting_migrator_service.cc
@@ -0,0 +1,233 @@ +// Copyright (c) 2015 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/password_manager/sync/browser/password_manager_setting_migrator_service.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/metrics/histogram_macros.h" +#include "components/password_manager/core/browser/password_manager_settings_migration_experiment.h" +#include "components/password_manager/core/common/password_manager_pref_names.h" +#include "components/sync_driver/sync_service.h" +#include "components/syncable_prefs/pref_service_syncable.h" + +namespace { + +bool GetBooleanUserOrDefaultPrefValue(PrefService* prefs, + const std::string& name) { + bool result = false; + const base::Value* value = prefs->GetUserPrefValue(name); + if (!value) + value = prefs->GetDefaultPrefValue(name); + value->GetAsBoolean(&result); + return result; +} + +void ChangeOnePrefBecauseAnotherPrefHasChanged( + PrefService* prefs, + const std::string& other_pref_name, + const std::string& changed_pref_name) { + bool changed_pref = + GetBooleanUserOrDefaultPrefValue(prefs, changed_pref_name); + bool other_pref = GetBooleanUserOrDefaultPrefValue(prefs, other_pref_name); + if (changed_pref != other_pref) + prefs->SetBoolean(other_pref_name, changed_pref); +} + +// Change value of both kPasswordManagerSavingEnabled and +// kCredentialsEnableService to the |new_value|. +void UpdatePreferencesValues(PrefService* prefs, bool new_value) { + prefs->SetBoolean(password_manager::prefs::kPasswordManagerSavingEnabled, + new_value); + prefs->SetBoolean(password_manager::prefs::kCredentialsEnableService, + new_value); +} + +void SaveCurrentPrefState(PrefService* prefs, + bool* new_pref_value, + bool* legacy_pref_value) { + *new_pref_value = GetBooleanUserOrDefaultPrefValue( + prefs, password_manager::prefs::kCredentialsEnableService); + *legacy_pref_value = GetBooleanUserOrDefaultPrefValue( + prefs, password_manager::prefs::kPasswordManagerSavingEnabled); +} + +void TrackInitialAndFinalValues(PrefService* prefs, + bool initial_new_pref_value, + bool initial_legacy_pref_value) { + bool final_new_pref_value = + prefs->GetBoolean(password_manager::prefs::kCredentialsEnableService); + bool final_legacy_pref_value = + prefs->GetBoolean(password_manager::prefs::kPasswordManagerSavingEnabled); + const int kMaxInitValue = 0x10; + int value_to_log = 0; + const int kInitialNewValueMask = 0x8; + const int kInitialLegacyValueMask = 0x4; + const int kFinalNewValueMask = 0x2; + const int kFinalLegacyValueMask = 0x1; + if (initial_new_pref_value) + value_to_log |= kInitialNewValueMask; + if (initial_legacy_pref_value) + value_to_log |= kInitialLegacyValueMask; + if (final_new_pref_value) + value_to_log |= kFinalNewValueMask; + if (final_legacy_pref_value) + value_to_log |= kFinalLegacyValueMask; + UMA_HISTOGRAM_ENUMERATION( + "PasswordManager.SettingsReconciliation.InitialAndFinalValues", + value_to_log, kMaxInitValue); +} + +} // namespace + +namespace password_manager { + +PasswordManagerSettingMigratorService::PasswordManagerSettingMigratorService( + syncable_prefs::PrefServiceSyncable* prefs) + : prefs_(prefs), sync_service_(nullptr) { + SaveCurrentPrefState(prefs_, &initial_new_pref_value_, + &initial_legacy_pref_value_); +} + +PasswordManagerSettingMigratorService:: + ~PasswordManagerSettingMigratorService() {} + +void PasswordManagerSettingMigratorService::InitializeMigration( + sync_driver::SyncService* sync_service) { + SaveCurrentPrefState(prefs_, &initial_new_pref_value_, + &initial_legacy_pref_value_); + const int kMaxInitialValues = 4; + UMA_HISTOGRAM_ENUMERATION( + "PasswordManager.SettingsReconciliation.InitialValues", + (static_cast<int>(initial_new_pref_value_) << 1 | + static_cast<int>(initial_legacy_pref_value_)), + kMaxInitialValues); + if (!password_manager::IsSettingsMigrationActive()) { + return; + } + sync_service_ = sync_service; + if (!sync_service_ || !CanSyncStart()) { + MigrateOffState(prefs_); + TrackInitialAndFinalValues(prefs_, initial_new_pref_value_, + initial_legacy_pref_value_); + } + InitObservers(); +} + +void PasswordManagerSettingMigratorService::InitObservers() { + pref_change_registrar_.Init(prefs_); + pref_change_registrar_.Add( + password_manager::prefs::kCredentialsEnableService, + base::Bind(&PasswordManagerSettingMigratorService:: + OnCredentialsEnableServicePrefChanged, + base::Unretained(this))); + pref_change_registrar_.Add( + password_manager::prefs::kPasswordManagerSavingEnabled, + base::Bind(&PasswordManagerSettingMigratorService:: + OnPasswordManagerSavingEnabledPrefChanged, + base::Unretained(this))); + // This causes OnIsSyncingChanged to be called when the value of + // PrefService::IsSyncing() changes. + prefs_->AddObserver(this); +} + +bool PasswordManagerSettingMigratorService::CanSyncStart() { + return sync_service_ && sync_service_->CanSyncStart() && + syncer::UserSelectableTypes().Has(syncer::PREFERENCES); +} + +void PasswordManagerSettingMigratorService::Shutdown() { + prefs_->RemoveObserver(this); +} + +void PasswordManagerSettingMigratorService:: + OnCredentialsEnableServicePrefChanged( + const std::string& changed_pref_name) { + sync_data_.push_back(GetBooleanUserOrDefaultPrefValue( + prefs_, password_manager::prefs::kCredentialsEnableService)); + ChangeOnePrefBecauseAnotherPrefHasChanged( + prefs_, password_manager::prefs::kPasswordManagerSavingEnabled, + password_manager::prefs::kCredentialsEnableService); +} + +void PasswordManagerSettingMigratorService:: + OnPasswordManagerSavingEnabledPrefChanged( + const std::string& changed_pref_name) { + sync_data_.push_back(GetBooleanUserOrDefaultPrefValue( + prefs_, password_manager::prefs::kPasswordManagerSavingEnabled)); + ChangeOnePrefBecauseAnotherPrefHasChanged( + prefs_, password_manager::prefs::kCredentialsEnableService, + password_manager::prefs::kPasswordManagerSavingEnabled); +} + +void PasswordManagerSettingMigratorService::OnIsSyncingChanged() { + if (WasModelAssociationStepPerformed()) { + // Initial sync has finished. + MigrateAfterModelAssociation(prefs_); + } + + if (prefs_->IsSyncing() == prefs_->IsPrioritySyncing()) { + // Sync is not in model association step. + SaveCurrentPrefState(prefs_, &initial_new_pref_value_, + &initial_legacy_pref_value_); + sync_data_.clear(); + } +} + +bool PasswordManagerSettingMigratorService::WasModelAssociationStepPerformed() { +#if defined(OS_ANDROID) + return prefs_->IsPrioritySyncing(); +#else + return prefs_->IsSyncing() && prefs_->IsPrioritySyncing(); +#endif +} + +void PasswordManagerSettingMigratorService::MigrateOffState( + PrefService* prefs) { + bool new_pref_value = GetBooleanUserOrDefaultPrefValue( + prefs_, password_manager::prefs::kCredentialsEnableService); + bool legacy_pref_value = GetBooleanUserOrDefaultPrefValue( + prefs_, password_manager::prefs::kPasswordManagerSavingEnabled); + UpdatePreferencesValues(prefs, new_pref_value && legacy_pref_value); +} + +void PasswordManagerSettingMigratorService::MigrateAfterModelAssociation( + PrefService* prefs) { + if (sync_data_.empty()) { + MigrateOffState(prefs); + } else if (sync_data_.size() == 1) { +#if defined(OS_ANDROID) + if (initial_new_pref_value_ != initial_legacy_pref_value_) { + // Treat special case for mobile clients where only priority pref + // arrives on the client. + if (!initial_new_pref_value_ && initial_legacy_pref_value_) + UpdatePreferencesValues(prefs, true); + else + UpdatePreferencesValues(prefs, false); + } else { + UpdatePreferencesValues(prefs, sync_data_[0]); + } +#else + // Only one value came from sync. This value should be assigned to both + // preferences. + UpdatePreferencesValues(prefs, sync_data_[0]); +#endif + } else { + bool sync_new_pref_value = sync_data_[0]; + bool sync_legacy_pref_value = sync_data_.back(); + if (sync_legacy_pref_value && sync_new_pref_value) { + UpdatePreferencesValues(prefs, true); + } else if (!sync_legacy_pref_value && !sync_new_pref_value) { + UpdatePreferencesValues(prefs, false); + } else if (!initial_legacy_pref_value_ && !initial_new_pref_value_) { + UpdatePreferencesValues(prefs, true); + } else { + UpdatePreferencesValues(prefs, false); + } + } + TrackInitialAndFinalValues(prefs, initial_new_pref_value_, + initial_legacy_pref_value_); +} + +} // namespace password_manager
diff --git a/components/password_manager/sync/browser/password_manager_setting_migrator_service.h b/components/password_manager/sync/browser/password_manager_setting_migrator_service.h new file mode 100644 index 0000000..4b1476d --- /dev/null +++ b/components/password_manager/sync/browser/password_manager_setting_migrator_service.h
@@ -0,0 +1,154 @@ +// Copyright (c) 2015 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_PASSWORD_MANAGER_SYNC_BROWSER_PASSWORD_MANAGER_SETTING_MIGRATOR_SERVICE_H_ +#define COMPONENTS_PASSWORD_MANAGER_SYNC_BROWSER_PASSWORD_MANAGER_SETTING_MIGRATOR_SERVICE_H_ + +#include <vector> + +#include "base/macros.h" +#include "base/memory/singleton.h" +#include "base/prefs/pref_change_registrar.h" +#include "components/keyed_service/core/keyed_service.h" +#include "components/syncable_prefs/pref_service_syncable_observer.h" + +namespace sync_driver { +class SyncService; +} + +namespace syncable_prefs { +class PrefServiceSyncable; +} + +namespace password_manager { + +// Service that is responsible for reconciling the legacy "Offer to save your +// web passwords" setting (henceforth denoted 'L', for legacy) with the new +// "Enable Smart Lock for Passwords" setting (henceforth denoted 'N', for new). +// +// It works as follows. +// +// Users who are not syncing (this is checked on start-up of the service +// calling to SyncService:CanSyncStart()) are migrated on startup of the +// service. These users can be in following states: +// 1. N = 0, L = 0 +// 2. N = 1, L = 1 +// 3. N = 1, L = 0 +// 4. N = 0, L = 1 +// +// Nothing should be done in case 1 and 2 since settings are already in sync; +// in case 3,4 we change value of N to 0. +// +// For users who are syncing we save the values for the new and legacy +// preference on service startup (|inital_values_|) and the values that come +// from sync during models association step (|sync_data_|). Propagating change +// of one preference to another preference without having this special treatment +// will not always work. Here is an example which illustrates possible corner +// case: the client executes the migration code for the first time, legacy +// preference has a value 1, new preference was registered for the +// first time and has default value which is also 1, the sync data snapshot +// which user has on a client contains new preference equal to 0 and old +// preference equal to 1, if we blindly propagate these values we first get +// both preferences equal to 0 after priority pref model was associated and +// then both preferences equal to 1 after preferences model was associated. +// But the correct final value in this case is 0. +// +// At the end of model association step we derive the new values for both +// settings using the following table (first column contains local values for +// the preferences, first row contains values which came from sync, where _ +// means that the value did not come): +// +// NL* 0_ 1_ _0 _1 00 01 10 11 +// +// 00 00 11 00 11 00 11 11 11 +// 01 00* 11* x x 00 00 00 11 +// 10 00* 00* x x 00 00 00 11 +// 11 00 11 00 11 00 00 00 11 +// +// *these cases only possible on mobile platforms, where we sync only priority +// preference data type. +// +// The service observes changes to both preferences (e.g. changes from sync, +// changes from UI) and propagates the change to the other preference if needed. +// +// Note: componetization of this service currently is impossible, because it +// depends on PrefServiceSyncable https://crbug.com/522536. +class PasswordManagerSettingMigratorService + : public KeyedService, + public syncable_prefs::PrefServiceSyncableObserver { + public: + explicit PasswordManagerSettingMigratorService( + syncable_prefs::PrefServiceSyncable* prefs); + ~PasswordManagerSettingMigratorService() override; + + void Shutdown() override; + + // PrefServiceSyncableObserver: + void OnIsSyncingChanged() override; + + void InitializeMigration(sync_driver::SyncService* sync_service); + + private: + // Initializes the observers: preferences observers and sync status observers. + void InitObservers(); + + // Returns true if sync is expected to start for the user. + bool CanSyncStart(); + + // Called when the value of the |kCredentialsEnableService| preference + // changes, and updates the value of |kPasswordManagerSavingEnabled| + // preference accordingly. + void OnCredentialsEnableServicePrefChanged( + const std::string& changed_pref_name); + + // Called when the value of the |kPasswordManagerSavingEnabled| preference + // changes, and updates the value of |kCredentialsEnableService| preference + // accordingly. + void OnPasswordManagerSavingEnabledPrefChanged( + const std::string& changed_pref_name); + + // Determines if model association step was performed. For desktop platforms, + // the condition is that for both priority preferences and regular preferences + // types association step was finished. For mobile platforms, the association + // only for priority prefs is required. + bool WasModelAssociationStepPerformed(); + + // Turns off one pref if another pref is off. + void MigrateOffState(PrefService* prefs); + + // Performs a migration after sync associates models. Migration is performed + // based on initial values for both preferences and values received from + // sync. + void MigrateAfterModelAssociation(PrefService* prefs); + + // Contains values which have come from sync during model association step. + // The vector minimum size is 0 and the vector maximum size is 4: + // * sync_data_ has length equal to 0, when no change to the preferences has + // came from sync. + // * sync_data has length equal to 1, when change to only one preference + // came from sync and another pref already had this value, e.g local state + // 01 and N=1 came from sync. + // * sync_data has length equals to 4, changes to both preference has came + // from sync, e.g. local state is 11 and 01 came from sync. + // This way index 0 corresponds to kCredentialsEnableService, last index + // corresponds to kPasswordManagerSavingEnabled if size of sync_data_ equals + // to 4, otherwise the vector contains the value only for one preference. + std::vector<bool> sync_data_; + + // The initial value for kCredentialsEnableService. + bool initial_new_pref_value_; + // The initial value for kPasswordManagerSavingEnabled. + bool initial_legacy_pref_value_; + + syncable_prefs::PrefServiceSyncable* prefs_; + sync_driver::SyncService* sync_service_; + + PrefChangeRegistrar pref_change_registrar_; + + DISALLOW_COPY_AND_ASSIGN(PasswordManagerSettingMigratorService); +}; + +} // namespace password_manager + +#endif // COMPONENTS_PASSWORD_MANAGER_SYNC_BROWSER_PASSWORD_MANAGER_SETTING_MIGRATOR_SERVICE_H_
diff --git a/components/password_manager/sync/browser/password_manager_setting_migrator_service_unittest.cc b/components/password_manager/sync/browser/password_manager_setting_migrator_service_unittest.cc new file mode 100644 index 0000000..d5f4e12 --- /dev/null +++ b/components/password_manager/sync/browser/password_manager_setting_migrator_service_unittest.cc
@@ -0,0 +1,469 @@ +// Copyright (c) 2015 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 "base/json/json_writer.h" +#include "base/metrics/field_trial.h" +#include "base/prefs/pref_service.h" +#include "base/test/histogram_tester.h" +#include "base/values.h" +#include "components/password_manager/core/browser/password_manager.h" +#include "components/password_manager/core/common/password_manager_pref_names.h" +#include "components/password_manager/sync/browser/password_manager_setting_migrator_service.h" +#include "components/pref_registry/testing_pref_service_syncable.h" +#include "components/sync_driver/fake_sync_service.h" +#include "components/syncable_prefs/pref_model_associator_client.h" +#include "components/syncable_prefs/pref_service_mock_factory.h" +#include "components/syncable_prefs/pref_service_syncable.h" +#include "sync/api/fake_sync_change_processor.h" +#include "sync/api/sync_error_factory.h" +#include "sync/api/sync_error_factory_mock.h" +#include "sync/internal_api/public/attachments/attachment_service_proxy_for_test.h" +#include "sync/protocol/sync.pb.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +const char kFieldTrialName[] = "PasswordManagerSettingsMigration"; +const char kEnabledGroupName[] = "Enable"; +const char kDisabledGroupName[] = "Disable"; + +const char kInitialValuesHistogramName[] = + "PasswordManager.SettingsReconciliation.InitialValues"; + +const char kInitialAndFinalValuesHistogramName[] = + "PasswordManager.SettingsReconciliation.InitialAndFinalValues"; + +enum BooleanPrefState { + OFF, + ON, + EMPTY, // datatype bucket is empty +}; + +// Enum used for histogram tracking of the initial values for the legacy and new +// preferences. +enum PasswordManagerPreferencesInitialValues { + N0L0, + N0L1, + N1L0, + N1L1, + NUM_INITIAL_VALUES, +}; + +// Enum used for histogram tracking of the combined initial values and final +// values for the legacy and new preferences. +enum PasswordManagerPreferencesInitialAndFinalValues { + I00F00, + I00F01, + I00F10, + I00F11, + I01F00, + I01F01, + I01F10, + I01F11, + I10F00, + I10F01, + I10F10, + I10F11, + I11F00, + I11F01, + I11F10, + I11F11, + NUM_INITIAL_AND_FINAL_VALUES, +}; + +syncer::SyncData CreatePrefSyncData(const std::string& name, bool value) { + base::FundamentalValue bool_value(value); + std::string serialized; + base::JSONWriter::Write(bool_value, &serialized); + sync_pb::EntitySpecifics specifics; + sync_pb::PreferenceSpecifics* pref = nullptr; + if (name == password_manager::prefs::kPasswordManagerSavingEnabled) + pref = specifics.mutable_preference(); + else if (name == password_manager::prefs::kCredentialsEnableService) + pref = specifics.mutable_priority_preference()->mutable_preference(); + else + NOTREACHED() << "Wrong preference name: " << name; + pref->set_name(name); + pref->set_value(serialized); + return syncer::SyncData::CreateRemoteData( + 1, specifics, base::Time(), syncer::AttachmentIdList(), + syncer::AttachmentServiceProxyForTest::Create()); +} + +// Emulates start of the syncing for the specific sync type. If |name| is +// kPasswordManagerSavingEnabled preference, then it's PREFERENCE data type. +// If |name| is kCredentialsEnableService pref, then it's PRIORITY_PREFERENCE +// data type. +void StartSyncingPref(syncable_prefs::PrefServiceSyncable* prefs, + const std::string& name, + BooleanPrefState pref_state_in_sync) { + syncer::SyncDataList sync_data_list; + if (pref_state_in_sync == EMPTY) { + sync_data_list = syncer::SyncDataList(); + } else { + sync_data_list.push_back( + CreatePrefSyncData(name, pref_state_in_sync == ON)); + } + + syncer::ModelType type = syncer::UNSPECIFIED; + if (name == password_manager::prefs::kPasswordManagerSavingEnabled) + type = syncer::PREFERENCES; + else if (name == password_manager::prefs::kCredentialsEnableService) + type = syncer::PRIORITY_PREFERENCES; + ASSERT_NE(syncer::UNSPECIFIED, type) << "Wrong preference name: " << name; + syncer::SyncableService* sync = prefs->GetSyncableService(type); + sync->MergeDataAndStartSyncing( + type, sync_data_list, scoped_ptr<syncer::SyncChangeProcessor>( + new syncer::FakeSyncChangeProcessor), + scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock)); +} + +class SyncServiceMock : public sync_driver::FakeSyncService { + public: + bool HasSyncSetupCompleted() const override { return true; } + + bool CanSyncStart() const override { return can_sync_start_; } + + void SetCanSyncStart(bool can_sync_start) { + can_sync_start_ = can_sync_start; + } + + private: + bool can_sync_start_ = true; +}; + +class TestPrefModelAssociatorClient + : public syncable_prefs::PrefModelAssociatorClient { + public: + TestPrefModelAssociatorClient() {} + ~TestPrefModelAssociatorClient() override {} + + // PrefModelAssociatorClient implementation. + bool IsMergeableListPreference(const std::string& pref_name) const override { + return false; + } + + bool IsMergeableDictionaryPreference( + const std::string& pref_name) const override { + return false; + } + + bool IsMigratedPreference(const std::string& new_pref_name, + std::string* old_pref_name) const override { + return false; + } + + bool IsOldMigratedPreference(const std::string& old_pref_name, + std::string* new_pref_name) const override { + return false; + } + + private: + DISALLOW_COPY_AND_ASSIGN(TestPrefModelAssociatorClient); +}; + +} // namespace + +namespace password_manager { + +class PasswordManagerSettingMigratorServiceTest : public testing::Test { + protected: + PasswordManagerSettingMigratorServiceTest() {} + ~PasswordManagerSettingMigratorServiceTest() override {} + + void SetUp() override { + SetupPreferenceMigrationEnvironment(); + EnforcePasswordManagerSettingMigrationExperiment(kEnabledGroupName); + } + + void SetupLocalPrefState(const std::string& name, BooleanPrefState state) { + if (state == ON) + prefs()->SetBoolean(name, true); + else if (state == OFF) + prefs()->SetBoolean(name, false); + else if (state == EMPTY) + ASSERT_TRUE(prefs()->FindPreference(name)->IsDefaultValue()); + } + + syncable_prefs::PrefServiceSyncable* prefs() { return pref_service_.get(); } + + void SetupPreferenceMigrationEnvironment() { + syncable_prefs::PrefServiceMockFactory factory; + factory.SetPrefModelAssociatorClient(&client_); + scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry( + new user_prefs::PrefRegistrySyncable); + password_manager::PasswordManager::RegisterProfilePrefs( + pref_registry.get()); + scoped_ptr<syncable_prefs::PrefServiceSyncable> pref_service_syncable = + factory.CreateSyncable(pref_registry.get()); + migration_service_.reset( + new PasswordManagerSettingMigratorService(pref_service_syncable.get())); + pref_service_.reset(pref_service_syncable.release()); + } + + void ExpectValuesForBothPrefValues(bool new_pref_value, bool old_pref_value) { + EXPECT_EQ(new_pref_value, + prefs()->GetBoolean(prefs::kCredentialsEnableService)); + EXPECT_EQ(old_pref_value, + prefs()->GetBoolean(prefs::kPasswordManagerSavingEnabled)); + } + + SyncServiceMock* profile_sync_service() { return &sync_service_; } + + void NotifyProfileAdded() { + migration_service_->InitializeMigration(&sync_service_); + } + + void EnforcePasswordManagerSettingMigrationExperiment(const char* name) { + // The existing instance of FieldTrialList should be deleted before creating + // new one, so reset() is called in order to do so. + field_trial_list_.reset(); + field_trial_list_.reset(new base::FieldTrialList(nullptr)); + base::FieldTrialList::CreateFieldTrial(kFieldTrialName, name); + } + + private: + scoped_ptr<base::FieldTrialList> field_trial_list_; + TestPrefModelAssociatorClient client_; + SyncServiceMock sync_service_; + scoped_ptr<syncable_prefs::PrefServiceSyncable> pref_service_; + scoped_ptr<PasswordManagerSettingMigratorService> migration_service_; + + DISALLOW_COPY_AND_ASSIGN(PasswordManagerSettingMigratorServiceTest); +}; + +TEST_F(PasswordManagerSettingMigratorServiceTest, TestMigrationOnLocalChanges) { + const struct { + const char* group; + const char* pref_name; + bool pref_value; + bool expected_new_pref_value; + bool expected_old_pref_value; + } kTestingTable[] = { + {kEnabledGroupName, prefs::kPasswordManagerSavingEnabled, true, true, + true}, + {kEnabledGroupName, prefs::kPasswordManagerSavingEnabled, false, false, + false}, + {kEnabledGroupName, prefs::kCredentialsEnableService, true, true, true}, + {kEnabledGroupName, prefs::kCredentialsEnableService, false, false, + false}, + {kDisabledGroupName, prefs::kPasswordManagerSavingEnabled, false, true, + false}, + {kDisabledGroupName, prefs::kCredentialsEnableService, false, false, + true}}; + + for (const auto& test_case : kTestingTable) { + SetupPreferenceMigrationEnvironment(); + EnforcePasswordManagerSettingMigrationExperiment(test_case.group); + prefs()->SetBoolean(prefs::kCredentialsEnableService, + !test_case.pref_value); + prefs()->SetBoolean(prefs::kPasswordManagerSavingEnabled, + !test_case.pref_value); + NotifyProfileAdded(); + base::HistogramTester tester; + prefs()->SetBoolean(test_case.pref_name, test_case.pref_value); + ExpectValuesForBothPrefValues(test_case.expected_new_pref_value, + test_case.expected_old_pref_value); + EXPECT_THAT(tester.GetAllSamples(kInitialValuesHistogramName), + testing::IsEmpty()); + } +} + +TEST_F(PasswordManagerSettingMigratorServiceTest, + ReconcileWhenWhenBothPrefsTypesArrivesFromSync) { + const struct { + BooleanPrefState new_pref_local_value; + BooleanPrefState old_pref_local_value; + BooleanPrefState new_pref_sync_value; + BooleanPrefState old_pref_sync_value; + bool result_value; + PasswordManagerPreferencesInitialValues histogram_initial_value; + PasswordManagerPreferencesInitialAndFinalValues histogram_initial_and_final; + } kTestingTable[] = { +#if defined(OS_ANDROID) + {ON, OFF, ON, EMPTY, false, N1L0, I10F00}, + {ON, OFF, OFF, EMPTY, false, N1L0, I10F00}, + {ON, OFF, EMPTY, EMPTY, false, N1L0, I10F00}, + {ON, ON, ON, EMPTY, true, N1L1, I11F11}, + {ON, ON, OFF, EMPTY, false, N1L1, I11F00}, + {OFF, OFF, ON, EMPTY, true, N0L0, I00F11}, + {OFF, OFF, OFF, EMPTY, false, N0L0, I00F00}, + {OFF, ON, ON, EMPTY, true, N0L1, I01F11}, + {OFF, ON, OFF, EMPTY, false, N0L1, I01F00}, + {OFF, ON, EMPTY, EMPTY, false, N0L1, I01F00}, +#else + {EMPTY, EMPTY, EMPTY, EMPTY, true, N1L1, I11F11}, + {EMPTY, EMPTY, EMPTY, OFF, false, N1L1, I11F00}, + {EMPTY, EMPTY, EMPTY, ON, true, N1L1, I11F11}, + {EMPTY, EMPTY, OFF, EMPTY, false, N1L1, I11F00}, + {EMPTY, EMPTY, ON, EMPTY, true, N1L1, I11F11}, + {OFF, OFF, EMPTY, EMPTY, false, N0L0, I00F00}, + {OFF, OFF, OFF, OFF, false, N0L0, I00F00}, + {OFF, OFF, OFF, ON, true, N0L0, I00F11}, + {OFF, OFF, ON, OFF, true, N0L0, I00F11}, + {OFF, ON, OFF, ON, false, N0L1, I01F00}, + {OFF, ON, ON, OFF, false, N0L1, I01F00}, + {OFF, ON, ON, ON, true, N0L1, I01F11}, + {ON, OFF, EMPTY, EMPTY, false, N1L0, I10F00}, + {ON, OFF, OFF, ON, false, N1L0, I10F00}, + {ON, OFF, ON, OFF, false, N1L0, I10F00}, + {ON, OFF, ON, ON, true, N1L0, I10F11}, + {ON, ON, EMPTY, OFF, false, N1L1, I11F00}, + {ON, ON, EMPTY, ON, true, N1L1, I11F11}, + {ON, ON, OFF, EMPTY, false, N1L1, I11F00}, + {ON, ON, OFF, OFF, false, N1L1, I11F00}, + {ON, ON, OFF, ON, false, N1L1, I11F00}, + {ON, ON, ON, EMPTY, true, N1L1, I11F11}, + {ON, ON, ON, OFF, false, N1L1, I11F00}, + {ON, ON, ON, ON, true, N1L1, I11F11}, +#endif + }; + + for (const auto& test_case : kTestingTable) { + SetupPreferenceMigrationEnvironment(); + EnforcePasswordManagerSettingMigrationExperiment(kEnabledGroupName); + SCOPED_TRACE(testing::Message("Local data = ") + << test_case.new_pref_local_value << " " + << test_case.old_pref_local_value); + SCOPED_TRACE(testing::Message("Sync data = ") + << test_case.new_pref_sync_value << " " + << test_case.old_pref_sync_value); + SetupLocalPrefState(prefs::kPasswordManagerSavingEnabled, + test_case.old_pref_local_value); + SetupLocalPrefState(prefs::kCredentialsEnableService, + test_case.new_pref_local_value); + base::HistogramTester tester; + NotifyProfileAdded(); + StartSyncingPref(prefs(), prefs::kCredentialsEnableService, + test_case.new_pref_sync_value); +#if !defined(OS_ANDROID) + StartSyncingPref(prefs(), prefs::kPasswordManagerSavingEnabled, + test_case.old_pref_sync_value); +#endif + ExpectValuesForBothPrefValues(test_case.result_value, + test_case.result_value); + EXPECT_THAT(tester.GetAllSamples(kInitialValuesHistogramName), + testing::ElementsAre( + base::Bucket(test_case.histogram_initial_value, 1))); + EXPECT_THAT(tester.GetAllSamples(kInitialAndFinalValuesHistogramName), + testing::ElementsAre( + base::Bucket(test_case.histogram_initial_and_final, 1))); + } +} + +TEST_F(PasswordManagerSettingMigratorServiceTest, + DoNotReconcileWhenWhenBothPrefsTypesArrivesFromSync) { + const struct { + BooleanPrefState new_pref_local_value; + BooleanPrefState old_pref_local_value; + BooleanPrefState new_pref_sync_value; + BooleanPrefState old_pref_sync_value; + bool result_new_pref_value; + bool result_old_pref_value; + PasswordManagerPreferencesInitialValues histogram_initial_value; + } kTestingTable[] = { +#if defined(OS_ANDROID) + {ON, OFF, ON, EMPTY, true, false, N1L0}, + {ON, OFF, OFF, EMPTY, false, false, N1L0}, + {ON, OFF, EMPTY, EMPTY, true, false, N1L0}, + {ON, ON, ON, EMPTY, true, true, N1L1}, + {ON, ON, OFF, EMPTY, false, true, N1L1}, + {OFF, OFF, ON, EMPTY, true, false, N0L0}, + {OFF, OFF, OFF, EMPTY, false, false, N0L0}, + {OFF, ON, ON, EMPTY, true, true, N0L1}, + {OFF, ON, OFF, EMPTY, false, true, N0L1}, + {OFF, ON, EMPTY, EMPTY, false, true, N0L1}, +#else + {OFF, OFF, OFF, ON, false, true, N0L0}, + {OFF, OFF, ON, OFF, true, false, N0L0}, + {OFF, OFF, ON, ON, true, true, N0L0}, + {OFF, ON, EMPTY, OFF, false, false, N0L1}, + {OFF, ON, EMPTY, ON, false, true, N0L1}, + {OFF, ON, OFF, EMPTY, false, true, N0L1}, + {OFF, ON, OFF, OFF, false, false, N0L1}, + {OFF, ON, OFF, ON, false, true, N0L1}, + {OFF, ON, ON, EMPTY, true, true, N0L1}, + {OFF, ON, ON, OFF, true, false, N0L1}, + {OFF, ON, ON, ON, true, true, N0L1}, + {ON, OFF, OFF, ON, false, true, N1L0}, + {ON, OFF, ON, OFF, true, false, N1L0}, + {ON, OFF, ON, ON, true, true, N1L0}, + {ON, ON, EMPTY, OFF, true, false, N1L1}, + {ON, ON, EMPTY, ON, true, true, N1L1}, + {ON, ON, OFF, EMPTY, false, true, N1L1}, + {ON, ON, OFF, OFF, false, false, N1L1}, + {ON, ON, OFF, ON, false, true, N1L1}, + {ON, ON, ON, EMPTY, true, true, N1L1}, + {ON, ON, ON, OFF, true, false, N1L1}, + {ON, ON, ON, ON, true, true, N1L1}, +#endif + }; + + for (const auto& test_case : kTestingTable) { + SetupPreferenceMigrationEnvironment(); + EnforcePasswordManagerSettingMigrationExperiment(kDisabledGroupName); + SCOPED_TRACE(testing::Message("Local data = ") + << test_case.new_pref_local_value << " " + << test_case.old_pref_local_value); + SCOPED_TRACE(testing::Message("Sync data = ") + << test_case.new_pref_sync_value << " " + << test_case.old_pref_sync_value); + SetupLocalPrefState(prefs::kPasswordManagerSavingEnabled, + test_case.old_pref_local_value); + SetupLocalPrefState(prefs::kCredentialsEnableService, + test_case.new_pref_local_value); + base::HistogramTester tester; + NotifyProfileAdded(); + StartSyncingPref(prefs(), prefs::kCredentialsEnableService, + test_case.new_pref_sync_value); +#if !defined(OS_ANDROID) + StartSyncingPref(prefs(), prefs::kPasswordManagerSavingEnabled, + test_case.old_pref_sync_value); +#endif + ExpectValuesForBothPrefValues(test_case.result_new_pref_value, + test_case.result_old_pref_value); + EXPECT_THAT(tester.GetAllSamples(kInitialValuesHistogramName), + testing::ElementsAre( + base::Bucket(test_case.histogram_initial_value, 1))); + EXPECT_THAT(tester.GetAllSamples(kInitialAndFinalValuesHistogramName), + testing::IsEmpty()); + } +} + +TEST_F(PasswordManagerSettingMigratorServiceTest, + ReconcileWhenSyncIsNotExpectedPasswordManagerEnabledOff) { + prefs()->SetBoolean(prefs::kPasswordManagerSavingEnabled, false); + profile_sync_service()->SetCanSyncStart(false); + base::HistogramTester tester; + NotifyProfileAdded(); + ExpectValuesForBothPrefValues(false, false); + EXPECT_THAT(tester.GetAllSamples(kInitialAndFinalValuesHistogramName), + testing::ElementsAre(base::Bucket(I10F00, 1))); +} + +TEST_F(PasswordManagerSettingMigratorServiceTest, + ReconcileWhenSyncIsNotExpectedPasswordManagerEnabledOn) { + prefs()->SetBoolean(prefs::kPasswordManagerSavingEnabled, true); + ASSERT_EQ(prefs()->GetBoolean(prefs::kCredentialsEnableService), true); + profile_sync_service()->SetCanSyncStart(false); + base::HistogramTester tester; + NotifyProfileAdded(); + ExpectValuesForBothPrefValues(true, true); + EXPECT_THAT(tester.GetAllSamples(kInitialAndFinalValuesHistogramName), + testing::ElementsAre(base::Bucket(I11F11, 1))); +} + +TEST_F(PasswordManagerSettingMigratorServiceTest, + ReconcileWhenSyncIsNotExpectedDefaultValuesForPrefs) { + ASSERT_EQ(prefs()->GetBoolean(prefs::kCredentialsEnableService), true); + profile_sync_service()->SetCanSyncStart(false); + base::HistogramTester tester; + NotifyProfileAdded(); + ExpectValuesForBothPrefValues(true, true); + EXPECT_THAT(tester.GetAllSamples(kInitialAndFinalValuesHistogramName), + testing::ElementsAre(base::Bucket(I11F11, 1))); +} + +} // namespace password_manager
diff --git a/components/pdf_viewer/pdf_viewer.cc b/components/pdf_viewer/pdf_viewer.cc index 0934fab..f3ba929 100644 --- a/components/pdf_viewer/pdf_viewer.cc +++ b/components/pdf_viewer/pdf_viewer.cc
@@ -75,7 +75,7 @@ } void Init(mojo::Shell* shell) { - surface_ = view_->RequestSurface(); + surface_ = view_->RequestSurface(mus::mojom::SURFACE_TYPE_DEFAULT); surface_->BindToThread(); mojo::ServiceProviderPtr gpu_service_provider; @@ -159,7 +159,7 @@ GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM]; glGenMailboxCHROMIUM(mailbox); glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox); - GLuint sync_point = glInsertSyncPointCHROMIUM(); + gpu::SyncToken sync_token(glInsertSyncPointCHROMIUM()); mus::mojom::TransferableResourcePtr resource = mus::mojom::TransferableResource::New(); @@ -174,7 +174,8 @@ for (int i = 0; i < GL_MAILBOX_SIZE_CHROMIUM; ++i) mailbox_holder->mailbox->name.push_back(mailbox[i]); mailbox_holder->texture_target = GL_TEXTURE_2D; - mailbox_holder->sync_point = sync_point; + mailbox_holder->sync_token = + mus::mojom::SyncToken::From<gpu::SyncToken>(sync_token); resource->mailbox_holder = mailbox_holder.Pass(); resource->is_repeated = false; resource->is_software = false; @@ -285,7 +286,8 @@ for (size_t i = 0; i < resources.size(); ++i) { mus::mojom::ReturnedResourcePtr resource = resources[i].Pass(); DCHECK_EQ(1, resource->count); - glWaitSyncPointCHROMIUM(resource->sync_point); + glWaitSyncTokenCHROMIUM( + resource->sync_token.To<gpu::SyncToken>().GetConstData()); uint32_t texture_id = resource_to_texture_id_map_[resource->id]; DCHECK_NE(0u, texture_id); resource_to_texture_id_map_.erase(resource->id);
diff --git a/components/policy/android/BUILD.gn b/components/policy/android/BUILD.gn index a3ef6ba..53bc165 100644 --- a/components/policy/android/BUILD.gn +++ b/components/policy/android/BUILD.gn
@@ -28,3 +28,14 @@ sources = _jni_sources jni_package = "policy" } + +junit_binary("components_policy_junit_tests") { + java_files = [ + "junit/src/org/chromium/policy/AbstractAppRestrictionsProviderTest.java", + "junit/src/org/chromium/policy/CombinedPolicyProviderTest.java", + ] + deps = [ + "//base:base_java", + ":policy_java", + ] +}
diff --git a/components/resource_provider/file_utils.cc b/components/resource_provider/file_utils.cc index 5b8eac5..54bdd905 100644 --- a/components/resource_provider/file_utils.cc +++ b/components/resource_provider/file_utils.cc
@@ -28,12 +28,19 @@ } // namespace base::FilePath GetPathForApplicationUrl(const GURL& application_url) { - if (application_url.scheme() != "mojo") + if (application_url.scheme() != "mojo" && application_url.scheme() != "exe") return base::FilePath(); std::string path = application_url.path(); base::TrimString(path, "/", &path); + // TODO(beng): I'm adding this because there is a collision between the + // executable name in the exe dir and the resource package dir on + // non-Windows systems. Arbitrary exes should probably load their + // resources themselves rather than use resource provider. + if (application_url.SchemeIs("exe")) + path += "_res"; + if (!IsPathNameValid(path)) return base::FilePath();
diff --git a/components/resource_provider/public/cpp/BUILD.gn b/components/resource_provider/public/cpp/BUILD.gn index ad13d1f..8cfa313 100644 --- a/components/resource_provider/public/cpp/BUILD.gn +++ b/components/resource_provider/public/cpp/BUILD.gn
@@ -14,7 +14,6 @@ "//mojo/application/public/cpp", "//mojo/application/public/interfaces", "//mojo/common", - "//mojo/platform_handle", "//third_party/mojo/src/mojo/public/cpp/bindings", "//third_party/mojo/src/mojo/public/cpp/system", ]
diff --git a/components/safe_browsing_db.gypi b/components/safe_browsing_db.gypi index c5cec12c..a874bfa 100644 --- a/components/safe_browsing_db.gypi +++ b/components/safe_browsing_db.gypi
@@ -16,8 +16,8 @@ # Note: sources list duplicated in GN build. 'safe_browsing_db/prefix_set.h', 'safe_browsing_db/prefix_set.cc', - 'safe_browsing_db/safe_browsing_db_util.h', - 'safe_browsing_db/safe_browsing_db_util.cc', + 'safe_browsing_db/util.h', + 'safe_browsing_db/util.cc', ], 'include_dirs': [ '..',
diff --git a/components/safe_browsing_db/BUILD.gn b/components/safe_browsing_db/BUILD.gn index 4147fe9..bc82f79 100644 --- a/components/safe_browsing_db/BUILD.gn +++ b/components/safe_browsing_db/BUILD.gn
@@ -5,7 +5,7 @@ group("safe_browsing_db") { deps = [ ":prefix_set", - ":safe_browsing_db_util", + ":util", ] } @@ -19,10 +19,10 @@ ] } -source_set("safe_browsing_db_util") { +source_set("util") { sources = [ - "safe_browsing_db_util.cc", - "safe_browsing_db_util.h", + "util.cc", + "util.h", ] deps = [ "//base", @@ -34,11 +34,11 @@ testonly = true sources = [ "prefix_set_unittest.cc", - "safe_browsing_db_util_unittest.cc", + "util_unittest.cc", ] deps = [ ":prefix_set", - ":safe_browsing_db_util", + ":util", "//base", "//testing/gtest", ]
diff --git a/components/safe_browsing_db/DEPS b/components/safe_browsing_db/DEPS index 4ef4138e4..12af900 100644 --- a/components/safe_browsing_db/DEPS +++ b/components/safe_browsing_db/DEPS
@@ -1,3 +1,4 @@ include_rules = [ "+crypto", + "+net", ]
diff --git a/components/safe_browsing_db/prefix_set.h b/components/safe_browsing_db/prefix_set.h index 433da66..5517105c 100644 --- a/components/safe_browsing_db/prefix_set.h +++ b/components/safe_browsing_db/prefix_set.h
@@ -55,7 +55,7 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" -#include "components/safe_browsing_db/safe_browsing_db_util.h" +#include "components/safe_browsing_db/util.h" namespace base { class FilePath;
diff --git a/components/safe_browsing_db/prefix_set_unittest.cc b/components/safe_browsing_db/prefix_set_unittest.cc index b980e71..08f639a9 100644 --- a/components/safe_browsing_db/prefix_set_unittest.cc +++ b/components/safe_browsing_db/prefix_set_unittest.cc
@@ -19,7 +19,7 @@ #include "base/rand_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" -#include "components/safe_browsing_db/safe_browsing_db_util.h" +#include "components/safe_browsing_db/util.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h"
diff --git a/components/safe_browsing_db/util.cc b/components/safe_browsing_db/util.cc new file mode 100644 index 0000000..8d95b9c --- /dev/null +++ b/components/safe_browsing_db/util.cc
@@ -0,0 +1,371 @@ +// Copyright (c) 2015 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_db/util.h" + +#include "base/strings/string_util.h" +#include "crypto/sha2.h" +#include "net/base/escape.h" +#include "url/gurl.h" +#include "url/url_util.h" + +// Utility functions ----------------------------------------------------------- + +namespace { +bool IsKnownList(const std::string& name) { + for (size_t i = 0; i < arraysize(safe_browsing::kAllLists); ++i) { + if (!strcmp(safe_browsing::kAllLists[i], name.c_str())) { + return true; + } + } + return false; +} +} // namespace + + +// SBCachedFullHashResult ------------------------------------------------------ + +SBCachedFullHashResult::SBCachedFullHashResult() {} + +SBCachedFullHashResult::SBCachedFullHashResult( + const base::Time& in_expire_after) + : expire_after(in_expire_after) {} + +SBCachedFullHashResult::~SBCachedFullHashResult() {} + + +namespace safe_browsing { + +// Listnames that browser can process. +const char kMalwareList[] = "goog-malware-shavar"; +const char kPhishingList[] = "goog-phish-shavar"; +const char kBinUrlList[] = "goog-badbinurl-shavar"; +const char kCsdWhiteList[] = "goog-csdwhite-sha256"; +const char kDownloadWhiteList[] = "goog-downloadwhite-digest256"; +const char kExtensionBlacklist[] = "goog-badcrxids-digestvar"; +const char kIPBlacklist[] = "goog-badip-digest256"; +const char kUnwantedUrlList[] = "goog-unwanted-shavar"; +const char kInclusionWhitelist[] = "goog-csdinclusionwhite-sha256"; + +const char* kAllLists[9] = { + kMalwareList, + kPhishingList, + kBinUrlList, + kCsdWhiteList, + kDownloadWhiteList, + kExtensionBlacklist, + kIPBlacklist, + kUnwantedUrlList, + kInclusionWhitelist, +}; + +ListType GetListId(const base::StringPiece& name) { + ListType id; + if (name == kMalwareList) { + id = MALWARE; + } else if (name == kPhishingList) { + id = PHISH; + } else if (name == kBinUrlList) { + id = BINURL; + } else if (name == kCsdWhiteList) { + id = CSDWHITELIST; + } else if (name == kDownloadWhiteList) { + id = DOWNLOADWHITELIST; + } else if (name == kExtensionBlacklist) { + id = EXTENSIONBLACKLIST; + } else if (name == kIPBlacklist) { + id = IPBLACKLIST; + } else if (name == kUnwantedUrlList) { + id = UNWANTEDURL; + } else if (name == kInclusionWhitelist) { + id = INCLUSIONWHITELIST; + } else { + id = INVALID; + } + return id; +} + +bool GetListName(ListType list_id, std::string* list) { + switch (list_id) { + case MALWARE: + *list = kMalwareList; + break; + case PHISH: + *list = kPhishingList; + break; + case BINURL: + *list = kBinUrlList; + break; + case CSDWHITELIST: + *list = kCsdWhiteList; + break; + case DOWNLOADWHITELIST: + *list = kDownloadWhiteList; + break; + case EXTENSIONBLACKLIST: + *list = kExtensionBlacklist; + break; + case IPBLACKLIST: + *list = kIPBlacklist; + break; + case UNWANTEDURL: + *list = kUnwantedUrlList; + break; + case INCLUSIONWHITELIST: + *list = kInclusionWhitelist; + break; + default: + return false; + } + DCHECK(IsKnownList(*list)); + return true; +} + + +SBFullHash SBFullHashForString(const base::StringPiece& str) { + SBFullHash h; + crypto::SHA256HashString(str, &h.full_hash, sizeof(h.full_hash)); + return h; +} + +SBFullHash StringToSBFullHash(const std::string& hash_in) { + DCHECK_EQ(crypto::kSHA256Length, hash_in.size()); + SBFullHash hash_out; + memcpy(hash_out.full_hash, hash_in.data(), crypto::kSHA256Length); + return hash_out; +} + +std::string SBFullHashToString(const SBFullHash& hash) { + DCHECK_EQ(crypto::kSHA256Length, sizeof(hash.full_hash)); + return std::string(hash.full_hash, sizeof(hash.full_hash)); +} + + +std::string Unescape(const std::string& url) { + std::string unescaped_str(url); + std::string old_unescaped_str; + const int kMaxLoopIterations = 1024; + int loop_var = 0; + do { + old_unescaped_str = unescaped_str; + unescaped_str = net::UnescapeURLComponent( + old_unescaped_str, net::UnescapeRule::SPOOFING_AND_CONTROL_CHARS | + net::UnescapeRule::SPACES | + net::UnescapeRule::URL_SPECIAL_CHARS); + } while (unescaped_str != old_unescaped_str && ++loop_var <= + kMaxLoopIterations); + + return unescaped_str; +} + +std::string Escape(const std::string& url) { + std::string escaped_str; + const char* kHexString = "0123456789ABCDEF"; + for (size_t i = 0; i < url.length(); i++) { + unsigned char c = static_cast<unsigned char>(url[i]); + if (c <= ' ' || c > '~' || c == '#' || c == '%') { + escaped_str.push_back('%'); + escaped_str.push_back(kHexString[c >> 4]); + escaped_str.push_back(kHexString[c & 0xf]); + } else { + escaped_str.push_back(c); + } + } + + return escaped_str; +} + +std::string RemoveConsecutiveChars(const std::string& str, const char c) { + std::string output(str); + std::string string_to_find; + std::string::size_type loc = 0; + string_to_find.append(2, c); + while ((loc = output.find(string_to_find, loc)) != std::string::npos) { + output.erase(loc, 1); + } + + return output; +} + +// Canonicalizes url as per Google Safe Browsing Specification. +// See section 6.1 in +// http://code.google.com/p/google-safe-browsing/wiki/Protocolv2Spec. +void CanonicalizeUrl(const GURL& url, + std::string* canonicalized_hostname, + std::string* canonicalized_path, + std::string* canonicalized_query) { + DCHECK(url.is_valid()); + + // We only canonicalize "normal" URLs. + if (!url.IsStandard()) + return; + + // Following canonicalization steps are excluded since url parsing takes care + // of those :- + // 1. Remove any tab (0x09), CR (0x0d), and LF (0x0a) chars from url. + // (Exclude escaped version of these chars). + // 2. Normalize hostname to 4 dot-seperated decimal values. + // 3. Lowercase hostname. + // 4. Resolve path sequences "/../" and "/./". + + // That leaves us with the following :- + // 1. Remove fragment in URL. + GURL url_without_fragment; + GURL::Replacements f_replacements; + f_replacements.ClearRef(); + f_replacements.ClearUsername(); + f_replacements.ClearPassword(); + url_without_fragment = url.ReplaceComponents(f_replacements); + + // 2. Do URL unescaping until no more hex encoded characters exist. + std::string url_unescaped_str(Unescape(url_without_fragment.spec())); + url::Parsed parsed; + url::ParseStandardURL(url_unescaped_str.data(), url_unescaped_str.length(), + &parsed); + + // 3. In hostname, remove all leading and trailing dots. + const std::string host = + (parsed.host.len > 0) + ? url_unescaped_str.substr(parsed.host.begin, parsed.host.len) + : std::string(); + std::string host_without_end_dots; + base::TrimString(host, ".", &host_without_end_dots); + + // 4. In hostname, replace consecutive dots with a single dot. + std::string host_without_consecutive_dots(RemoveConsecutiveChars( + host_without_end_dots, '.')); + + // 5. In path, replace runs of consecutive slashes with a single slash. + std::string path = + (parsed.path.len > 0) + ? url_unescaped_str.substr(parsed.path.begin, parsed.path.len) + : std::string(); + std::string path_without_consecutive_slash(RemoveConsecutiveChars(path, '/')); + + url::Replacements<char> hp_replacements; + hp_replacements.SetHost( + host_without_consecutive_dots.data(), + url::Component(0, host_without_consecutive_dots.length())); + hp_replacements.SetPath( + path_without_consecutive_slash.data(), + url::Component(0, path_without_consecutive_slash.length())); + + std::string url_unescaped_with_can_hostpath; + url::StdStringCanonOutput output(&url_unescaped_with_can_hostpath); + url::Parsed temp_parsed; + url::ReplaceComponents(url_unescaped_str.data(), + url_unescaped_str.length(), + parsed, + hp_replacements, + NULL, + &output, + &temp_parsed); + output.Complete(); + + // 6. Step needed to revert escaping done in url::ReplaceComponents. + url_unescaped_with_can_hostpath = Unescape(url_unescaped_with_can_hostpath); + + // 7. After performing all above steps, percent-escape all chars in url which + // are <= ASCII 32, >= 127, #, %. Escapes must be uppercase hex characters. + std::string escaped_canon_url_str(Escape(url_unescaped_with_can_hostpath)); + url::Parsed final_parsed; + url::ParseStandardURL(escaped_canon_url_str.data(), + escaped_canon_url_str.length(), + &final_parsed); + + if (canonicalized_hostname && final_parsed.host.len > 0) { + *canonicalized_hostname = + escaped_canon_url_str.substr(final_parsed.host.begin, + final_parsed.host.len); + } + if (canonicalized_path && final_parsed.path.len > 0) { + *canonicalized_path = escaped_canon_url_str.substr(final_parsed.path.begin, + final_parsed.path.len); + } + if (canonicalized_query && final_parsed.query.len > 0) { + *canonicalized_query = escaped_canon_url_str.substr( + final_parsed.query.begin, final_parsed.query.len); + } +} + +void GenerateHostsToCheck(const GURL& url, std::vector<std::string>* hosts) { + hosts->clear(); + + std::string canon_host; + CanonicalizeUrl(url, &canon_host, NULL, NULL); + + const std::string host = canon_host; // const sidesteps GCC bugs below! + if (host.empty()) + return; + + // Per the Safe Browsing Protocol v2 spec, we try the host, and also up to 4 + // hostnames formed by starting with the last 5 components and successively + // removing the leading component. The last component isn't examined alone, + // since it's the TLD or a subcomponent thereof. + // + // Note that we don't need to be clever about stopping at the "real" eTLD -- + // the data on the server side has been filtered to ensure it will not + // blacklist a whole TLD, and it's not significantly slower on our side to + // just check too much. + // + // Also note that because we have a simple blacklist, not some sort of complex + // whitelist-in-blacklist or vice versa, it doesn't matter what order we check + // these in. + const size_t kMaxHostsToCheck = 4; + bool skipped_last_component = false; + for (std::string::const_reverse_iterator i(host.rbegin()); + i != host.rend() && hosts->size() < kMaxHostsToCheck; ++i) { + if (*i == '.') { + if (skipped_last_component) + hosts->push_back(std::string(i.base(), host.end())); + else + skipped_last_component = true; + } + } + hosts->push_back(host); +} + +void GeneratePathsToCheck(const GURL& url, std::vector<std::string>* paths) { + paths->clear(); + + std::string canon_path; + std::string canon_query; + CanonicalizeUrl(url, NULL, &canon_path, &canon_query); + + const std::string path = canon_path; // const sidesteps GCC bugs below! + const std::string query = canon_query; + if (path.empty()) + return; + + // Per the Safe Browsing Protocol v2 spec, we try the exact path with/without + // the query parameters, and also up to 4 paths formed by starting at the root + // and adding more path components. + // + // As with the hosts above, it doesn't matter what order we check these in. + const size_t kMaxPathsToCheck = 4; + for (std::string::const_iterator i(path.begin()); + i != path.end() && paths->size() < kMaxPathsToCheck; ++i) { + if (*i == '/') + paths->push_back(std::string(path.begin(), i + 1)); + } + + if (!paths->empty() && paths->back() != path) + paths->push_back(path); + + if (!query.empty()) + paths->push_back(path + "?" + query); +} + +void GeneratePatternsToCheck(const GURL& url, std::vector<std::string>* urls) { + std::vector<std::string> hosts, paths; + GenerateHostsToCheck(url, &hosts); + GeneratePathsToCheck(url, &paths); + for (size_t h = 0; h < hosts.size(); ++h) { + for (size_t p = 0; p < paths.size(); ++p) { + urls->push_back(hosts[h] + paths[p]); + } + } +} + +} // namespace safe_browsing
diff --git a/components/safe_browsing_db/util.h b/components/safe_browsing_db/util.h new file mode 100644 index 0000000..666e081 --- /dev/null +++ b/components/safe_browsing_db/util.h
@@ -0,0 +1,167 @@ +// Copyright (c) 2015 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. +// +// Utilities for the SafeBrowsing DB code. + +#ifndef COMPONENTS_SAFE_BROWSING_DB_UTIL_H_ +#define COMPONENTS_SAFE_BROWSING_DB_UTIL_H_ + +#include <cstring> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/strings/string_piece.h" +#include "base/time/time.h" + + +class GURL; + +// Different types of threats that SafeBrowsing protects against. +enum SBThreatType { + // No threat at all. + SB_THREAT_TYPE_SAFE, + + // The URL is being used for phishing. + SB_THREAT_TYPE_URL_PHISHING, + + // The URL hosts malware. + SB_THREAT_TYPE_URL_MALWARE, + + // The URL hosts unwanted programs. + SB_THREAT_TYPE_URL_UNWANTED, + + // The download URL is malware. + SB_THREAT_TYPE_BINARY_MALWARE_URL, + + // Url detected by the client-side phishing model. Note that unlike the + // above values, this does not correspond to a downloaded list. + SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL, + + // The Chrome extension or app (given by its ID) is malware. + SB_THREAT_TYPE_EXTENSION, + + // Url detected by the client-side malware IP list. This IP list is part + // of the client side detection model. + SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL, +}; + + +// TODO(vakh): Move all these declarations under safe_browsing namespace. +// A truncated hash's type. +typedef uint32 SBPrefix; + +// A full hash. +union SBFullHash { + char full_hash[32]; + SBPrefix prefix; +}; + +// Used when we get a gethash response. +struct SBFullHashResult { + SBFullHash hash; + // TODO(shess): Refactor to allow ListType here. + int list_id; + std::string metadata; +}; + +// Caches individual response from GETHASH request. +struct SBCachedFullHashResult { + SBCachedFullHashResult(); + explicit SBCachedFullHashResult(const base::Time& in_expire_after); + ~SBCachedFullHashResult(); + + base::Time expire_after; + std::vector<SBFullHashResult> full_hashes; +}; + + +namespace safe_browsing { + +// SafeBrowsing list names. +extern const char kMalwareList[]; +extern const char kPhishingList[]; +// Binary Download list name. +extern const char kBinUrlList[]; +// SafeBrowsing client-side detection whitelist list name. +extern const char kCsdWhiteList[]; +// SafeBrowsing download whitelist list name. +extern const char kDownloadWhiteList[]; +// SafeBrowsing extension list name. +extern const char kExtensionBlacklist[]; +// SafeBrowsing csd malware IP blacklist name. +extern const char kIPBlacklist[]; +// SafeBrowsing unwanted URL list. +extern const char kUnwantedUrlList[]; +// SafeBrowsing off-domain inclusion whitelist list name. +extern const char kInclusionWhitelist[]; +// This array must contain all Safe Browsing lists. +extern const char* kAllLists[9]; + + +enum ListType { + INVALID = -1, + MALWARE = 0, + PHISH = 1, + BINURL = 2, + // Obsolete BINHASH = 3, + CSDWHITELIST = 4, + // SafeBrowsing lists are stored in pairs. Keep ListType 5 + // available for a potential second list that we would store in the + // csd-whitelist store file. + DOWNLOADWHITELIST = 6, + // See above comment. Leave 7 available. + EXTENSIONBLACKLIST = 8, + // See above comment. Leave 9 available. + // Obsolete SIDEEFFECTFREEWHITELIST = 10, + // See above comment. Leave 11 available. + IPBLACKLIST = 12, + // See above comment. Leave 13 available. + UNWANTEDURL = 14, + // See above comment. Leave 15 available. + INCLUSIONWHITELIST = 16, + // See above comment. Leave 17 available. +}; + + +inline bool SBFullHashEqual(const SBFullHash& a, const SBFullHash& b) { + return !memcmp(a.full_hash, b.full_hash, sizeof(a.full_hash)); +} + +inline bool SBFullHashLess(const SBFullHash& a, const SBFullHash& b) { + return memcmp(a.full_hash, b.full_hash, sizeof(a.full_hash)) < 0; +} + +// Generate full hash for the given string. +SBFullHash SBFullHashForString(const base::StringPiece& str); +SBFullHash StringToSBFullHash(const std::string& hash_in); +std::string SBFullHashToString(const SBFullHash& hash_out); + + +// Maps a list name to ListType. +ListType GetListId(const base::StringPiece& name); + +// Maps a ListId to list name. Return false if fails. +bool GetListName(ListType list_id, std::string* list); + +// Canonicalizes url as per Google Safe Browsing Specification. +// See section 6.1 in +// http://code.google.com/p/google-safe-browsing/wiki/Protocolv2Spec. +void CanonicalizeUrl(const GURL& url, std::string* canonicalized_hostname, + std::string* canonicalized_path, + std::string* canonicalized_query); + +// Given a URL, returns all the hosts we need to check. They are returned +// in order of size (i.e. b.c is first, then a.b.c). +void GenerateHostsToCheck(const GURL& url, std::vector<std::string>* hosts); + +// Given a URL, returns all the paths we need to check. +void GeneratePathsToCheck(const GURL& url, std::vector<std::string>* paths); + +// Given a URL, returns all the patterns we need to check. +void GeneratePatternsToCheck(const GURL& url, std::vector<std::string>* urls); + +} // namespace safe_browsing + +#endif // COMPONENTS_SAFE_BROWSING_DB_UTIL_H_
diff --git a/components/safe_browsing_db/util_unittest.cc b/components/safe_browsing_db/util_unittest.cc new file mode 100644 index 0000000..d29bd3f --- /dev/null +++ b/components/safe_browsing_db/util_unittest.cc
@@ -0,0 +1,339 @@ +// Copyright (c) 2015 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 <algorithm> + +#include "base/strings/stringprintf.h" +#include "components/safe_browsing_db/util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace { + +bool VectorContains(const std::vector<std::string>& data, + const std::string& str) { + return std::find(data.begin(), data.end(), str) != data.end(); +} + +// Tests that we generate the required host/path combinations for testing +// according to the Safe Browsing spec. +// See section 6.2 in +// http://code.google.com/p/google-safe-browsing/wiki/Protocolv2Spec. +TEST(SafeBrowsingDbUtilTest, UrlParsing) { + std::vector<std::string> hosts, paths; + + GURL url("http://a.b.c/1/2.html?param=1"); + safe_browsing::GenerateHostsToCheck(url, &hosts); + safe_browsing::GeneratePathsToCheck(url, &paths); + EXPECT_EQ(hosts.size(), static_cast<size_t>(2)); + EXPECT_EQ(paths.size(), static_cast<size_t>(4)); + EXPECT_EQ(hosts[0], "b.c"); + EXPECT_EQ(hosts[1], "a.b.c"); + + EXPECT_TRUE(VectorContains(paths, "/1/2.html?param=1")); + EXPECT_TRUE(VectorContains(paths, "/1/2.html")); + EXPECT_TRUE(VectorContains(paths, "/1/")); + EXPECT_TRUE(VectorContains(paths, "/")); + + url = GURL("http://a.b.c.d.e.f.g/1.html"); + safe_browsing::GenerateHostsToCheck(url, &hosts); + safe_browsing::GeneratePathsToCheck(url, &paths); + EXPECT_EQ(hosts.size(), static_cast<size_t>(5)); + EXPECT_EQ(paths.size(), static_cast<size_t>(2)); + EXPECT_EQ(hosts[0], "f.g"); + EXPECT_EQ(hosts[1], "e.f.g"); + EXPECT_EQ(hosts[2], "d.e.f.g"); + EXPECT_EQ(hosts[3], "c.d.e.f.g"); + EXPECT_EQ(hosts[4], "a.b.c.d.e.f.g"); + EXPECT_TRUE(VectorContains(paths, "/1.html")); + EXPECT_TRUE(VectorContains(paths, "/")); + + url = GURL("http://a.b/saw-cgi/eBayISAPI.dll/"); + safe_browsing::GeneratePathsToCheck(url, &paths); + EXPECT_EQ(paths.size(), static_cast<size_t>(3)); + EXPECT_TRUE(VectorContains(paths, "/saw-cgi/eBayISAPI.dll/")); + EXPECT_TRUE(VectorContains(paths, "/saw-cgi/")); + EXPECT_TRUE(VectorContains(paths, "/")); +} + +// Tests the url canonicalization according to the Safe Browsing spec. +// See section 6.1 in +// http://code.google.com/p/google-safe-browsing/wiki/Protocolv2Spec. +TEST(SafeBrowsingDbUtilTest, CanonicalizeUrl) { + struct { + const char* input_url; + const char* expected_canonicalized_hostname; + const char* expected_canonicalized_path; + const char* expected_canonicalized_query; + } tests[] = { + { + "http://host/%25%32%35", + "host", + "/%25", + "" + }, { + "http://host/%25%32%35%25%32%35", + "host", + "/%25%25", + "" + }, { + "http://host/%2525252525252525", + "host", + "/%25", + "" + }, { + "http://host/asdf%25%32%35asd", + "host", + "/asdf%25asd", + "" + }, { + "http://host/%%%25%32%35asd%%", + "host", + "/%25%25%25asd%25%25", + "" + }, { + "http://host/%%%25%32%35asd%%", + "host", + "/%25%25%25asd%25%25", + "" + }, { + "http://www.google.com/", + "www.google.com", + "/", + "" + }, { + "http://%31%36%38%2e%31%38%38%2e%39%39%2e%32%36/%2E%73%65%63%75%72%65/%77" + "%77%77%2E%65%62%61%79%2E%63%6F%6D/", + "168.188.99.26", + "/.secure/www.ebay.com/", + "" + }, { + "http://195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserd" + "ataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/", + "195.127.0.11", + "/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmv" + "alidateinfoswqpcmlx=hgplmcx/", + "" + }, { + "http://host.com/%257Ea%2521b%2540c%2523d%2524e%25f%255E00%252611%252A" + "22%252833%252944_55%252B", + "host.com", + "/~a!b@c%23d$e%25f^00&11*22(33)44_55+", + "" + }, { + "http://3279880203/blah", + "195.127.0.11", + "/blah", + "" + }, { + "http://www.google.com/blah/..", + "www.google.com", + "/", + "" + }, { + "http://www.google.com/blah#fraq", + "www.google.com", + "/blah", + "" + }, { + "http://www.GOOgle.com/", + "www.google.com", + "/", + "" + }, { + "http://www.google.com.../", + "www.google.com", + "/", + "" + }, { + "http://www.google.com/q?", + "www.google.com", + "/q", + "" + }, { + "http://www.google.com/q?r?", + "www.google.com", + "/q", + "r?" + }, { + "http://www.google.com/q?r?s", + "www.google.com", + "/q", + "r?s" + }, { + "http://evil.com/foo#bar#baz", + "evil.com", + "/foo", + "" + }, { + "http://evil.com/foo;", + "evil.com", + "/foo;", + "" + }, { + "http://evil.com/foo?bar;", + "evil.com", + "/foo", + "bar;" + }, { + "http://notrailingslash.com", + "notrailingslash.com", + "/", + "" + }, { + "http://www.gotaport.com:1234/", + "www.gotaport.com", + "/", + "" + }, { + " http://www.google.com/ ", + "www.google.com", + "/", + "" + }, { + "http:// leadingspace.com/", + "%20leadingspace.com", + "/", + "" + }, { + "http://%20leadingspace.com/", + "%20leadingspace.com", + "/", + "" + }, { + "https://www.securesite.com/", + "www.securesite.com", + "/", + "" + }, { + "http://host.com/ab%23cd", + "host.com", + "/ab%23cd", + "" + }, { + "http://host%3e.com//twoslashes?more//slashes", + "host>.com", + "/twoslashes", + "more//slashes" + }, { + "http://host.com/abc?val=xyz#anything", + "host.com", + "/abc", + "val=xyz" + }, { + "http://abc:def@host.com/xyz", + "host.com", + "/xyz", + "" + }, { + "http://host%3e.com/abc/%2e%2e%2fdef", + "host>.com", + "/def", + "" + }, { + "http://.......host...com.....//abc/////def%2F%2F%2Fxyz", + "host.com", + "/abc/def/xyz", + "" + }, { + "ftp://host.com/foo?bar", + "host.com", + "/foo", + "bar" + }, { + "data:text/html;charset=utf-8,%0D%0A", + "", + "", + "" + }, { + "javascript:alert()", + "", + "", + "" + }, { + "mailto:abc@example.com", + "", + "", + "" + }, + }; + for (size_t i = 0; i < arraysize(tests); ++i) { + SCOPED_TRACE(base::StringPrintf("Test: %s", tests[i].input_url)); + GURL url(tests[i].input_url); + + std::string canonicalized_hostname; + std::string canonicalized_path; + std::string canonicalized_query; + safe_browsing::CanonicalizeUrl(url, &canonicalized_hostname, + &canonicalized_path, &canonicalized_query); + + EXPECT_EQ(tests[i].expected_canonicalized_hostname, + canonicalized_hostname); + EXPECT_EQ(tests[i].expected_canonicalized_path, + canonicalized_path); + EXPECT_EQ(tests[i].expected_canonicalized_query, + canonicalized_query); + } +} + +TEST(SafeBrowsingDbUtilTest, ListIdListNameConversion) { + std::string list_name; + EXPECT_FALSE(safe_browsing::GetListName(safe_browsing::INVALID, + &list_name)); + EXPECT_TRUE(safe_browsing::GetListName(safe_browsing::MALWARE, + &list_name)); + EXPECT_EQ(list_name, std::string(safe_browsing::kMalwareList)); + EXPECT_EQ(safe_browsing::MALWARE, + safe_browsing::GetListId(list_name)); + + EXPECT_TRUE(safe_browsing::GetListName(safe_browsing::PHISH, + &list_name)); + EXPECT_EQ(list_name, std::string(safe_browsing::kPhishingList)); + EXPECT_EQ(safe_browsing::PHISH, + safe_browsing::GetListId(list_name)); + + EXPECT_TRUE(safe_browsing::GetListName(safe_browsing::BINURL, + &list_name)); + EXPECT_EQ(list_name, std::string(safe_browsing::kBinUrlList)); + EXPECT_EQ(safe_browsing::BINURL, + safe_browsing::GetListId(list_name)); +} + +// Since the ids are saved in file, we need to make sure they don't change. +// Since only the last bit of each id is saved in file together with +// chunkids, this checks only last bit. +TEST(SafeBrowsingDbUtilTest, ListIdVerification) { + EXPECT_EQ(0, safe_browsing::MALWARE % 2); + EXPECT_EQ(1, safe_browsing::PHISH % 2); + EXPECT_EQ(0, safe_browsing::BINURL %2); +} + +TEST(SafeBrowsingDbUtilTest, StringToSBFullHashAndSBFullHashToString) { + // 31 chars plus the last \0 as full_hash. + const std::string hash_in = "12345678902234567890323456789012"; + SBFullHash hash_out = safe_browsing::StringToSBFullHash(hash_in); + EXPECT_EQ(0x34333231U, hash_out.prefix); + EXPECT_EQ(0, memcmp(hash_in.data(), hash_out.full_hash, sizeof(SBFullHash))); + + std::string hash_final = safe_browsing::SBFullHashToString(hash_out); + EXPECT_EQ(hash_in, hash_final); +} + +TEST(SafeBrowsingDbUtilTest, FullHashOperators) { + const SBFullHash kHash1 = safe_browsing::SBFullHashForString("one"); + const SBFullHash kHash2 = safe_browsing::SBFullHashForString("two"); + + EXPECT_TRUE(safe_browsing::SBFullHashEqual(kHash1, kHash1)); + EXPECT_TRUE(safe_browsing::SBFullHashEqual(kHash2, kHash2)); + EXPECT_FALSE(safe_browsing::SBFullHashEqual(kHash1, kHash2)); + EXPECT_FALSE(safe_browsing::SBFullHashEqual(kHash2, kHash1)); + + EXPECT_FALSE(safe_browsing::SBFullHashLess(kHash1, kHash2)); + EXPECT_TRUE(safe_browsing::SBFullHashLess(kHash2, kHash1)); + + EXPECT_FALSE(safe_browsing::SBFullHashLess(kHash1, kHash1)); + EXPECT_FALSE(safe_browsing::SBFullHashLess(kHash2, kHash2)); +} + +} // namespace
diff --git a/components/scheduler/BUILD.gn b/components/scheduler/BUILD.gn index 4e43318..ea7bd88 100644 --- a/components/scheduler/BUILD.gn +++ b/components/scheduler/BUILD.gn
@@ -16,6 +16,7 @@ configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] deps = [ + ":common", "//base", "//cc:cc", "//third_party/WebKit/public:blink", @@ -27,12 +28,19 @@ ] } +# GYP version: components/scheduler.gypi:scheduler_common +source_set("common") { + sources = rebase_path(scheduler_gypi_values.scheduler_common_sources, + ".", + "//components/scheduler") +} + source_set("unit_tests") { testonly = true sources = [ - "base/nestable_task_runner_for_test.cc", - "base/nestable_task_runner_for_test.h", + "base/task_queue_manager_delegate_for_test.cc", + "base/task_queue_manager_delegate_for_test.h", "base/task_queue_manager_unittest.cc", "base/task_queue_selector_unittest.cc", "base/task_queue_sets_unittest.cc", @@ -42,9 +50,10 @@ "base/test_time_source.h", "child/idle_helper_unittest.cc", "child/scheduler_helper_unittest.cc", - "child/scheduler_task_runner_delegate_for_test.cc", - "child/scheduler_task_runner_delegate_for_test.h", - "child/scheduler_task_runner_delegate_impl_unittest.cc", + "child/scheduler_tqm_delegate_for_test.cc", + "child/scheduler_tqm_delegate_for_test.h", + "child/scheduler_tqm_delegate_impl_unittest.cc", + "child/virtual_time_tqm_delegate_unittest.cc", "child/webthread_impl_for_worker_scheduler_unittest.cc", "child/worker_scheduler_impl_unittest.cc", "renderer/deadline_task_runner_unittest.cc",
diff --git a/components/scheduler/DEPS b/components/scheduler/DEPS index 2d4a7445..a70514277 100644 --- a/components/scheduler/DEPS +++ b/components/scheduler/DEPS
@@ -1,3 +1,4 @@ include_rules = [ "-components/scheduler", + "+components/scheduler/common", ]
diff --git a/components/scheduler/base/lazy_now.cc b/components/scheduler/base/lazy_now.cc index 411e51b5..c80dd47 100644 --- a/components/scheduler/base/lazy_now.cc +++ b/components/scheduler/base/lazy_now.cc
@@ -4,6 +4,7 @@ #include "components/scheduler/base/lazy_now.h" +#include "base/time/tick_clock.h" #include "components/scheduler/base/task_queue_manager.h" namespace scheduler { @@ -11,7 +12,7 @@ base::TimeTicks LazyNow::Now() { if (now_.is_null()) - now_ = task_queue_manager_->Now(); + now_ = tick_clock_->NowTicks(); return now_; }
diff --git a/components/scheduler/base/lazy_now.h b/components/scheduler/base/lazy_now.h index db5f0594..fd52322 100644 --- a/components/scheduler/base/lazy_now.h +++ b/components/scheduler/base/lazy_now.h
@@ -7,27 +7,27 @@ #include "base/time/time.h" -namespace scheduler { -class TaskQueueManager; +namespace base { +class TickClock; +} +namespace scheduler { namespace internal { // Now() is somewhat expensive so it makes sense not to call Now() unless we // really need to. class LazyNow { public: - explicit LazyNow(base::TimeTicks now) - : task_queue_manager_(nullptr), now_(now) { + explicit LazyNow(base::TimeTicks now) : tick_clock_(nullptr), now_(now) { DCHECK(!now.is_null()); } - explicit LazyNow(TaskQueueManager* task_queue_manager) - : task_queue_manager_(task_queue_manager) {} + explicit LazyNow(base::TickClock* tick_clock) : tick_clock_(tick_clock) {} base::TimeTicks Now(); private: - TaskQueueManager* task_queue_manager_; // NOT OWNED + base::TickClock* tick_clock_; // NOT OWNED base::TimeTicks now_; };
diff --git a/components/scheduler/base/nestable_single_thread_task_runner.h b/components/scheduler/base/nestable_single_thread_task_runner.h deleted file mode 100644 index 2fc7c28..0000000 --- a/components/scheduler/base/nestable_single_thread_task_runner.h +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2015 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_SCHEDULER_BASE_NESTABLE_SINGLE_THREAD_TASK_RUNNER_H_ -#define COMPONENTS_SCHEDULER_BASE_NESTABLE_SINGLE_THREAD_TASK_RUNNER_H_ - -#include "base/single_thread_task_runner.h" -#include "base/message_loop/message_loop.h" -#include "components/scheduler/scheduler_export.h" - -namespace scheduler { - -// A single thread task runner which exposes whether it is running nested. -class SCHEDULER_EXPORT NestableSingleThreadTaskRunner - : public base::SingleThreadTaskRunner { - public: - NestableSingleThreadTaskRunner() {} - - // Returns true if the task runner is nested (i.e., running a run loop within - // a nested task). - virtual bool IsNested() const = 0; - - protected: - ~NestableSingleThreadTaskRunner() override {} - - DISALLOW_COPY_AND_ASSIGN(NestableSingleThreadTaskRunner); -}; - -} // namespace scheduler - -#endif // COMPONENTS_SCHEDULER_BASE_NESTABLE_SINGLE_THREAD_TASK_RUNNER_H_
diff --git a/components/scheduler/base/nestable_task_runner_for_test.cc b/components/scheduler/base/nestable_task_runner_for_test.cc deleted file mode 100644 index 5f20dd4..0000000 --- a/components/scheduler/base/nestable_task_runner_for_test.cc +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright 2015 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/scheduler/base/nestable_task_runner_for_test.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" - -namespace scheduler { - -// static -scoped_refptr<NestableTaskRunnerForTest> NestableTaskRunnerForTest::Create( - scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - return make_scoped_refptr(new NestableTaskRunnerForTest(task_runner)); -} - -NestableTaskRunnerForTest::NestableTaskRunnerForTest( - scoped_refptr<base::SingleThreadTaskRunner> task_runner) - : task_runner_(task_runner) {} - -NestableTaskRunnerForTest::~NestableTaskRunnerForTest() {} - -bool NestableTaskRunnerForTest::PostDelayedTask( - const tracked_objects::Location& from_here, - const base::Closure& task, - base::TimeDelta delay) { - return task_runner_->PostDelayedTask(from_here, task, delay); -} - -bool NestableTaskRunnerForTest::PostNonNestableDelayedTask( - const tracked_objects::Location& from_here, - const base::Closure& task, - base::TimeDelta delay) { - return task_runner_->PostNonNestableDelayedTask(from_here, task, delay); -} - -bool NestableTaskRunnerForTest::RunsTasksOnCurrentThread() const { - return task_runner_->RunsTasksOnCurrentThread(); -} - -bool NestableTaskRunnerForTest::IsNested() const { - return false; -} - -} // namespace scheduler
diff --git a/components/scheduler/base/nestable_task_runner_for_test.h b/components/scheduler/base/nestable_task_runner_for_test.h deleted file mode 100644 index 593b846..0000000 --- a/components/scheduler/base/nestable_task_runner_for_test.h +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2015 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 CONTENT_RENDERER_SCHEDULER_BASE_NESTABLE_TASK_RUNNER_FOR_TEST_H_ -#define CONTENT_RENDERER_SCHEDULER_BASE_NESTABLE_TASK_RUNNER_FOR_TEST_H_ - -#include "components/scheduler/base/nestable_single_thread_task_runner.h" - -namespace scheduler { - -class NestableTaskRunnerForTest : public NestableSingleThreadTaskRunner { - public: - static scoped_refptr<NestableTaskRunnerForTest> Create( - scoped_refptr<base::SingleThreadTaskRunner> task_runner); - - // NestableSingleThreadTaskRunner implementation - bool PostDelayedTask(const tracked_objects::Location& from_here, - const base::Closure& task, - base::TimeDelta delay) override; - bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, - const base::Closure& task, - base::TimeDelta delay) override; - bool RunsTasksOnCurrentThread() const override; - bool IsNested() const override; - - protected: - ~NestableTaskRunnerForTest() override; - NestableTaskRunnerForTest( - scoped_refptr<base::SingleThreadTaskRunner> task_runner); - - private: - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - - DISALLOW_COPY_AND_ASSIGN(NestableTaskRunnerForTest); -}; - -} // namespace scheduler - -#endif // CONTENT_RENDERER_SCHEDULER_BASE_NESTABLE_TASK_RUNNER_FOR_TEST_H_
diff --git a/components/scheduler/base/task_queue_impl.cc b/components/scheduler/base/task_queue_impl.cc index 98db7c57..1c8dbf4 100644 --- a/components/scheduler/base/task_queue_impl.cc +++ b/components/scheduler/base/task_queue_impl.cc
@@ -103,7 +103,7 @@ base::AutoLock lock(any_thread_lock_); if (!any_thread().task_queue_manager) return false; - LazyNow lazy_now(any_thread().task_queue_manager); + LazyNow lazy_now(any_thread().task_queue_manager->tick_clock()); return PostDelayedTaskLocked(&lazy_now, from_here, task, desired_run_time, TaskType::NORMAL); } @@ -116,7 +116,7 @@ base::AutoLock lock(any_thread_lock_); if (!any_thread().task_queue_manager) return false; - LazyNow lazy_now(any_thread().task_queue_manager); + LazyNow lazy_now(any_thread().task_queue_manager->tick_clock()); base::TimeTicks desired_run_time; if (delay > base::TimeDelta()) desired_run_time = lazy_now.Now() + delay; @@ -321,7 +321,7 @@ if (!any_thread().task_queue_manager) return; - LazyNow lazy_now(any_thread().task_queue_manager); + LazyNow lazy_now(any_thread().task_queue_manager->tick_clock()); MoveReadyDelayedTasksToIncomingQueueLocked(&lazy_now); bool was_empty = main_thread_only().work_queue.empty();
diff --git a/components/scheduler/base/task_queue_manager.cc b/components/scheduler/base/task_queue_manager.cc index 06ac8be..f859d0c1d 100644 --- a/components/scheduler/base/task_queue_manager.cc +++ b/components/scheduler/base/task_queue_manager.cc
@@ -8,10 +8,9 @@ #include <set> #include "base/bind.h" -#include "base/time/default_tick_clock.h" #include "components/scheduler/base/lazy_now.h" -#include "components/scheduler/base/nestable_single_thread_task_runner.h" #include "components/scheduler/base/task_queue_impl.h" +#include "components/scheduler/base/task_queue_manager_delegate.h" #include "components/scheduler/base/task_queue_selector.h" #include "components/scheduler/base/task_queue_sets.h" @@ -22,15 +21,14 @@ namespace scheduler { TaskQueueManager::TaskQueueManager( - scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner, + scoped_refptr<TaskQueueManagerDelegate> delegate, const char* tracing_category, const char* disabled_by_default_tracing_category, const char* disabled_by_default_verbose_tracing_category) - : main_task_runner_(main_task_runner), + : delegate_(delegate), task_was_run_on_quiescence_monitored_queue_(false), pending_dowork_count_(0), work_batch_size_(1), - time_source_(new base::DefaultTickClock), tracing_category_(tracing_category), disabled_by_default_tracing_category_( disabled_by_default_tracing_category), @@ -39,7 +37,7 @@ observer_(nullptr), deletion_sentinel_(new DeletionSentinel()), weak_factory_(this) { - DCHECK(main_task_runner->RunsTasksOnCurrentThread()); + DCHECK(delegate->RunsTasksOnCurrentThread()); TRACE_EVENT_OBJECT_CREATED_WITH_ID(disabled_by_default_tracing_category, "TaskQueueManager", this); selector_.SetTaskQueueSelectorObserver(this); @@ -173,7 +171,7 @@ DCHECK(main_thread_checker_.CalledOnValidThread()); TRACE_EVENT0(disabled_by_default_tracing_category_, "TaskQueueManager::UpdateWorkQueues"); - internal::LazyNow lazy_now(this); + internal::LazyNow lazy_now(tick_clock()); // Move any ready delayed tasks into the incomming queues. WakeupReadyDelayedQueues(&lazy_now); @@ -194,19 +192,19 @@ void TaskQueueManager::ScheduleDelayedWorkTask( scoped_refptr<internal::TaskQueueImpl> queue, base::TimeTicks delayed_run_time) { - internal::LazyNow lazy_now(this); + internal::LazyNow lazy_now(tick_clock()); ScheduleDelayedWork(queue.get(), delayed_run_time, &lazy_now); } void TaskQueueManager::ScheduleDelayedWork(internal::TaskQueueImpl* queue, base::TimeTicks delayed_run_time, internal::LazyNow* lazy_now) { - if (!main_task_runner_->BelongsToCurrentThread()) { + if (!delegate_->BelongsToCurrentThread()) { // NOTE posting a delayed task from a different thread is not expected to be // common. This pathway is less optimal than perhaps it could be because // it causes two main thread tasks to be run. Should this assumption prove // to be false in future, we may need to revisit this. - main_task_runner_->PostTask( + delegate_->PostTask( FROM_HERE, base::Bind(&TaskQueueManager::ScheduleDelayedWorkTask, weak_factory_.GetWeakPtr(), scoped_refptr<internal::TaskQueueImpl>(queue), @@ -214,13 +212,13 @@ return; } - // Make sure there's one (and only one) task posted to |main_task_runner_| + // Make sure there's one (and only one) task posted to |delegate_| // to call |DelayedDoWork| at |delayed_run_time|. if (delayed_wakeup_multimap_.find(delayed_run_time) == delayed_wakeup_multimap_.end()) { base::TimeDelta delay = std::max(base::TimeDelta(), delayed_run_time - lazy_now->Now()); - main_task_runner_->PostDelayedTask(FROM_HERE, do_work_closure_, delay); + delegate_->PostDelayedTask(FROM_HERE, do_work_closure_, delay); } delayed_wakeup_multimap_.insert(std::make_pair(delayed_run_time, queue)); } @@ -247,7 +245,7 @@ } void TaskQueueManager::MaybePostDoWorkOnMainRunner() { - bool on_main_thread = main_task_runner_->BelongsToCurrentThread(); + bool on_main_thread = delegate_->BelongsToCurrentThread(); if (on_main_thread) { // We only want one pending DoWork posted from the main thread, or we risk // an explosion of pending DoWorks which could starve out everything else. @@ -255,10 +253,9 @@ return; } pending_dowork_count_++; - main_task_runner_->PostTask(FROM_HERE, - decrement_pending_and_do_work_closure_); + delegate_->PostTask(FROM_HERE, decrement_pending_and_do_work_closure_); } else { - main_task_runner_->PostTask(FROM_HERE, do_work_closure_); + delegate_->PostTask(FROM_HERE, do_work_closure_); } } @@ -269,7 +266,7 @@ } DCHECK(main_thread_checker_.CalledOnValidThread()); - if (!main_task_runner_->IsNested()) + if (!delegate_->IsNested()) queues_to_delete_.clear(); // Pass false and nullptr to UpdateWorkQueues here to prevent waking up a @@ -299,15 +296,19 @@ // Only run a single task per batch in nested run loops so that we can // properly exit the nested loop when someone calls RunLoop::Quit(). - if (main_task_runner_->IsNested()) + if (delegate_->IsNested()) break; } // TODO(alexclarke): Consider refactoring the above loop to terminate only // when there's no more work left to be done, rather than posting a // continuation task. - if (!selector_.EnabledWorkQueuesEmpty()) + if (!selector_.EnabledWorkQueuesEmpty()) { MaybePostDoWorkOnMainRunner(); + } else { + // Tell the task runner we have no more work. + delegate_->OnNoMoreImmediateWork(); + } } bool TaskQueueManager::SelectQueueToService( @@ -335,13 +336,12 @@ if (queue->GetQuiescenceMonitored()) task_was_run_on_quiescence_monitored_queue_ = true; - if (!pending_task.nestable && main_task_runner_->IsNested()) { + if (!pending_task.nestable && delegate_->IsNested()) { // Defer non-nestable work to the main task runner. NOTE these tasks can be // arbitrarily delayed so the additional delay should not be a problem. // TODO(skyostil): Figure out a way to not forget which task queue the // task is associated with. See http://crbug.com/522843. - main_task_runner_->PostNonNestableTask(pending_task.posted_from, - pending_task.task); + delegate_->PostNonNestableTask(pending_task.posted_from, pending_task.task); return ProcessTaskResult::DEFERRED; } @@ -373,15 +373,7 @@ } bool TaskQueueManager::RunsTasksOnCurrentThread() const { - return main_task_runner_->RunsTasksOnCurrentThread(); -} - -bool TaskQueueManager::PostDelayedTask( - const tracked_objects::Location& from_here, - const base::Closure& task, - base::TimeDelta delay) { - DCHECK_GE(delay, base::TimeDelta()); - return main_task_runner_->PostDelayedTask(from_here, task, delay); + return delegate_->RunsTasksOnCurrentThread(); } void TaskQueueManager::SetWorkBatchSize(int work_batch_size) { @@ -402,20 +394,14 @@ task_observers_.RemoveObserver(task_observer); } -void TaskQueueManager::SetTimeSourceForTesting( - scoped_ptr<base::TickClock> time_source) { - DCHECK(main_thread_checker_.CalledOnValidThread()); - time_source_ = time_source.Pass(); -} - bool TaskQueueManager::GetAndClearSystemIsQuiescentBit() { bool task_was_run = task_was_run_on_quiescence_monitored_queue_; task_was_run_on_quiescence_monitored_queue_ = false; return !task_was_run; } -base::TimeTicks TaskQueueManager::Now() const { - return time_source_->NowTicks(); +base::TickClock* TaskQueueManager::tick_clock() const { + return delegate_.get(); } int TaskQueueManager::GetNextSequenceNumber() {
diff --git a/components/scheduler/base/task_queue_manager.h b/components/scheduler/base/task_queue_manager.h index f415674..88737a3 100644 --- a/components/scheduler/base/task_queue_manager.h +++ b/components/scheduler/base/task_queue_manager.h
@@ -34,7 +34,7 @@ class TaskQueueImpl; } // namespace internal -class NestableSingleThreadTaskRunner; +class TaskQueueManagerDelegate; // The task queue manager provides N task queues and a selector interface for // choosing which task queue to service next. Each task queue consists of two @@ -51,14 +51,13 @@ class SCHEDULER_EXPORT TaskQueueManager : public internal::TaskQueueSelector::Observer { public: - // Create a task queue manager where |main_task_runner| identifies the thread + // Create a task queue manager where |delegate| identifies the thread // on which where the tasks are eventually run. Category strings must have // application lifetime (statics or literals). They may not include " chars. - TaskQueueManager( - scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner, - const char* tracing_category, - const char* disabled_by_default_tracing_category, - const char* disabled_by_default_verbose_tracing_category); + TaskQueueManager(scoped_refptr<TaskQueueManagerDelegate> delegate, + const char* tracing_category, + const char* disabled_by_default_tracing_category, + const char* disabled_by_default_verbose_tracing_category); ~TaskQueueManager() override; // Returns the time of the next pending delayed task in any queue. Ignores @@ -78,8 +77,6 @@ void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer); void RemoveTaskObserver(base::MessageLoop::TaskObserver* task_observer); - void SetTimeSourceForTesting(scoped_ptr<base::TickClock> time_source); - // Returns true if any task from a monitored task queue was was run since the // last call to GetAndClearSystemIsQuiescentBit. bool GetAndClearSystemIsQuiescentBit(); @@ -103,6 +100,9 @@ // Note |observer| is expected to outlive the SchedulerHelper. void SetObserver(Observer* observer); + // Returns the TickClock used by the TaskQueueManager. + base::TickClock* tick_clock() const; + private: friend class internal::LazyNow; friend class internal::TaskQueueImpl; @@ -160,15 +160,10 @@ internal::TaskQueueImpl::Task* out_previous_task); bool RunsTasksOnCurrentThread() const; - bool PostDelayedTask(const tracked_objects::Location& from_here, - const base::Closure& task, - base::TimeDelta delay); bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, const base::Closure& task, base::TimeDelta delay); - base::TimeTicks Now() const; - int GetNextSequenceNumber(); scoped_refptr<base::trace_event::ConvertableToTraceFormat> @@ -224,7 +219,7 @@ base::debug::TaskAnnotator task_annotator_; base::ThreadChecker main_thread_checker_; - scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner_; + scoped_refptr<TaskQueueManagerDelegate> delegate_; internal::TaskQueueSelector selector_; base::Closure decrement_pending_and_do_work_closure_; @@ -238,8 +233,6 @@ int work_batch_size_; - scoped_ptr<base::TickClock> time_source_; - base::ObserverList<base::MessageLoop::TaskObserver> task_observers_; const char* tracing_category_;
diff --git a/components/scheduler/base/task_queue_manager_delegate.h b/components/scheduler/base/task_queue_manager_delegate.h new file mode 100644 index 0000000..a93110e8 --- /dev/null +++ b/components/scheduler/base/task_queue_manager_delegate.h
@@ -0,0 +1,40 @@ +// Copyright 2015 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_SCHEDULER_BASE_TASK_QUEUE_MANAGER_DELEGATE_H_ +#define COMPONENTS_SCHEDULER_BASE_TASK_QUEUE_MANAGER_DELEGATE_H_ + +#include "base/callback.h" +#include "base/macros.h" +#include "base/message_loop/message_loop.h" +#include "base/time/tick_clock.h" +#include "components/scheduler/scheduler_export.h" + +namespace scheduler { + +class SCHEDULER_EXPORT TaskQueueManagerDelegate + : public base::SingleThreadTaskRunner, + public base::TickClock { + public: + TaskQueueManagerDelegate() {} + + // Returns true if the task runner is nested (i.e., running a run loop within + // a nested task). + virtual bool IsNested() const = 0; + + // Used by the TaskQueueManager to tell us there is no more non-delayed work + // to do. + // TODO(alexclarke): Try and find a better interface that avoids the need for + // this. + virtual void OnNoMoreImmediateWork() = 0; + + protected: + ~TaskQueueManagerDelegate() override {} + + DISALLOW_COPY_AND_ASSIGN(TaskQueueManagerDelegate); +}; + +} // namespace scheduler + +#endif // COMPONENTS_SCHEDULER_BASE_TASK_QUEUE_MANAGER_DELEGATE_H_
diff --git a/components/scheduler/base/task_queue_manager_delegate_for_test.cc b/components/scheduler/base/task_queue_manager_delegate_for_test.cc new file mode 100644 index 0000000..d1d2316 --- /dev/null +++ b/components/scheduler/base/task_queue_manager_delegate_for_test.cc
@@ -0,0 +1,56 @@ +// Copyright 2015 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/scheduler/base/task_queue_manager_delegate_for_test.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" + +namespace scheduler { + +// static +scoped_refptr<TaskQueueManagerDelegateForTest> +TaskQueueManagerDelegateForTest::Create( + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_ptr<base::TickClock> time_source) { + return make_scoped_refptr( + new TaskQueueManagerDelegateForTest(task_runner, time_source.Pass())); +} + +TaskQueueManagerDelegateForTest::TaskQueueManagerDelegateForTest( + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_ptr<base::TickClock> time_source) + : task_runner_(task_runner), time_source_(time_source.Pass()) {} + +TaskQueueManagerDelegateForTest::~TaskQueueManagerDelegateForTest() {} + +bool TaskQueueManagerDelegateForTest::PostDelayedTask( + const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) { + return task_runner_->PostDelayedTask(from_here, task, delay); +} + +bool TaskQueueManagerDelegateForTest::PostNonNestableDelayedTask( + const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) { + return task_runner_->PostNonNestableDelayedTask(from_here, task, delay); +} + +bool TaskQueueManagerDelegateForTest::RunsTasksOnCurrentThread() const { + return task_runner_->RunsTasksOnCurrentThread(); +} + +bool TaskQueueManagerDelegateForTest::IsNested() const { + return false; +} + +base::TimeTicks TaskQueueManagerDelegateForTest::NowTicks() { + return time_source_->NowTicks(); +} + +void TaskQueueManagerDelegateForTest::OnNoMoreImmediateWork() {} + +} // namespace scheduler
diff --git a/components/scheduler/base/task_queue_manager_delegate_for_test.h b/components/scheduler/base/task_queue_manager_delegate_for_test.h new file mode 100644 index 0000000..390dd90f --- /dev/null +++ b/components/scheduler/base/task_queue_manager_delegate_for_test.h
@@ -0,0 +1,47 @@ +// Copyright 2015 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_SCHEDULER_BASE_TASK_QUEUE_MANAGER_DELEGATE_FOR_TEST_H_ +#define COMPONENTS_SCHEDULER_BASE_TASK_QUEUE_MANAGER_DELEGATE_FOR_TEST_H_ + +#include "base/macros.h" +#include "base/time/tick_clock.h" +#include "components/scheduler/base/task_queue_manager_delegate.h" + +namespace scheduler { + +class TaskQueueManagerDelegateForTest : public TaskQueueManagerDelegate { + public: + static scoped_refptr<TaskQueueManagerDelegateForTest> Create( + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_ptr<base::TickClock> time_source); + + // NestableSingleThreadTaskRunner implementation + bool PostDelayedTask(const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) override; + bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) override; + bool RunsTasksOnCurrentThread() const override; + bool IsNested() const override; + base::TimeTicks NowTicks() override; + void OnNoMoreImmediateWork() override; + + protected: + ~TaskQueueManagerDelegateForTest() override; + TaskQueueManagerDelegateForTest( + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_ptr<base::TickClock> time_source); + + private: + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + scoped_ptr<base::TickClock> time_source_; + + DISALLOW_COPY_AND_ASSIGN(TaskQueueManagerDelegateForTest); +}; + +} // namespace scheduler + +#endif // COMPONENTS_SCHEDULER_BASE_TASK_QUEUE_MANAGER_DELEGATE_FOR_TEST_H_
diff --git a/components/scheduler/base/task_queue_manager_perftest.cc b/components/scheduler/base/task_queue_manager_perftest.cc index df4bf5e..dcdb5069 100644 --- a/components/scheduler/base/task_queue_manager_perftest.cc +++ b/components/scheduler/base/task_queue_manager_perftest.cc
@@ -6,8 +6,9 @@ #include "base/bind.h" #include "base/threading/thread.h" -#include "components/scheduler/base/nestable_task_runner_for_test.h" +#include "base/time/default_tick_clock.h" #include "components/scheduler/base/task_queue_impl.h" +#include "components/scheduler/base/task_queue_manager_delegate_for_test.h" #include "components/scheduler/base/task_queue_selector.h" #include "components/scheduler/base/task_queue_sets.h" #include "testing/gtest/include/gtest/gtest.h" @@ -33,7 +34,9 @@ num_queues_ = num_queues; message_loop_.reset(new base::MessageLoop()); manager_ = make_scoped_ptr(new TaskQueueManager( - NestableTaskRunnerForTest::Create(message_loop_->task_runner()), + TaskQueueManagerDelegateForTest::Create( + message_loop_->task_runner(), + make_scoped_ptr(new base::DefaultTickClock())), "fake.category", "fake.category", "fake.category.debug")); for (size_t i = 0; i < num_queues; i++) queues_.push_back(manager_->NewTaskQueue(TaskQueue::Spec("test")));
diff --git a/components/scheduler/base/task_queue_manager_unittest.cc b/components/scheduler/base/task_queue_manager_unittest.cc index fcdb835..1c46c69 100644 --- a/components/scheduler/base/task_queue_manager_unittest.cc +++ b/components/scheduler/base/task_queue_manager_unittest.cc
@@ -10,8 +10,8 @@ #include "base/test/simple_test_tick_clock.h" #include "base/threading/thread.h" #include "cc/test/ordered_simple_task_runner.h" -#include "components/scheduler/base/nestable_task_runner_for_test.h" #include "components/scheduler/base/task_queue_impl.h" +#include "components/scheduler/base/task_queue_manager_delegate_for_test.h" #include "components/scheduler/base/task_queue_selector.h" #include "components/scheduler/base/task_queue_sets.h" #include "components/scheduler/base/test_always_fail_time_source.h" @@ -23,10 +23,11 @@ namespace scheduler { -class MessageLoopTaskRunner : public NestableTaskRunnerForTest { +class MessageLoopTaskRunner : public TaskQueueManagerDelegateForTest { public: - static scoped_refptr<MessageLoopTaskRunner> Create() { - return make_scoped_refptr(new MessageLoopTaskRunner()); + static scoped_refptr<MessageLoopTaskRunner> Create( + scoped_ptr<base::TickClock> tick_clock) { + return make_scoped_refptr(new MessageLoopTaskRunner(tick_clock.Pass())); } // NestableTaskRunner implementation. @@ -35,9 +36,10 @@ } private: - MessageLoopTaskRunner() - : NestableTaskRunnerForTest(base::MessageLoop::current()->task_runner()) { - } + explicit MessageLoopTaskRunner(scoped_ptr<base::TickClock> tick_clock) + : TaskQueueManagerDelegateForTest(base::MessageLoop::current() + ->task_runner(), + tick_clock.Pass()) {} ~MessageLoopTaskRunner() override {} }; @@ -46,28 +48,34 @@ void DeleteTaskQueueManager() { manager_.reset(); } protected: - void Initialize(size_t num_queues) { - now_src_.reset(new base::SimpleTestTickClock()); - now_src_->Advance(base::TimeDelta::FromMicroseconds(1000)); + void InitializeWithClock(size_t num_queues, + scoped_ptr<base::TickClock> test_time_source) { test_task_runner_ = make_scoped_refptr( new cc::OrderedSimpleTaskRunner(now_src_.get(), false)); - main_task_runner_ = - NestableTaskRunnerForTest::Create(test_task_runner_.get()); + main_task_runner_ = TaskQueueManagerDelegateForTest::Create( + test_task_runner_.get(), + make_scoped_ptr(new TestTimeSource(now_src_.get()))); manager_ = make_scoped_ptr(new TaskQueueManager( main_task_runner_, "test.scheduler", "test.scheduler", "test.scheduler.debug")); - manager_->SetTimeSourceForTesting( - make_scoped_ptr(new TestTimeSource(now_src_.get()))); for (size_t i = 0; i < num_queues; i++) runners_.push_back(manager_->NewTaskQueue(TaskQueue::Spec("test_queue"))); } + void Initialize(size_t num_queues) { + now_src_.reset(new base::SimpleTestTickClock()); + now_src_->Advance(base::TimeDelta::FromMicroseconds(1000)); + InitializeWithClock(num_queues, + make_scoped_ptr(new TestTimeSource(now_src_.get()))); + } + void InitializeWithRealMessageLoop(size_t num_queues) { message_loop_.reset(new base::MessageLoop()); - manager_ = make_scoped_ptr( - new TaskQueueManager(MessageLoopTaskRunner::Create(), "test.scheduler", - "test.scheduler", "test.scheduler.debug")); + manager_ = make_scoped_ptr(new TaskQueueManager( + MessageLoopTaskRunner::Create( + make_scoped_ptr(new TestTimeSource(now_src_.get()))), + "test.scheduler", "test.scheduler", "test.scheduler.debug")); for (size_t i = 0; i < num_queues; i++) runners_.push_back(manager_->NewTaskQueue(TaskQueue::Spec("test_queue"))); @@ -75,7 +83,7 @@ scoped_ptr<base::MessageLoop> message_loop_; scoped_ptr<base::SimpleTestTickClock> now_src_; - scoped_refptr<NestableTaskRunnerForTest> main_task_runner_; + scoped_refptr<TaskQueueManagerDelegateForTest> main_task_runner_; scoped_refptr<cc::OrderedSimpleTaskRunner> test_task_runner_; scoped_ptr<TaskQueueManager> manager_; std::vector<scoped_refptr<internal::TaskQueueImpl>> runners_; @@ -95,6 +103,28 @@ message_loop->RunUntilIdle(); } +void NopTask() {} + +TEST_F(TaskQueueManagerTest, NowNotCalledWhenThereAreNoDelayedTasks) { + message_loop_.reset(new base::MessageLoop()); + manager_ = make_scoped_ptr(new TaskQueueManager( + MessageLoopTaskRunner::Create( + make_scoped_ptr(new TestAlwaysFailTimeSource())), + "test.scheduler", "test.scheduler", "test.scheduler.debug")); + + for (size_t i = 0; i < 3; i++) + runners_.push_back(manager_->NewTaskQueue(TaskQueue::Spec("test_queue"))); + + runners_[0]->PostTask(FROM_HERE, base::Bind(&NopTask)); + runners_[0]->PostTask(FROM_HERE, base::Bind(&NopTask)); + runners_[1]->PostTask(FROM_HERE, base::Bind(&NopTask)); + runners_[1]->PostTask(FROM_HERE, base::Bind(&NopTask)); + runners_[2]->PostTask(FROM_HERE, base::Bind(&NopTask)); + runners_[2]->PostTask(FROM_HERE, base::Bind(&NopTask)); + + message_loop_->RunUntilIdle(); +} + void NullTask() {} void TestTask(int value, std::vector<int>* out_result) { @@ -128,24 +158,6 @@ EXPECT_THAT(run_order, ElementsAre(1, 2, 3, 4, 5, 6)); } -void NopTask() {} - -TEST_F(TaskQueueManagerTest, NowNotCalledWhenThereAreNoDelayedTasks) { - Initialize(3u); - - manager_->SetTimeSourceForTesting( - make_scoped_ptr(new TestAlwaysFailTimeSource())); - - runners_[0]->PostTask(FROM_HERE, base::Bind(&NopTask)); - runners_[0]->PostTask(FROM_HERE, base::Bind(&NopTask)); - runners_[1]->PostTask(FROM_HERE, base::Bind(&NopTask)); - runners_[1]->PostTask(FROM_HERE, base::Bind(&NopTask)); - runners_[2]->PostTask(FROM_HERE, base::Bind(&NopTask)); - runners_[2]->PostTask(FROM_HERE, base::Bind(&NopTask)); - - test_task_runner_->RunUntilIdle(); -} - TEST_F(TaskQueueManagerTest, NonNestableTaskPosting) { InitializeWithRealMessageLoop(1u); @@ -886,11 +898,8 @@ } TEST_F(TaskQueueManagerTest, NextPendingDelayedTaskRunTime) { - scoped_ptr<base::SimpleTestTickClock> clock(new base::SimpleTestTickClock()); - clock->Advance(base::TimeDelta::FromMicroseconds(10000)); Initialize(2u); - manager_->SetTimeSourceForTesting( - make_scoped_ptr(new TestTimeSource(clock.get()))); + now_src_->Advance(base::TimeDelta::FromMicroseconds(10000)); // With no delayed tasks. EXPECT_TRUE(manager_->NextPendingDelayedTaskRunTime().is_null()); @@ -902,30 +911,30 @@ // With a delayed task. base::TimeDelta expected_delay = base::TimeDelta::FromMilliseconds(50); runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), expected_delay); - EXPECT_EQ(clock->NowTicks() + expected_delay, + EXPECT_EQ(now_src_->NowTicks() + expected_delay, manager_->NextPendingDelayedTaskRunTime()); // With another delayed task in the same queue with a longer delay. runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), base::TimeDelta::FromMilliseconds(100)); - EXPECT_EQ(clock->NowTicks() + expected_delay, + EXPECT_EQ(now_src_->NowTicks() + expected_delay, manager_->NextPendingDelayedTaskRunTime()); // With another delayed task in the same queue with a shorter delay. expected_delay = base::TimeDelta::FromMilliseconds(20); runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), expected_delay); - EXPECT_EQ(clock->NowTicks() + expected_delay, + EXPECT_EQ(now_src_->NowTicks() + expected_delay, manager_->NextPendingDelayedTaskRunTime()); // With another delayed task in a different queue with a shorter delay. expected_delay = base::TimeDelta::FromMilliseconds(10); runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), expected_delay); - EXPECT_EQ(clock->NowTicks() + expected_delay, + EXPECT_EQ(now_src_->NowTicks() + expected_delay, manager_->NextPendingDelayedTaskRunTime()); // Test it updates as time progresses - clock->Advance(expected_delay); - EXPECT_EQ(clock->NowTicks(), manager_->NextPendingDelayedTaskRunTime()); + now_src_->Advance(expected_delay); + EXPECT_EQ(now_src_->NowTicks(), manager_->NextPendingDelayedTaskRunTime()); } TEST_F(TaskQueueManagerTest, NextPendingDelayedTaskRunTime_MultipleQueues) {
diff --git a/components/scheduler/child/idle_helper.cc b/components/scheduler/child/idle_helper.cc index dc58c88..90f6d62 100644 --- a/components/scheduler/child/idle_helper.cc +++ b/components/scheduler/child/idle_helper.cc
@@ -139,7 +139,7 @@ return; } - base::TimeTicks now(helper_->Now()); + base::TimeTicks now(helper_->tick_clock()->NowTicks()); base::TimeDelta next_long_idle_period_delay; IdlePeriodState new_idle_period_state = ComputeNewLongIdlePeriodState(now, &next_long_idle_period_delay); @@ -203,7 +203,7 @@ if (IsInIdlePeriod(state_.idle_period_state()) && state_.idle_period_state() != IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED && - helper_->Now() >= state_.idle_period_deadline()) { + helper_->tick_clock()->NowTicks() >= state_.idle_period_deadline()) { // If the idle period deadline has now been reached, either end the idle // period or trigger a new long-idle period. if (IsInLongIdlePeriod(state_.idle_period_state())) { @@ -238,8 +238,9 @@ } else { // Otherwise ensure that we kick the scheduler at the right time to // initiate the next idle period. - next_long_idle_period_delay = std::max( - base::TimeDelta(), state_.idle_period_deadline() - helper_->Now()); + next_long_idle_period_delay = + std::max(base::TimeDelta(), state_.idle_period_deadline() - + helper_->tick_clock()->NowTicks()); } if (next_long_idle_period_delay == base::TimeDelta()) { EnableLongIdlePeriod(); @@ -358,7 +359,9 @@ bool is_tracing; TRACE_EVENT_CATEGORY_GROUP_ENABLED(tracing_category_, &is_tracing); if (is_tracing) { - base::TimeTicks now(optional_now.is_null() ? helper_->Now() : optional_now); + base::TimeTicks now(optional_now.is_null() + ? helper_->tick_clock()->NowTicks() + : optional_now); base::TraceTicks trace_now = base::TraceTicks::Now(); idle_period_deadline_for_tracing_ = trace_now + (new_deadline - now); TraceEventIdlePeriodStateChange(
diff --git a/components/scheduler/child/idle_helper_unittest.cc b/components/scheduler/child/idle_helper_unittest.cc index 5e7f17c..b4f559b 100644 --- a/components/scheduler/child/idle_helper_unittest.cc +++ b/components/scheduler/child/idle_helper_unittest.cc
@@ -11,8 +11,8 @@ #include "components/scheduler/base/task_queue_manager.h" #include "components/scheduler/base/test_time_source.h" #include "components/scheduler/child/scheduler_helper.h" -#include "components/scheduler/child/scheduler_task_runner_delegate_for_test.h" -#include "components/scheduler/child/scheduler_task_runner_delegate_impl.h" +#include "components/scheduler/child/scheduler_tqm_delegate_for_test.h" +#include "components/scheduler/child/scheduler_tqm_delegate_impl.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -126,13 +126,16 @@ idle_helper->EndIdlePeriod(); } -scoped_refptr<SchedulerTaskRunnerDelegate> CreateTaskRunnerDelegate( +scoped_refptr<SchedulerTqmDelegate> CreateTaskRunnerDelegate( base::MessageLoop* message_loop, - scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner) { + scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner, + scoped_ptr<TestTimeSource> test_time_source) { if (message_loop) - return SchedulerTaskRunnerDelegateImpl::Create(message_loop); + return SchedulerTqmDelegateImpl::Create(message_loop, + test_time_source.Pass()); - return SchedulerTaskRunnerDelegateForTest::Create(mock_task_runner); + return SchedulerTqmDelegateForTest::Create(mock_task_runner, + test_time_source.Pass()); } }; // namespace @@ -172,8 +175,10 @@ ? nullptr : new cc::OrderedSimpleTaskRunner(clock_.get(), false)), message_loop_(message_loop), - main_task_runner_( - CreateTaskRunnerDelegate(message_loop, mock_task_runner_)), + main_task_runner_(CreateTaskRunnerDelegate( + message_loop, + mock_task_runner_, + make_scoped_ptr(new TestTimeSource(clock_.get())))), scheduler_helper_( new SchedulerHelper(main_task_runner_, "test.idle", @@ -185,10 +190,6 @@ default_task_runner_(scheduler_helper_->DefaultTaskRunner()), idle_task_runner_(idle_helper_->IdleTaskRunner()) { clock_->Advance(base::TimeDelta::FromMicroseconds(5000)); - scheduler_helper_->SetTimeSourceForTesting( - make_scoped_ptr(new TestTimeSource(clock_.get()))); - scheduler_helper_->GetTaskQueueManagerForTesting()->SetTimeSourceForTesting( - make_scoped_ptr(new TestTimeSource(clock_.get()))); } ~BaseIdleHelperTest() override {} @@ -274,7 +275,7 @@ scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_; scoped_ptr<base::MessageLoop> message_loop_; - scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner_; + scoped_refptr<SchedulerTqmDelegate> main_task_runner_; scoped_ptr<SchedulerHelper> scheduler_helper_; scoped_ptr<IdleHelperForTest> idle_helper_; scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
diff --git a/components/scheduler/child/scheduler_helper.cc b/components/scheduler/child/scheduler_helper.cc index e0d683e..acec8b6 100644 --- a/components/scheduler/child/scheduler_helper.cc +++ b/components/scheduler/child/scheduler_helper.cc
@@ -8,18 +8,18 @@ #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "components/scheduler/base/task_queue_impl.h" -#include "components/scheduler/child/scheduler_task_runner_delegate.h" +#include "components/scheduler/child/scheduler_tqm_delegate.h" namespace scheduler { SchedulerHelper::SchedulerHelper( - scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner, + scoped_refptr<SchedulerTqmDelegate> task_queue_manager_delegate, const char* tracing_category, const char* disabled_by_default_tracing_category, const char* disabled_by_default_verbose_tracing_category) - : main_task_runner_(main_task_runner), + : task_queue_manager_delegate_(task_queue_manager_delegate), task_queue_manager_( - new TaskQueueManager(main_task_runner, + new TaskQueueManager(task_queue_manager_delegate, tracing_category, disabled_by_default_tracing_category, disabled_by_default_verbose_tracing_category)), @@ -34,7 +34,6 @@ .SetShouldNotifyObservers(false))), default_task_runner_(NewTaskQueue(TaskQueue::Spec("default_tq") .SetShouldMonitorQuiescence(true))), - time_source_(new base::DefaultTickClock), observer_(nullptr), tracing_category_(tracing_category), disabled_by_default_tracing_category_( @@ -45,7 +44,8 @@ task_queue_manager_->SetWorkBatchSize(4); - main_task_runner_->SetDefaultTaskRunner(default_task_runner_.get()); + task_queue_manager_delegate_->SetDefaultTaskRunner( + default_task_runner_.get()); } SchedulerHelper::~SchedulerHelper() { @@ -57,7 +57,7 @@ if (task_queue_manager_) task_queue_manager_->SetObserver(nullptr); task_queue_manager_.reset(); - main_task_runner_->RestoreDefaultTaskRunner(); + task_queue_manager_delegate_->RestoreDefaultTaskRunner(); } scoped_refptr<TaskQueue> SchedulerHelper::NewTaskQueue( @@ -79,12 +79,6 @@ return control_after_wakeup_task_runner_; } -void SchedulerHelper::SetTimeSourceForTesting( - scoped_ptr<base::TickClock> time_source) { - CheckOnValidThread(); - time_source_ = time_source.Pass(); -} - void SchedulerHelper::SetWorkBatchSizeForTesting(size_t work_batch_size) { CheckOnValidThread(); DCHECK(task_queue_manager_.get()); @@ -96,8 +90,8 @@ return task_queue_manager_.get(); } -base::TimeTicks SchedulerHelper::Now() const { - return time_source_->NowTicks(); +base::TickClock* SchedulerHelper::tick_clock() const { + return task_queue_manager_->tick_clock(); } base::TimeTicks SchedulerHelper::NextPendingDelayedTaskRunTime() const {
diff --git a/components/scheduler/child/scheduler_helper.h b/components/scheduler/child/scheduler_helper.h index 241ae609..a0b8be26 100644 --- a/components/scheduler/child/scheduler_helper.h +++ b/components/scheduler/child/scheduler_helper.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_SCHEDULER_CHILD_SCHEDULER_HELPER_H_ #define COMPONENTS_SCHEDULER_CHILD_SCHEDULER_HELPER_H_ +#include "base/time/tick_clock.h" #include "components/scheduler/base/task_queue_manager.h" #include "components/scheduler/base/task_queue_selector.h" #include "components/scheduler/scheduler_export.h" @@ -15,17 +16,18 @@ namespace scheduler { -class SchedulerTaskRunnerDelegate; +class SchedulerTqmDelegate; // Common scheduler functionality for default tasks. class SCHEDULER_EXPORT SchedulerHelper : public TaskQueueManager::Observer { public: // Category strings must have application lifetime (statics or // literals). They may not include " chars. - SchedulerHelper(scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner, - const char* tracing_category, - const char* disabled_by_default_tracing_category, - const char* disabled_by_default_verbose_tracing_category); + SchedulerHelper( + scoped_refptr<SchedulerTqmDelegate> task_queue_manager_delegate, + const char* tracing_category, + const char* disabled_by_default_tracing_category, + const char* disabled_by_default_verbose_tracing_category); ~SchedulerHelper() override; // TaskQueueManager::Observer implementation: @@ -81,12 +83,11 @@ void SetObserver(Observer* observer); // Accessor methods. - base::TimeTicks Now() const; + base::TickClock* tick_clock() const; base::TimeTicks NextPendingDelayedTaskRunTime() const; bool GetAndClearSystemIsQuiescentBit(); // Test helpers. - void SetTimeSourceForTesting(scoped_ptr<base::TickClock> time_source); void SetWorkBatchSizeForTesting(size_t work_batch_size); TaskQueueManager* GetTaskQueueManagerForTesting(); @@ -94,14 +95,12 @@ friend class SchedulerHelperTest; base::ThreadChecker thread_checker_; - scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner_; + scoped_refptr<SchedulerTqmDelegate> task_queue_manager_delegate_; scoped_ptr<TaskQueueManager> task_queue_manager_; scoped_refptr<TaskQueue> control_task_runner_; scoped_refptr<TaskQueue> control_after_wakeup_task_runner_; scoped_refptr<TaskQueue> default_task_runner_; - scoped_ptr<base::TickClock> time_source_; - Observer* observer_; // NOT OWNED const char* tracing_category_; const char* disabled_by_default_tracing_category_;
diff --git a/components/scheduler/child/scheduler_helper_unittest.cc b/components/scheduler/child/scheduler_helper_unittest.cc index 5d75bb2..f2d60cf9 100644 --- a/components/scheduler/child/scheduler_helper_unittest.cc +++ b/components/scheduler/child/scheduler_helper_unittest.cc
@@ -9,7 +9,7 @@ #include "cc/test/ordered_simple_task_runner.h" #include "components/scheduler/base/task_queue.h" #include "components/scheduler/base/test_time_source.h" -#include "components/scheduler/child/scheduler_task_runner_delegate_for_test.h" +#include "components/scheduler/child/scheduler_tqm_delegate_for_test.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -46,8 +46,9 @@ SchedulerHelperTest() : clock_(new base::SimpleTestTickClock()), mock_task_runner_(new cc::OrderedSimpleTaskRunner(clock_.get(), false)), - main_task_runner_( - SchedulerTaskRunnerDelegateForTest::Create(mock_task_runner_)), + main_task_runner_(SchedulerTqmDelegateForTest::Create( + mock_task_runner_, + make_scoped_ptr(new TestTimeSource(clock_.get())))), scheduler_helper_(new SchedulerHelper( main_task_runner_, "test.scheduler", @@ -55,10 +56,6 @@ TRACE_DISABLED_BY_DEFAULT("test.scheduler.dbg"))), default_task_runner_(scheduler_helper_->DefaultTaskRunner()) { clock_->Advance(base::TimeDelta::FromMicroseconds(5000)); - scheduler_helper_->SetTimeSourceForTesting( - make_scoped_ptr(new TestTimeSource(clock_.get()))); - scheduler_helper_->GetTaskQueueManagerForTesting()->SetTimeSourceForTesting( - make_scoped_ptr(new TestTimeSource(clock_.get()))); } ~SchedulerHelperTest() override {} @@ -86,7 +83,7 @@ scoped_ptr<base::SimpleTestTickClock> clock_; scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_; - scoped_refptr<SchedulerTaskRunnerDelegateForTest> main_task_runner_; + scoped_refptr<SchedulerTqmDelegateForTest> main_task_runner_; scoped_ptr<SchedulerHelper> scheduler_helper_; scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
diff --git a/components/scheduler/child/scheduler_task_runner_delegate.h b/components/scheduler/child/scheduler_task_runner_delegate.h deleted file mode 100644 index dd0fc14..0000000 --- a/components/scheduler/child/scheduler_task_runner_delegate.h +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2015 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_SCHEDULER_CHILD_SCHEDULER_TASK_RUNNER_DELEGATE_H_ -#define COMPONENTS_SCHEDULER_CHILD_SCHEDULER_TASK_RUNNER_DELEGATE_H_ - -#include "base/message_loop/message_loop.h" -#include "components/scheduler/base/nestable_single_thread_task_runner.h" -#include "components/scheduler/scheduler_export.h" - -namespace scheduler { - -class SCHEDULER_EXPORT SchedulerTaskRunnerDelegate - : public NestableSingleThreadTaskRunner { - public: - SchedulerTaskRunnerDelegate() {} - - // If the underlying task runner supports the concept of a default task - // runner, the delegate should implement this function to redirect that task - // runner to the scheduler. - virtual void SetDefaultTaskRunner( - scoped_refptr<base::SingleThreadTaskRunner> task_runner) = 0; - - // Similarly this method can be used to restore the original task runner when - // the scheduler no longer wants to intercept tasks. - virtual void RestoreDefaultTaskRunner() = 0; - - protected: - ~SchedulerTaskRunnerDelegate() override {} - - DISALLOW_COPY_AND_ASSIGN(SchedulerTaskRunnerDelegate); -}; - -} // namespace scheduler - -#endif // COMPONENTS_SCHEDULER_CHILD_SCHEDULER_TASK_RUNNER_DELEGATE_H_
diff --git a/components/scheduler/child/scheduler_task_runner_delegate_for_test.cc b/components/scheduler/child/scheduler_task_runner_delegate_for_test.cc deleted file mode 100644 index 4405d6d8..0000000 --- a/components/scheduler/child/scheduler_task_runner_delegate_for_test.cc +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2015 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/scheduler/child/scheduler_task_runner_delegate_for_test.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "components/scheduler/base/nestable_task_runner_for_test.h" - -namespace scheduler { - -// static -scoped_refptr<SchedulerTaskRunnerDelegateForTest> -SchedulerTaskRunnerDelegateForTest::Create( - scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - return make_scoped_refptr( - new SchedulerTaskRunnerDelegateForTest(task_runner)); -} - -SchedulerTaskRunnerDelegateForTest::SchedulerTaskRunnerDelegateForTest( - scoped_refptr<base::SingleThreadTaskRunner> task_runner) - : task_runner_(NestableTaskRunnerForTest::Create(task_runner)) {} - -SchedulerTaskRunnerDelegateForTest::~SchedulerTaskRunnerDelegateForTest() {} - -void SchedulerTaskRunnerDelegateForTest::SetDefaultTaskRunner( - scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - default_task_runner_ = task_runner.Pass(); -} - -void SchedulerTaskRunnerDelegateForTest::RestoreDefaultTaskRunner() { - default_task_runner_ = nullptr; -} - -bool SchedulerTaskRunnerDelegateForTest::PostDelayedTask( - const tracked_objects::Location& from_here, - const base::Closure& task, - base::TimeDelta delay) { - return task_runner_->PostDelayedTask(from_here, task, delay); -} - -bool SchedulerTaskRunnerDelegateForTest::PostNonNestableDelayedTask( - const tracked_objects::Location& from_here, - const base::Closure& task, - base::TimeDelta delay) { - return task_runner_->PostNonNestableDelayedTask(from_here, task, delay); -} - -bool SchedulerTaskRunnerDelegateForTest::RunsTasksOnCurrentThread() const { - return task_runner_->RunsTasksOnCurrentThread(); -} - -bool SchedulerTaskRunnerDelegateForTest::IsNested() const { - return task_runner_->IsNested(); -} - -} // namespace scheduler
diff --git a/components/scheduler/child/scheduler_task_runner_delegate_for_test.h b/components/scheduler/child/scheduler_task_runner_delegate_for_test.h deleted file mode 100644 index 27c6309..0000000 --- a/components/scheduler/child/scheduler_task_runner_delegate_for_test.h +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2015 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 CONTENT_RENDERER_SCHEDULER_TASK_RUNNER_DELEGATE_FOR_TEST_H_ -#define CONTENT_RENDERER_SCHEDULER_TASK_RUNNER_DELEGATE_FOR_TEST_H_ - -#include "components/scheduler/child/scheduler_task_runner_delegate.h" - -namespace scheduler { - -class NestableTaskRunnerForTest; - -class SchedulerTaskRunnerDelegateForTest : public SchedulerTaskRunnerDelegate { - public: - static scoped_refptr<SchedulerTaskRunnerDelegateForTest> Create( - scoped_refptr<base::SingleThreadTaskRunner> task_runner); - - // SchedulerTaskRunnerDelegate implementation - void SetDefaultTaskRunner( - scoped_refptr<base::SingleThreadTaskRunner> task_runner) override; - void RestoreDefaultTaskRunner() override; - bool PostDelayedTask(const tracked_objects::Location& from_here, - const base::Closure& task, - base::TimeDelta delay) override; - bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, - const base::Closure& task, - base::TimeDelta delay) override; - bool RunsTasksOnCurrentThread() const override; - bool IsNested() const override; - - base::SingleThreadTaskRunner* default_task_runner() const { - return default_task_runner_.get(); - } - - protected: - ~SchedulerTaskRunnerDelegateForTest() override; - - private: - explicit SchedulerTaskRunnerDelegateForTest( - scoped_refptr<base::SingleThreadTaskRunner> task_runner); - - scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; - - scoped_refptr<NestableTaskRunnerForTest> task_runner_; - - DISALLOW_COPY_AND_ASSIGN(SchedulerTaskRunnerDelegateForTest); -}; - -} // namespace scheduler - -#endif // CONTENT_RENDERER_SCHEDULER_SCHEDULER_TASK_RUNNER_DELEGATE_FOR_TEST_H_
diff --git a/components/scheduler/child/scheduler_task_runner_delegate_impl.cc b/components/scheduler/child/scheduler_task_runner_delegate_impl.cc deleted file mode 100644 index 0c34554..0000000 --- a/components/scheduler/child/scheduler_task_runner_delegate_impl.cc +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright 2015 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/scheduler/child/scheduler_task_runner_delegate_impl.h" - -namespace scheduler { - -// static -scoped_refptr<SchedulerTaskRunnerDelegateImpl> -SchedulerTaskRunnerDelegateImpl::Create(base::MessageLoop* message_loop) { - return make_scoped_refptr(new SchedulerTaskRunnerDelegateImpl(message_loop)); -} - -SchedulerTaskRunnerDelegateImpl::SchedulerTaskRunnerDelegateImpl( - base::MessageLoop* message_loop) - : message_loop_(message_loop), - message_loop_task_runner_(message_loop->task_runner()) {} - -SchedulerTaskRunnerDelegateImpl::~SchedulerTaskRunnerDelegateImpl() { - RestoreDefaultTaskRunner(); -} - -void SchedulerTaskRunnerDelegateImpl::SetDefaultTaskRunner( - scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - message_loop_->SetTaskRunner(task_runner); -} - -void SchedulerTaskRunnerDelegateImpl::RestoreDefaultTaskRunner() { - if (base::MessageLoop::current() == message_loop_) - message_loop_->SetTaskRunner(message_loop_task_runner_); -} - -bool SchedulerTaskRunnerDelegateImpl::PostDelayedTask( - const tracked_objects::Location& from_here, - const base::Closure& task, - base::TimeDelta delay) { - return message_loop_task_runner_->PostDelayedTask(from_here, task, delay); -} - -bool SchedulerTaskRunnerDelegateImpl::PostNonNestableDelayedTask( - const tracked_objects::Location& from_here, - const base::Closure& task, - base::TimeDelta delay) { - return message_loop_task_runner_->PostNonNestableDelayedTask(from_here, task, - delay); -} - -bool SchedulerTaskRunnerDelegateImpl::RunsTasksOnCurrentThread() const { - return message_loop_task_runner_->RunsTasksOnCurrentThread(); -} - -bool SchedulerTaskRunnerDelegateImpl::IsNested() const { - return message_loop_->IsNested(); -} - -} // namespace scheduler
diff --git a/components/scheduler/child/scheduler_task_runner_delegate_impl.h b/components/scheduler/child/scheduler_task_runner_delegate_impl.h deleted file mode 100644 index 2f18b99..0000000 --- a/components/scheduler/child/scheduler_task_runner_delegate_impl.h +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2015 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_SCHEDULER_CHILD_SCHEDULER_TASK_RUNNER_DELEGATE_IMPL_H_ -#define COMPONENTS_SCHEDULER_CHILD_SCHEDULER_TASK_RUNNER_DELEGATE_IMPL_H_ - -#include "base/message_loop/message_loop.h" -#include "components/scheduler/child/scheduler_task_runner_delegate.h" -#include "components/scheduler/scheduler_export.h" - -namespace scheduler { - -class SCHEDULER_EXPORT SchedulerTaskRunnerDelegateImpl - : public SchedulerTaskRunnerDelegate { - public: - // |message_loop| is not owned and must outlive the lifetime of this object. - static scoped_refptr<SchedulerTaskRunnerDelegateImpl> Create( - base::MessageLoop* message_loop); - - // SchedulerTaskRunnerDelegate implementation - void SetDefaultTaskRunner( - scoped_refptr<base::SingleThreadTaskRunner> task_runner) override; - void RestoreDefaultTaskRunner() override; - bool PostDelayedTask(const tracked_objects::Location& from_here, - const base::Closure& task, - base::TimeDelta delay) override; - bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, - const base::Closure& task, - base::TimeDelta delay) override; - bool RunsTasksOnCurrentThread() const override; - bool IsNested() const override; - - protected: - ~SchedulerTaskRunnerDelegateImpl() override; - - private: - explicit SchedulerTaskRunnerDelegateImpl(base::MessageLoop* message_loop); - - // Not owned. - base::MessageLoop* message_loop_; - scoped_refptr<SingleThreadTaskRunner> message_loop_task_runner_; - - DISALLOW_COPY_AND_ASSIGN(SchedulerTaskRunnerDelegateImpl); -}; - -} // namespace scheduler - -#endif // COMPONENTS_SCHEDULER_CHILD_SCHEDULER_TASK_RUNNER_DELEGATE_IMPL_H_
diff --git a/components/scheduler/child/scheduler_task_runner_delegate_impl_unittest.cc b/components/scheduler/child/scheduler_task_runner_delegate_impl_unittest.cc deleted file mode 100644 index 7e55a12..0000000 --- a/components/scheduler/child/scheduler_task_runner_delegate_impl_unittest.cc +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2015 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/scheduler/child/scheduler_task_runner_delegate_impl.h" - -#include "base/message_loop/message_loop.h" -#include "base/test/test_simple_task_runner.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace scheduler { - -TEST(SchedulerTaskRunnerDelegateImplTest, TestTaskRunnerOverriding) { - base::MessageLoop loop; - scoped_refptr<base::SingleThreadTaskRunner> original_runner( - loop.task_runner()); - scoped_refptr<base::SingleThreadTaskRunner> custom_runner( - new base::TestSimpleTaskRunner()); - { - scoped_refptr<SchedulerTaskRunnerDelegateImpl> delegate( - SchedulerTaskRunnerDelegateImpl::Create(&loop)); - delegate->SetDefaultTaskRunner(custom_runner); - DCHECK_EQ(custom_runner, loop.task_runner()); - } - DCHECK_EQ(original_runner, loop.task_runner()); -} - -} // namespace scheduler
diff --git a/components/scheduler/child/scheduler_tqm_delegate.h b/components/scheduler/child/scheduler_tqm_delegate.h new file mode 100644 index 0000000..bb294450 --- /dev/null +++ b/components/scheduler/child/scheduler_tqm_delegate.h
@@ -0,0 +1,37 @@ +// Copyright 2015 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_SCHEDULER_CHILD_SCHEDULER_TQM_DELEGATE_H_ +#define COMPONENTS_SCHEDULER_CHILD_SCHEDULER_TQM_DELEGATE_H_ + +#include "base/macros.h" +#include "base/message_loop/message_loop.h" +#include "components/scheduler/base/task_queue_manager_delegate.h" +#include "components/scheduler/scheduler_export.h" + +namespace scheduler { + +class SCHEDULER_EXPORT SchedulerTqmDelegate : public TaskQueueManagerDelegate { + public: + SchedulerTqmDelegate() {} + + // If the underlying task runner supports the concept of a default task + // runner, the delegate should implement this function to redirect that task + // runner to the scheduler. + virtual void SetDefaultTaskRunner( + scoped_refptr<base::SingleThreadTaskRunner> task_runner) = 0; + + // Similarly this method can be used to restore the original task runner when + // the scheduler no longer wants to intercept tasks. + virtual void RestoreDefaultTaskRunner() = 0; + + protected: + ~SchedulerTqmDelegate() override {} + + DISALLOW_COPY_AND_ASSIGN(SchedulerTqmDelegate); +}; + +} // namespace scheduler + +#endif // COMPONENTS_SCHEDULER_CHILD_SCHEDULER_TQM_DELEGATE_H_
diff --git a/components/scheduler/child/scheduler_tqm_delegate_for_test.cc b/components/scheduler/child/scheduler_tqm_delegate_for_test.cc new file mode 100644 index 0000000..4ff373f --- /dev/null +++ b/components/scheduler/child/scheduler_tqm_delegate_for_test.cc
@@ -0,0 +1,67 @@ +// Copyright 2015 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/scheduler/child/scheduler_tqm_delegate_for_test.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "components/scheduler/base/task_queue_manager_delegate_for_test.h" + +namespace scheduler { + +// static +scoped_refptr<SchedulerTqmDelegateForTest> SchedulerTqmDelegateForTest::Create( + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_ptr<base::TickClock> time_source) { + return make_scoped_refptr( + new SchedulerTqmDelegateForTest(task_runner, time_source.Pass())); +} + +SchedulerTqmDelegateForTest::SchedulerTqmDelegateForTest( + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_ptr<base::TickClock> time_source) + : task_runner_( + TaskQueueManagerDelegateForTest::Create(task_runner, + time_source.Pass())) {} + +SchedulerTqmDelegateForTest::~SchedulerTqmDelegateForTest() {} + +void SchedulerTqmDelegateForTest::SetDefaultTaskRunner( + scoped_refptr<base::SingleThreadTaskRunner> task_runner) { + default_task_runner_ = task_runner.Pass(); +} + +void SchedulerTqmDelegateForTest::RestoreDefaultTaskRunner() { + default_task_runner_ = nullptr; +} + +bool SchedulerTqmDelegateForTest::PostDelayedTask( + const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) { + return task_runner_->PostDelayedTask(from_here, task, delay); +} + +bool SchedulerTqmDelegateForTest::PostNonNestableDelayedTask( + const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) { + return task_runner_->PostNonNestableDelayedTask(from_here, task, delay); +} + +bool SchedulerTqmDelegateForTest::RunsTasksOnCurrentThread() const { + return task_runner_->RunsTasksOnCurrentThread(); +} + +bool SchedulerTqmDelegateForTest::IsNested() const { + return task_runner_->IsNested(); +} + +base::TimeTicks SchedulerTqmDelegateForTest::NowTicks() { + return task_runner_->NowTicks(); +} + +void SchedulerTqmDelegateForTest::OnNoMoreImmediateWork() {} + +} // namespace scheduler
diff --git a/components/scheduler/child/scheduler_tqm_delegate_for_test.h b/components/scheduler/child/scheduler_tqm_delegate_for_test.h new file mode 100644 index 0000000..2d9478f --- /dev/null +++ b/components/scheduler/child/scheduler_tqm_delegate_for_test.h
@@ -0,0 +1,58 @@ +// Copyright 2015 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 CONTENT_RENDERER_SCHEDULER_TQM_DELEGATE_FOR_TEST_H_ +#define CONTENT_RENDERER_SCHEDULER_TQM_DELEGATE_FOR_TEST_H_ + +#include "base/macros.h" +#include "base/test/simple_test_tick_clock.h" +#include "components/scheduler/child/scheduler_tqm_delegate.h" + +namespace scheduler { + +class TaskQueueManagerDelegateForTest; + +class SchedulerTqmDelegateForTest : public SchedulerTqmDelegate { + public: + static scoped_refptr<SchedulerTqmDelegateForTest> Create( + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_ptr<base::TickClock> time_source); + + // SchedulerTqmDelegate implementation + void SetDefaultTaskRunner( + scoped_refptr<base::SingleThreadTaskRunner> task_runner) override; + void RestoreDefaultTaskRunner() override; + bool PostDelayedTask(const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) override; + bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) override; + bool RunsTasksOnCurrentThread() const override; + bool IsNested() const override; + base::TimeTicks NowTicks() override; + void OnNoMoreImmediateWork() override; + + base::SingleThreadTaskRunner* default_task_runner() const { + return default_task_runner_.get(); + } + + protected: + ~SchedulerTqmDelegateForTest() override; + + private: + SchedulerTqmDelegateForTest( + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_ptr<base::TickClock> time_source); + + scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; + + scoped_refptr<TaskQueueManagerDelegateForTest> task_runner_; + + DISALLOW_COPY_AND_ASSIGN(SchedulerTqmDelegateForTest); +}; + +} // namespace scheduler + +#endif // CONTENT_RENDERER_SCHEDULER_TQM_DELEGATE_FOR_TEST_H_
diff --git a/components/scheduler/child/scheduler_tqm_delegate_impl.cc b/components/scheduler/child/scheduler_tqm_delegate_impl.cc new file mode 100644 index 0000000..8057d7e --- /dev/null +++ b/components/scheduler/child/scheduler_tqm_delegate_impl.cc
@@ -0,0 +1,67 @@ +// Copyright 2015 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/scheduler/child/scheduler_tqm_delegate_impl.h" + +namespace scheduler { + +// static +scoped_refptr<SchedulerTqmDelegateImpl> SchedulerTqmDelegateImpl::Create( + base::MessageLoop* message_loop, + scoped_ptr<base::TickClock> time_source) { + return make_scoped_refptr( + new SchedulerTqmDelegateImpl(message_loop, time_source.Pass())); +} + +SchedulerTqmDelegateImpl::SchedulerTqmDelegateImpl( + base::MessageLoop* message_loop, + scoped_ptr<base::TickClock> time_source) + : message_loop_(message_loop), + message_loop_task_runner_(message_loop->task_runner()), + time_source_(time_source.Pass()) {} + +SchedulerTqmDelegateImpl::~SchedulerTqmDelegateImpl() { + RestoreDefaultTaskRunner(); +} + +void SchedulerTqmDelegateImpl::SetDefaultTaskRunner( + scoped_refptr<base::SingleThreadTaskRunner> task_runner) { + message_loop_->SetTaskRunner(task_runner); +} + +void SchedulerTqmDelegateImpl::RestoreDefaultTaskRunner() { + if (base::MessageLoop::current() == message_loop_) + message_loop_->SetTaskRunner(message_loop_task_runner_); +} + +bool SchedulerTqmDelegateImpl::PostDelayedTask( + const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) { + return message_loop_task_runner_->PostDelayedTask(from_here, task, delay); +} + +bool SchedulerTqmDelegateImpl::PostNonNestableDelayedTask( + const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) { + return message_loop_task_runner_->PostNonNestableDelayedTask(from_here, task, + delay); +} + +bool SchedulerTqmDelegateImpl::RunsTasksOnCurrentThread() const { + return message_loop_task_runner_->RunsTasksOnCurrentThread(); +} + +bool SchedulerTqmDelegateImpl::IsNested() const { + return message_loop_->IsNested(); +} + +base::TimeTicks SchedulerTqmDelegateImpl::NowTicks() { + return time_source_->NowTicks(); +} + +void SchedulerTqmDelegateImpl::OnNoMoreImmediateWork() {} + +} // namespace scheduler
diff --git a/components/scheduler/child/scheduler_tqm_delegate_impl.h b/components/scheduler/child/scheduler_tqm_delegate_impl.h new file mode 100644 index 0000000..23c378c --- /dev/null +++ b/components/scheduler/child/scheduler_tqm_delegate_impl.h
@@ -0,0 +1,55 @@ +// Copyright 2015 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_SCHEDULER_CHILD_SCHEDULER_TQM_DELEGATE_IMPL_H_ +#define COMPONENTS_SCHEDULER_CHILD_SCHEDULER_TQM_DELEGATE_IMPL_H_ + +#include "base/macros.h" +#include "base/message_loop/message_loop.h" +#include "base/time/tick_clock.h" +#include "components/scheduler/child/scheduler_tqm_delegate.h" +#include "components/scheduler/scheduler_export.h" + +namespace scheduler { + +class SCHEDULER_EXPORT SchedulerTqmDelegateImpl : public SchedulerTqmDelegate { + public: + // |message_loop| is not owned and must outlive the lifetime of this object. + static scoped_refptr<SchedulerTqmDelegateImpl> Create( + base::MessageLoop* message_loop, + scoped_ptr<base::TickClock> time_source); + + // SchedulerTqmDelegate implementation + void SetDefaultTaskRunner( + scoped_refptr<base::SingleThreadTaskRunner> task_runner) override; + void RestoreDefaultTaskRunner() override; + bool PostDelayedTask(const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) override; + bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) override; + bool RunsTasksOnCurrentThread() const override; + bool IsNested() const override; + base::TimeTicks NowTicks() override; + void OnNoMoreImmediateWork() override; + + protected: + ~SchedulerTqmDelegateImpl() override; + + private: + SchedulerTqmDelegateImpl(base::MessageLoop* message_loop, + scoped_ptr<base::TickClock> time_source); + + // Not owned. + base::MessageLoop* message_loop_; + scoped_refptr<SingleThreadTaskRunner> message_loop_task_runner_; + scoped_ptr<base::TickClock> time_source_; + + DISALLOW_COPY_AND_ASSIGN(SchedulerTqmDelegateImpl); +}; + +} // namespace scheduler + +#endif // COMPONENTS_SCHEDULER_CHILD_SCHEDULER_TQM_DELEGATE_IMPL_H_
diff --git a/components/scheduler/child/scheduler_tqm_delegate_impl_unittest.cc b/components/scheduler/child/scheduler_tqm_delegate_impl_unittest.cc new file mode 100644 index 0000000..2b91064 --- /dev/null +++ b/components/scheduler/child/scheduler_tqm_delegate_impl_unittest.cc
@@ -0,0 +1,30 @@ +// Copyright 2015 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/scheduler/child/scheduler_tqm_delegate_impl.h" + +#include "base/message_loop/message_loop.h" +#include "base/test/test_simple_task_runner.h" +#include "base/time/default_tick_clock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace scheduler { + +TEST(SchedulerTqmDelegateImplTest, TestTaskRunnerOverriding) { + base::MessageLoop loop; + scoped_refptr<base::SingleThreadTaskRunner> original_runner( + loop.task_runner()); + scoped_refptr<base::SingleThreadTaskRunner> custom_runner( + new base::TestSimpleTaskRunner()); + { + scoped_refptr<SchedulerTqmDelegateImpl> delegate( + SchedulerTqmDelegateImpl::Create( + &loop, make_scoped_ptr(new base::DefaultTickClock()))); + delegate->SetDefaultTaskRunner(custom_runner); + DCHECK_EQ(custom_runner, loop.task_runner()); + } + DCHECK_EQ(original_runner, loop.task_runner()); +} + +} // namespace scheduler
diff --git a/components/scheduler/child/virtual_time_tqm_delegate.cc b/components/scheduler/child/virtual_time_tqm_delegate.cc new file mode 100644 index 0000000..2d7399f --- /dev/null +++ b/components/scheduler/child/virtual_time_tqm_delegate.cc
@@ -0,0 +1,89 @@ +// Copyright 2015 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/scheduler/child/virtual_time_tqm_delegate.h" + +namespace scheduler { + +// static +scoped_refptr<VirtualTimeTqmDelegate> VirtualTimeTqmDelegate::Create( + base::MessageLoop* message_loop, + base::TimeTicks initial_now) { + return make_scoped_refptr( + new VirtualTimeTqmDelegate(message_loop, initial_now)); +} + +VirtualTimeTqmDelegate::VirtualTimeTqmDelegate(base::MessageLoop* message_loop, + base::TimeTicks initial_now) + : message_loop_(message_loop), + message_loop_task_runner_(message_loop->task_runner()), + now_(initial_now) {} + +VirtualTimeTqmDelegate::~VirtualTimeTqmDelegate() { + RestoreDefaultTaskRunner(); +} + +void VirtualTimeTqmDelegate::SetDefaultTaskRunner( + scoped_refptr<base::SingleThreadTaskRunner> task_runner) { + message_loop_->SetTaskRunner(task_runner); +} + +void VirtualTimeTqmDelegate::RestoreDefaultTaskRunner() { + if (base::MessageLoop::current() == message_loop_) + message_loop_->SetTaskRunner(message_loop_task_runner_); +} + +bool VirtualTimeTqmDelegate::PostDelayedTask( + const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) { + if (delay > base::TimeDelta()) { + base::TimeTicks fire_time = now_ + delay; + delayed_wakeup_multimap_.insert(std::make_pair(fire_time, task)); + } + return message_loop_task_runner_->PostDelayedTask(from_here, task, delay); +} + +bool VirtualTimeTqmDelegate::PostNonNestableDelayedTask( + const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) { + return message_loop_task_runner_->PostNonNestableDelayedTask(from_here, task, + delay); +} + +bool VirtualTimeTqmDelegate::RunsTasksOnCurrentThread() const { + return message_loop_task_runner_->RunsTasksOnCurrentThread(); +} + +bool VirtualTimeTqmDelegate::IsNested() const { + return message_loop_->IsNested(); +} + +base::TimeTicks VirtualTimeTqmDelegate::NowTicks() { + return now_; +} + +void VirtualTimeTqmDelegate::AdvancedTimeTo(base::TimeTicks now) { + now_ = now; + DCHECK_GE(now, now_); + while (!delayed_wakeup_multimap_.empty()) { + DelayedWakeupMultimap::iterator next_wakeup = + delayed_wakeup_multimap_.begin(); + if (next_wakeup->first > now) + break; + message_loop_task_runner_->PostDelayedTask(FROM_HERE, next_wakeup->second, + base::TimeDelta()); + delayed_wakeup_multimap_.erase(next_wakeup); + } +} + +void VirtualTimeTqmDelegate::OnNoMoreImmediateWork() { + if (delayed_wakeup_multimap_.empty()) + return; + + AdvancedTimeTo(delayed_wakeup_multimap_.begin()->first); +} + +} // namespace scheduler
diff --git a/components/scheduler/child/virtual_time_tqm_delegate.h b/components/scheduler/child/virtual_time_tqm_delegate.h new file mode 100644 index 0000000..ba0302a --- /dev/null +++ b/components/scheduler/child/virtual_time_tqm_delegate.h
@@ -0,0 +1,63 @@ +// Copyright 2015 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_SCHEDULER_CHILD_VIRTUAL_TIME_TQM_DELEGATE_H_ +#define COMPONENTS_SCHEDULER_CHILD_VIRTUAL_TIME_TQM_DELEGATE_H_ + +#include <map> + +#include "base/macros.h" +#include "base/message_loop/message_loop.h" +#include "base/time/tick_clock.h" +#include "components/scheduler/child/scheduler_tqm_delegate.h" +#include "components/scheduler/scheduler_export.h" + +namespace scheduler { + +class SCHEDULER_EXPORT VirtualTimeTqmDelegate : public SchedulerTqmDelegate { + public: + // |message_loop| is not owned and must outlive the lifetime of this object. + static scoped_refptr<VirtualTimeTqmDelegate> Create( + base::MessageLoop* message_loop, + base::TimeTicks initial_now); + + // SchedulerTqmDelegate implementation + void SetDefaultTaskRunner( + scoped_refptr<base::SingleThreadTaskRunner> task_runner) override; + void RestoreDefaultTaskRunner() override; + bool PostDelayedTask(const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) override; + bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) override; + bool RunsTasksOnCurrentThread() const override; + bool IsNested() const override; + base::TimeTicks NowTicks() override; + void OnNoMoreImmediateWork() override; + + protected: + ~VirtualTimeTqmDelegate() override; + + private: + explicit VirtualTimeTqmDelegate(base::MessageLoop* message_loop, + base::TimeTicks initial_no); + + void AdvancedTimeTo(base::TimeTicks now); + + typedef std::multimap<base::TimeTicks, base::Closure> DelayedWakeupMultimap; + + DelayedWakeupMultimap delayed_wakeup_multimap_; + + // Not owned. + base::MessageLoop* message_loop_; + scoped_refptr<SingleThreadTaskRunner> message_loop_task_runner_; + base::TimeTicks now_; + + DISALLOW_COPY_AND_ASSIGN(VirtualTimeTqmDelegate); +}; + +} // namespace scheduler + +#endif // COMPONENTS_SCHEDULER_CHILD_VIRTUAL_TIME_TQM_DELEGATE_H_
diff --git a/components/scheduler/child/virtual_time_tqm_delegate_unittest.cc b/components/scheduler/child/virtual_time_tqm_delegate_unittest.cc new file mode 100644 index 0000000..8d7e6ab --- /dev/null +++ b/components/scheduler/child/virtual_time_tqm_delegate_unittest.cc
@@ -0,0 +1,54 @@ +// Copyright 2015 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/scheduler/child/virtual_time_tqm_delegate.h" + +#include "base/bind.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace scheduler { + +class VirtualTimeTqmDelegateTest : public testing::Test { + public: + VirtualTimeTqmDelegateTest() {} + + ~VirtualTimeTqmDelegateTest() override {} + + void SetUp() override { + message_loop_.reset(new base::MessageLoop()); + initial_time_ = base::TimeTicks() + base::TimeDelta::FromSeconds(100); + virtual_time_tqm_delegate_ = + VirtualTimeTqmDelegate::Create(message_loop_.get(), initial_time_); + } + + base::TimeTicks initial_time_; + scoped_ptr<base::MessageLoop> message_loop_; + + scoped_refptr<VirtualTimeTqmDelegate> virtual_time_tqm_delegate_; +}; + +namespace { +void TestFunc(bool* run) { + *run = true; +} +} + +TEST_F(VirtualTimeTqmDelegateTest, OnNoMoreImmediateWork_TimersFastForward) { + bool was_run = false; + virtual_time_tqm_delegate_->PostDelayedTask(FROM_HERE, + base::Bind(TestFunc, &was_run), + base::TimeDelta::FromSeconds(1)); + + EXPECT_EQ(initial_time_, virtual_time_tqm_delegate_->NowTicks()); + + virtual_time_tqm_delegate_->OnNoMoreImmediateWork(); + + EXPECT_EQ(initial_time_ + base::TimeDelta::FromSeconds(1), + virtual_time_tqm_delegate_->NowTicks()); + + message_loop_->RunUntilIdle(); + EXPECT_TRUE(was_run); +} + +} // namespace scheduler
diff --git a/components/scheduler/child/webthread_impl_for_worker_scheduler.cc b/components/scheduler/child/webthread_impl_for_worker_scheduler.cc index 0706d53e..8cd69b80 100644 --- a/components/scheduler/child/webthread_impl_for_worker_scheduler.cc +++ b/components/scheduler/child/webthread_impl_for_worker_scheduler.cc
@@ -8,8 +8,9 @@ #include "base/location.h" #include "base/single_thread_task_runner.h" #include "base/synchronization/waitable_event.h" +#include "base/time/default_tick_clock.h" #include "components/scheduler/base/task_queue.h" -#include "components/scheduler/child/scheduler_task_runner_delegate_impl.h" +#include "components/scheduler/child/scheduler_tqm_delegate_impl.h" #include "components/scheduler/child/web_scheduler_impl.h" #include "components/scheduler/child/web_task_runner_impl.h" #include "components/scheduler/child/worker_scheduler_impl.h" @@ -43,8 +44,10 @@ void WebThreadImplForWorkerScheduler::InitOnThread( base::WaitableEvent* completion) { - task_runner_delegate_ = - SchedulerTaskRunnerDelegateImpl::Create(thread_->message_loop()); + // TODO(alexclarke): Do we need to unify virtual time for workers and the + // main thread? + task_runner_delegate_ = SchedulerTqmDelegateImpl::Create( + thread_->message_loop(), make_scoped_ptr(new base::DefaultTickClock())); worker_scheduler_ = WorkerScheduler::Create(task_runner_delegate_); worker_scheduler_->Init(); task_runner_ = worker_scheduler_->DefaultTaskRunner();
diff --git a/components/scheduler/child/webthread_impl_for_worker_scheduler.h b/components/scheduler/child/webthread_impl_for_worker_scheduler.h index f6ab21f..5075313 100644 --- a/components/scheduler/child/webthread_impl_for_worker_scheduler.h +++ b/components/scheduler/child/webthread_impl_for_worker_scheduler.h
@@ -17,7 +17,7 @@ }; namespace scheduler { -class SchedulerTaskRunnerDelegate; +class SchedulerTqmDelegate; class SingleThreadIdleTaskRunner; class WebSchedulerImpl; class WebTaskRunnerImpl; @@ -57,7 +57,7 @@ scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; scoped_refptr<scheduler::SingleThreadIdleTaskRunner> idle_task_runner_; - scoped_refptr<SchedulerTaskRunnerDelegate> task_runner_delegate_; + scoped_refptr<SchedulerTqmDelegate> task_runner_delegate_; scoped_ptr<WebTaskRunnerImpl> web_task_runner_; };
diff --git a/components/scheduler/child/worker_scheduler.cc b/components/scheduler/child/worker_scheduler.cc index 55db90dcd..18f6cec 100644 --- a/components/scheduler/child/worker_scheduler.cc +++ b/components/scheduler/child/worker_scheduler.cc
@@ -5,7 +5,7 @@ #include "components/scheduler/child/worker_scheduler.h" #include "base/message_loop/message_loop.h" -#include "components/scheduler/child/scheduler_task_runner_delegate.h" +#include "components/scheduler/child/scheduler_tqm_delegate.h" #include "components/scheduler/child/worker_scheduler_impl.h" namespace scheduler { @@ -18,7 +18,7 @@ // static scoped_ptr<WorkerScheduler> WorkerScheduler::Create( - scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner) { + scoped_refptr<SchedulerTqmDelegate> main_task_runner) { return make_scoped_ptr(new WorkerSchedulerImpl(main_task_runner.Pass())); }
diff --git a/components/scheduler/child/worker_scheduler.h b/components/scheduler/child/worker_scheduler.h index 7a1ec046..a6163b6 100644 --- a/components/scheduler/child/worker_scheduler.h +++ b/components/scheduler/child/worker_scheduler.h
@@ -15,13 +15,13 @@ } namespace scheduler { -class SchedulerTaskRunnerDelegate; +class SchedulerTqmDelegate; class SCHEDULER_EXPORT WorkerScheduler : public ChildScheduler { public: ~WorkerScheduler() override; static scoped_ptr<WorkerScheduler> Create( - scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner); + scoped_refptr<SchedulerTqmDelegate> main_task_runner); // Must be called before the scheduler can be used. Does any post construction // initialization needed such as initializing idle period detection.
diff --git a/components/scheduler/child/worker_scheduler_impl.cc b/components/scheduler/child/worker_scheduler_impl.cc index 673d447..e74328d 100644 --- a/components/scheduler/child/worker_scheduler_impl.cc +++ b/components/scheduler/child/worker_scheduler_impl.cc
@@ -8,12 +8,12 @@ #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "components/scheduler/base/task_queue.h" -#include "components/scheduler/child/scheduler_task_runner_delegate.h" +#include "components/scheduler/child/scheduler_tqm_delegate.h" namespace scheduler { WorkerSchedulerImpl::WorkerSchedulerImpl( - scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner) + scoped_refptr<SchedulerTqmDelegate> main_task_runner) : helper_(main_task_runner, "worker.scheduler", TRACE_DISABLED_BY_DEFAULT("worker.scheduler"),
diff --git a/components/scheduler/child/worker_scheduler_impl.h b/components/scheduler/child/worker_scheduler_impl.h index 65fee339..e854cc9 100644 --- a/components/scheduler/child/worker_scheduler_impl.h +++ b/components/scheduler/child/worker_scheduler_impl.h
@@ -18,13 +18,13 @@ namespace scheduler { -class SchedulerTaskRunnerDelegate; +class SchedulerTqmDelegate; class SCHEDULER_EXPORT WorkerSchedulerImpl : public WorkerScheduler, public IdleHelper::Delegate { public: explicit WorkerSchedulerImpl( - scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner); + scoped_refptr<SchedulerTqmDelegate> main_task_runner); ~WorkerSchedulerImpl() override; // WorkerScheduler implementation:
diff --git a/components/scheduler/child/worker_scheduler_impl_unittest.cc b/components/scheduler/child/worker_scheduler_impl_unittest.cc index 47e0c68..06792d4 100644 --- a/components/scheduler/child/worker_scheduler_impl_unittest.cc +++ b/components/scheduler/child/worker_scheduler_impl_unittest.cc
@@ -9,7 +9,7 @@ #include "base/test/simple_test_tick_clock.h" #include "cc/test/ordered_simple_task_runner.h" #include "components/scheduler/base/test_time_source.h" -#include "components/scheduler/child/scheduler_task_runner_delegate_for_test.h" +#include "components/scheduler/child/scheduler_tqm_delegate_for_test.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -53,7 +53,7 @@ class WorkerSchedulerImplForTest : public WorkerSchedulerImpl { public: WorkerSchedulerImplForTest( - scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner, + scoped_refptr<SchedulerTqmDelegate> main_task_runner, base::SimpleTestTickClock* clock_) : WorkerSchedulerImpl(main_task_runner), clock_(clock_), @@ -92,18 +92,13 @@ WorkerSchedulerImplTest() : clock_(new base::SimpleTestTickClock()), mock_task_runner_(new cc::OrderedSimpleTaskRunner(clock_.get(), true)), - main_task_runner_( - SchedulerTaskRunnerDelegateForTest::Create(mock_task_runner_)), + main_task_runner_(SchedulerTqmDelegateForTest::Create( + mock_task_runner_, + make_scoped_ptr(new TestTimeSource(clock_.get())))), scheduler_( new WorkerSchedulerImplForTest(main_task_runner_, clock_.get())), timeline_(nullptr) { clock_->Advance(base::TimeDelta::FromMicroseconds(5000)); - scheduler_->GetSchedulerHelperForTesting()->SetTimeSourceForTesting( - make_scoped_ptr(new TestTimeSource(clock_.get()))); - scheduler_->GetSchedulerHelperForTesting() - ->GetTaskQueueManagerForTesting() - ->SetTimeSourceForTesting( - make_scoped_ptr(new TestTimeSource(clock_.get()))); } ~WorkerSchedulerImplTest() override {} @@ -175,7 +170,7 @@ // Only one of mock_task_runner_ or message_loop_ will be set. scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_; - scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner_; + scoped_refptr<SchedulerTqmDelegate> main_task_runner_; scoped_ptr<WorkerSchedulerImplForTest> scheduler_; scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
diff --git a/components/scheduler/common/scheduler_switches.cc b/components/scheduler/common/scheduler_switches.cc new file mode 100644 index 0000000..8ea8fe9 --- /dev/null +++ b/components/scheduler/common/scheduler_switches.cc
@@ -0,0 +1,16 @@ +// Copyright 2015 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/scheduler/common/scheduler_switches.h" + +namespace scheduler { +namespace switches { + +// Enable Virtualized time where the render thread's time source skips forward +// to the next scheduled delayed time if there is no more non-delayed work to be +// done. +const char kEnableVirtualizedTime[] = "enable-virtualized-time"; + +} // namespace switches +} // namespace scheduler
diff --git a/components/scheduler/common/scheduler_switches.h b/components/scheduler/common/scheduler_switches.h new file mode 100644 index 0000000..2a8cb0cb --- /dev/null +++ b/components/scheduler/common/scheduler_switches.h
@@ -0,0 +1,16 @@ +// Copyright 2015 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_SCHEDULER_COMMON_SCHEDULER_SWITCHES_H_ +#define COMPONENTS_SCHEDULER_COMMON_SCHEDULER_SWITCHES_H_ + +namespace scheduler { +namespace switches { + +extern const char kEnableVirtualizedTime[]; + +} // namespace switches +} // namespace scheduler + +#endif // COMPONENTS_SCHEDULER_COMMON_SCHEDULER_SWITCHES_H_
diff --git a/components/scheduler/ppapi/webthread_impl_for_ppapi.cc b/components/scheduler/ppapi/webthread_impl_for_ppapi.cc index 113efdc..d657fd3 100644 --- a/components/scheduler/ppapi/webthread_impl_for_ppapi.cc +++ b/components/scheduler/ppapi/webthread_impl_for_ppapi.cc
@@ -7,8 +7,9 @@ #include "base/bind.h" #include "base/location.h" #include "base/single_thread_task_runner.h" +#include "base/time/default_tick_clock.h" #include "components/scheduler/base/task_queue.h" -#include "components/scheduler/child/scheduler_task_runner_delegate_impl.h" +#include "components/scheduler/child/scheduler_tqm_delegate_impl.h" #include "components/scheduler/child/web_scheduler_impl.h" #include "components/scheduler/child/web_task_runner_impl.h" #include "components/scheduler/child/worker_scheduler_impl.h" @@ -17,8 +18,9 @@ WebThreadImplForPPAPI::WebThreadImplForPPAPI() : thread_id_(base::PlatformThread::CurrentId()), - task_runner_delegate_(SchedulerTaskRunnerDelegateImpl::Create( - base::MessageLoop::current())), + task_runner_delegate_(SchedulerTqmDelegateImpl::Create( + base::MessageLoop::current(), + make_scoped_ptr(new base::DefaultTickClock()))), worker_scheduler_(WorkerScheduler::Create(task_runner_delegate_)) { worker_scheduler_->Init(); task_runner_ = worker_scheduler_->DefaultTaskRunner();
diff --git a/components/scheduler/ppapi/webthread_impl_for_ppapi.h b/components/scheduler/ppapi/webthread_impl_for_ppapi.h index d85c02a..426f321 100644 --- a/components/scheduler/ppapi/webthread_impl_for_ppapi.h +++ b/components/scheduler/ppapi/webthread_impl_for_ppapi.h
@@ -16,7 +16,7 @@ }; namespace scheduler { -class SchedulerTaskRunnerDelegate; +class SchedulerTqmDelegate; class SingleThreadIdleTaskRunner; class WebSchedulerImpl; class WebTaskRunnerImpl; @@ -43,7 +43,7 @@ base::MessageLoop::TaskObserver* observer) override; blink::PlatformThreadId thread_id_; - scoped_refptr<SchedulerTaskRunnerDelegate> task_runner_delegate_; + scoped_refptr<SchedulerTqmDelegate> task_runner_delegate_; scoped_ptr<scheduler::WorkerScheduler> worker_scheduler_; scoped_ptr<scheduler::WebSchedulerImpl> web_scheduler_; scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner_;
diff --git a/components/scheduler/renderer/DEPS b/components/scheduler/renderer/DEPS index 2f3b2d4..66d5d999 100644 --- a/components/scheduler/renderer/DEPS +++ b/components/scheduler/renderer/DEPS
@@ -1,6 +1,7 @@ include_rules = [ "+components/scheduler/base", "+components/scheduler/child", + "+components/scheduler/common", "+components/scheduler/scheduler_export.h", "+cc/base", "+cc/output",
diff --git a/components/scheduler/renderer/idle_time_estimator.cc b/components/scheduler/renderer/idle_time_estimator.cc index 52e72da..30c91561 100644 --- a/components/scheduler/renderer/idle_time_estimator.cc +++ b/components/scheduler/renderer/idle_time_estimator.cc
@@ -10,11 +10,12 @@ IdleTimeEstimator::IdleTimeEstimator( const scoped_refptr<TaskQueue>& compositor_task_runner, + base::TickClock* time_source, int sample_count, double estimation_percentile) : compositor_task_runner_(compositor_task_runner), per_frame_compositor_task_runtime_(sample_count), - time_source_(new base::DefaultTickClock), + time_source_(time_source), estimation_percentile_(estimation_percentile), nesting_level_(0), did_commit_(false) { @@ -48,11 +49,6 @@ did_commit_ = false; } -void IdleTimeEstimator::SetTimeSourceForTesting( - scoped_ptr<base::TickClock> time_source) { - time_source_ = time_source.Pass(); -} - void IdleTimeEstimator::WillProcessTask(const base::PendingTask& pending_task) { nesting_level_++; if (nesting_level_ == 1)
diff --git a/components/scheduler/renderer/idle_time_estimator.h b/components/scheduler/renderer/idle_time_estimator.h index eb9eee3..af00fbb 100644 --- a/components/scheduler/renderer/idle_time_estimator.h +++ b/components/scheduler/renderer/idle_time_estimator.h
@@ -18,6 +18,7 @@ : public base::MessageLoop::TaskObserver { public: IdleTimeEstimator(const scoped_refptr<TaskQueue>& compositor_task_runner, + base::TickClock* time_source, int sample_count, double estimation_percentile); @@ -36,12 +37,10 @@ void WillProcessTask(const base::PendingTask& pending_task) override; void DidProcessTask(const base::PendingTask& pending_task) override; - void SetTimeSourceForTesting(scoped_ptr<base::TickClock> time_source); - private: scoped_refptr<TaskQueue> compositor_task_runner_; cc::RollingTimeDeltaHistory per_frame_compositor_task_runtime_; - scoped_ptr<base::TickClock> time_source_; + base::TickClock* time_source_; // NOT OWNED double estimation_percentile_; base::TimeTicks task_start_time_;
diff --git a/components/scheduler/renderer/idle_time_estimator_unittest.cc b/components/scheduler/renderer/idle_time_estimator_unittest.cc index 695be80..99105cc 100644 --- a/components/scheduler/renderer/idle_time_estimator_unittest.cc +++ b/components/scheduler/renderer/idle_time_estimator_unittest.cc
@@ -8,7 +8,7 @@ #include "cc/test/ordered_simple_task_runner.h" #include "components/scheduler/base/task_queue_manager.h" #include "components/scheduler/base/test_time_source.h" -#include "components/scheduler/child/scheduler_task_runner_delegate_for_test.h" +#include "components/scheduler/child/scheduler_tqm_delegate_for_test.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -18,14 +18,13 @@ public: IdleTimeEstimatorForTest( const scoped_refptr<TaskQueue>& compositor_task_runner, - base::SimpleTestTickClock* clock, + TestTimeSource* test_time_source, int sample_count, double estimation_percentile) : IdleTimeEstimator(compositor_task_runner, + test_time_source, sample_count, - estimation_percentile) { - SetTimeSourceForTesting(make_scoped_ptr(new TestTimeSource(clock))); - } + estimation_percentile) {} }; class IdleTimeEstimatorTest : public testing::Test { @@ -38,17 +37,18 @@ void SetUp() override { clock_.reset(new base::SimpleTestTickClock()); clock_->Advance(base::TimeDelta::FromMicroseconds(5000)); + test_time_source_.reset(new TestTimeSource(clock_.get())); mock_task_runner_ = make_scoped_refptr( new cc::OrderedSimpleTaskRunner(clock_.get(), false)); - main_task_runner_ = - SchedulerTaskRunnerDelegateForTest::Create(mock_task_runner_); + main_task_runner_ = SchedulerTqmDelegateForTest::Create( + mock_task_runner_, make_scoped_ptr(new TestTimeSource(clock_.get()))); manager_ = make_scoped_ptr(new TaskQueueManager( main_task_runner_, "test.scheduler", "test.scheduler", "test.scheduler.debug")); compositor_task_runner_ = manager_->NewTaskQueue(TaskQueue::Spec("compositor_tq")); - estimator_.reset(new IdleTimeEstimatorForTest(compositor_task_runner_, - clock_.get(), 10, 50)); + estimator_.reset(new IdleTimeEstimatorForTest( + compositor_task_runner_, test_time_source_.get(), 10, 50)); } void SimulateFrameWithOneCompositorTask(int compositor_time) { @@ -84,8 +84,9 @@ } scoped_ptr<base::SimpleTestTickClock> clock_; + scoped_ptr<TestTimeSource> test_time_source_; scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_; - scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner_; + scoped_refptr<SchedulerTqmDelegate> main_task_runner_; scoped_ptr<TaskQueueManager> manager_; scoped_refptr<TaskQueue> compositor_task_runner_; scoped_ptr<IdleTimeEstimatorForTest> estimator_;
diff --git a/components/scheduler/renderer/renderer_scheduler.cc b/components/scheduler/renderer/renderer_scheduler.cc index 20d66343..8a32b8b 100644 --- a/components/scheduler/renderer/renderer_scheduler.cc +++ b/components/scheduler/renderer/renderer_scheduler.cc
@@ -4,10 +4,14 @@ #include "components/scheduler/renderer/renderer_scheduler.h" +#include "base/command_line.h" #include "base/message_loop/message_loop.h" +#include "base/time/default_tick_clock.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_impl.h" -#include "components/scheduler/child/scheduler_task_runner_delegate_impl.h" +#include "components/scheduler/child/scheduler_tqm_delegate_impl.h" +#include "components/scheduler/child/virtual_time_tqm_delegate.h" +#include "components/scheduler/common/scheduler_switches.h" #include "components/scheduler/renderer/renderer_scheduler_impl.h" namespace scheduler { @@ -30,8 +34,15 @@ TRACE_DISABLED_BY_DEFAULT("renderer.scheduler.debug")); base::MessageLoop* message_loop = base::MessageLoop::current(); - return make_scoped_ptr(new RendererSchedulerImpl( - SchedulerTaskRunnerDelegateImpl::Create(message_loop))); + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kEnableVirtualizedTime)) { + return make_scoped_ptr(new RendererSchedulerImpl( + VirtualTimeTqmDelegate::Create(message_loop, base::TimeTicks::Now()))); + } else { + return make_scoped_ptr( + new RendererSchedulerImpl(SchedulerTqmDelegateImpl::Create( + message_loop, make_scoped_ptr(new base::DefaultTickClock())))); + } } // static
diff --git a/components/scheduler/renderer/renderer_scheduler_impl.cc b/components/scheduler/renderer/renderer_scheduler_impl.cc index 24f98749..d9aee6d 100644 --- a/components/scheduler/renderer/renderer_scheduler_impl.cc +++ b/components/scheduler/renderer/renderer_scheduler_impl.cc
@@ -6,12 +6,13 @@ #include "base/bind.h" #include "base/debug/stack_trace.h" +#include "base/logging.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "cc/output/begin_frame_args.h" #include "components/scheduler/base/task_queue_impl.h" #include "components/scheduler/base/task_queue_selector.h" -#include "components/scheduler/child/scheduler_task_runner_delegate.h" +#include "components/scheduler/child/scheduler_tqm_delegate.h" namespace scheduler { namespace { @@ -28,7 +29,7 @@ } RendererSchedulerImpl::RendererSchedulerImpl( - scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner) + scoped_refptr<SchedulerTqmDelegate> main_task_runner) : helper_(main_task_runner, "renderer.scheduler", TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), @@ -48,7 +49,7 @@ base::Bind(&RendererSchedulerImpl::UpdatePolicy, base::Unretained(this)), helper_.ControlTaskRunner()), - main_thread_only_(compositor_task_runner_), + main_thread_only_(compositor_task_runner_, helper_.tick_clock()), policy_may_need_update_(&any_thread_lock_), weak_factory_(this) { update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, @@ -97,12 +98,16 @@ default_queue_priority(TaskQueue::NORMAL_PRIORITY) {} RendererSchedulerImpl::MainThreadOnly::MainThreadOnly( - const scoped_refptr<TaskQueue>& compositor_task_runner) - : loading_task_cost_estimator(kLoadingTaskEstimationSampleCount, + const scoped_refptr<TaskQueue>& compositor_task_runner, + base::TickClock* time_source) + : loading_task_cost_estimator(time_source, + kLoadingTaskEstimationSampleCount, kLoadingTaskEstimationPercentile), - timer_task_cost_estimator(kTimerTaskEstimationSampleCount, + timer_task_cost_estimator(time_source, + kTimerTaskEstimationSampleCount, kTimerTaskEstimationPercentile), idle_time_estimator(compositor_task_runner, + time_source, kShortIdlePeriodDurationSampleCount, kShortIdlePeriodDurationPercentile), current_use_case(UseCase::NONE), @@ -245,7 +250,7 @@ if (helper_.IsShutdown()) return; - base::TimeTicks now(helper_.Now()); + base::TimeTicks now(helper_.tick_clock()->NowTicks()); if (now < MainThreadOnly().estimated_next_frame_begin) { // TODO(rmcilroy): Consider reducing the idle period based on the runtime of // the next pending delayed tasks (as currently done in for long idle times) @@ -302,7 +307,7 @@ // TODO(alexclarke): Should we update policy here? TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", - this, AsValue(helper_.Now())); + this, AsValue(helper_.tick_clock()->NowTicks())); } void RendererSchedulerImpl::SetHasVisibleRenderWidgetWithTouchHandler( @@ -402,7 +407,7 @@ blink::WebInputEvent::Type type, InputEventState input_event_state) { base::AutoLock lock(any_thread_lock_); - base::TimeTicks now = helper_.Now(); + base::TimeTicks now = helper_.tick_clock()->NowTicks(); // TODO(alexclarke): Move WebInputEventTraits where we can access it from here // and record the name rather than the integer representation. @@ -470,7 +475,8 @@ helper_.CheckOnValidThread(); if (ShouldPrioritizeInputEvent(web_input_event)) { base::AutoLock lock(any_thread_lock_); - AnyThread().user_model.DidFinishProcessingInputEvent(helper_.Now()); + AnyThread().user_model.DidFinishProcessingInputEvent( + helper_.tick_clock()->NowTicks()); } } @@ -561,7 +567,7 @@ if (helper_.IsShutdown()) return; - base::TimeTicks now = helper_.Now(); + base::TimeTicks now = helper_.tick_clock()->NowTicks(); policy_may_need_update_.SetWhileLocked(false); base::TimeDelta expected_use_case_duration; @@ -835,7 +841,7 @@ any_thread_lock_.AssertAcquired(); if (optional_now.is_null()) - optional_now = helper_.Now(); + optional_now = helper_.tick_clock()->NowTicks(); scoped_refptr<base::trace_event::TracedValue> state = new base::trace_event::TracedValue(); @@ -907,7 +913,7 @@ void RendererSchedulerImpl::OnIdlePeriodEnded() { base::AutoLock lock(any_thread_lock_); - AnyThread().last_idle_period_end_time = helper_.Now(); + AnyThread().last_idle_period_end_time = helper_.tick_clock()->NowTicks(); AnyThread().in_idle_period = false; UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED); } @@ -931,8 +937,9 @@ "RendererSchedulerImpl::OnNavigationStarted"); base::AutoLock lock(any_thread_lock_); AnyThread().rails_loading_priority_deadline = - helper_.Now() + base::TimeDelta::FromMilliseconds( - kRailsInitialLoadingPrioritizationMillis); + helper_.tick_clock()->NowTicks() + + base::TimeDelta::FromMilliseconds( + kRailsInitialLoadingPrioritizationMillis); ResetForNavigationLocked(); } @@ -966,7 +973,7 @@ MainThreadOnly().loading_task_cost_estimator.Clear(); MainThreadOnly().timer_task_cost_estimator.Clear(); MainThreadOnly().idle_time_estimator.Clear(); - AnyThread().user_model.Reset(helper_.Now()); + AnyThread().user_model.Reset(helper_.tick_clock()->NowTicks()); MainThreadOnly().have_seen_a_begin_main_frame = false; UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED); }
diff --git a/components/scheduler/renderer/renderer_scheduler_impl.h b/components/scheduler/renderer/renderer_scheduler_impl.h index d137b16..70f2eaa 100644 --- a/components/scheduler/renderer/renderer_scheduler_impl.h +++ b/components/scheduler/renderer/renderer_scheduler_impl.h
@@ -33,8 +33,7 @@ public SchedulerHelper::Observer, public RenderWidgetSignals::Observer { public: - RendererSchedulerImpl( - scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner); + RendererSchedulerImpl(scoped_refptr<SchedulerTqmDelegate> main_task_runner); ~RendererSchedulerImpl() override; // RendererScheduler implementation: @@ -245,8 +244,8 @@ // (the accessors) for the following data members. struct MainThreadOnly { - explicit MainThreadOnly( - const scoped_refptr<TaskQueue>& compositor_task_runner); + MainThreadOnly(const scoped_refptr<TaskQueue>& compositor_task_runner, + base::TickClock* time_source); ~MainThreadOnly(); TaskCostEstimator loading_task_cost_estimator;
diff --git a/components/scheduler/renderer/renderer_scheduler_impl_unittest.cc b/components/scheduler/renderer/renderer_scheduler_impl_unittest.cc index 2382399..2cff5ac 100644 --- a/components/scheduler/renderer/renderer_scheduler_impl_unittest.cc +++ b/components/scheduler/renderer/renderer_scheduler_impl_unittest.cc
@@ -9,8 +9,8 @@ #include "cc/output/begin_frame_args.h" #include "cc/test/ordered_simple_task_runner.h" #include "components/scheduler/base/test_time_source.h" -#include "components/scheduler/child/scheduler_task_runner_delegate_for_test.h" -#include "components/scheduler/child/scheduler_task_runner_delegate_impl.h" +#include "components/scheduler/child/scheduler_tqm_delegate_for_test.h" +#include "components/scheduler/child/scheduler_tqm_delegate_impl.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -178,7 +178,7 @@ using RendererSchedulerImpl::OnIdlePeriodStarted; RendererSchedulerImplForTest( - scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner) + scoped_refptr<SchedulerTqmDelegate> main_task_runner) : RendererSchedulerImpl(main_task_runner), update_policy_count_(0) {} void UpdatePolicyLocked(UpdateType update_type) override { @@ -236,13 +236,14 @@ void SetUp() override { if (message_loop_) { - main_task_runner_ = - SchedulerTaskRunnerDelegateImpl::Create(message_loop_.get()); + main_task_runner_ = SchedulerTqmDelegateImpl::Create( + message_loop_.get(), + make_scoped_ptr(new TestTimeSource(clock_.get()))); } else { mock_task_runner_ = make_scoped_refptr( new cc::OrderedSimpleTaskRunner(clock_.get(), false)); - main_task_runner_ = - SchedulerTaskRunnerDelegateForTest::Create(mock_task_runner_); + main_task_runner_ = SchedulerTqmDelegateForTest::Create( + mock_task_runner_, make_scoped_ptr(new TestTimeSource(clock_.get()))); } Initialize( make_scoped_ptr(new RendererSchedulerImplForTest(main_task_runner_))); @@ -255,19 +256,6 @@ loading_task_runner_ = scheduler_->LoadingTaskRunner(); idle_task_runner_ = scheduler_->IdleTaskRunner(); timer_task_runner_ = scheduler_->TimerTaskRunner(); - scheduler_->GetSchedulerHelperForTesting()->SetTimeSourceForTesting( - make_scoped_ptr(new TestTimeSource(clock_.get()))); - scheduler_->GetSchedulerHelperForTesting() - ->GetTaskQueueManagerForTesting() - ->SetTimeSourceForTesting( - make_scoped_ptr(new TestTimeSource(clock_.get()))); - scheduler_->GetLoadingTaskCostEstimatorForTesting() - ->SetTimeSourceForTesting( - make_scoped_ptr(new TestTimeSource(clock_.get()))); - scheduler_->GetTimerTaskCostEstimatorForTesting()->SetTimeSourceForTesting( - make_scoped_ptr(new TestTimeSource(clock_.get()))); - scheduler_->GetIdleTimeEstimatorForTesting()->SetTimeSourceForTesting( - make_scoped_ptr(new TestTimeSource(clock_.get()))); } void TearDown() override { @@ -486,7 +474,7 @@ scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_; scoped_ptr<base::MessageLoop> message_loop_; - scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner_; + scoped_refptr<SchedulerTqmDelegate> main_task_runner_; scoped_ptr<RendererSchedulerImplForTest> scheduler_; scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; @@ -1368,8 +1356,8 @@ void SetUp() override { mock_task_runner_ = make_scoped_refptr( new cc::OrderedSimpleTaskRunner(clock_.get(), false)); - main_task_runner_ = - SchedulerTaskRunnerDelegateForTest::Create(mock_task_runner_); + main_task_runner_ = SchedulerTqmDelegateForTest::Create( + mock_task_runner_, make_scoped_ptr(new TestTimeSource(clock_.get()))); mock_scheduler_ = new RendererSchedulerImplForTest(main_task_runner_); Initialize(make_scoped_ptr(mock_scheduler_)); }
diff --git a/components/scheduler/renderer/task_cost_estimator.cc b/components/scheduler/renderer/task_cost_estimator.cc index 910760df..ce8dee9 100644 --- a/components/scheduler/renderer/task_cost_estimator.cc +++ b/components/scheduler/renderer/task_cost_estimator.cc
@@ -8,10 +8,11 @@ namespace scheduler { -TaskCostEstimator::TaskCostEstimator(int sample_count, +TaskCostEstimator::TaskCostEstimator(base::TickClock* time_source, + int sample_count, double estimation_percentile) : rolling_time_delta_history_(sample_count), - time_source_(new base::DefaultTickClock), + time_source_(time_source), outstanding_task_count_(0), estimation_percentile_(estimation_percentile) {} @@ -39,9 +40,4 @@ expected_task_duration_ = base::TimeDelta(); } -void TaskCostEstimator::SetTimeSourceForTesting( - scoped_ptr<base::TickClock> time_source) { - time_source_ = time_source.Pass(); -} - } // namespace scheduler
diff --git a/components/scheduler/renderer/task_cost_estimator.h b/components/scheduler/renderer/task_cost_estimator.h index 7fe68db..fa0f4c48 100644 --- a/components/scheduler/renderer/task_cost_estimator.h +++ b/components/scheduler/renderer/task_cost_estimator.h
@@ -20,7 +20,9 @@ class SCHEDULER_EXPORT TaskCostEstimator : public base::MessageLoop::TaskObserver { public: - TaskCostEstimator(int sample_count, double estimation_percentile); + TaskCostEstimator(base::TickClock* time_source, + int sample_count, + double estimation_percentile); ~TaskCostEstimator() override; base::TimeDelta expected_task_duration() const; @@ -31,11 +33,9 @@ void Clear(); - void SetTimeSourceForTesting(scoped_ptr<base::TickClock> time_source); - private: cc::RollingTimeDeltaHistory rolling_time_delta_history_; - scoped_ptr<base::TickClock> time_source_; + base::TickClock* time_source_; // NOT OWNED int outstanding_task_count_; double estimation_percentile_; base::TimeTicks task_start_time_;
diff --git a/components/scheduler/renderer/task_cost_estimator_unittest.cc b/components/scheduler/renderer/task_cost_estimator_unittest.cc index 5f3fe8a..ec6fb1b 100644 --- a/components/scheduler/renderer/task_cost_estimator_unittest.cc +++ b/components/scheduler/renderer/task_cost_estimator_unittest.cc
@@ -16,23 +16,26 @@ TaskCostEstimatorTest() {} ~TaskCostEstimatorTest() override {} - void SetUp() override {} + void SetUp() override { + test_time_source_.reset(new TestTimeSource(&clock_)); + } base::SimpleTestTickClock clock_; + scoped_ptr<TestTimeSource> test_time_source_; }; class TaskCostEstimatorForTest : public TaskCostEstimator { public: - TaskCostEstimatorForTest(base::SimpleTestTickClock* clock, + TaskCostEstimatorForTest(TestTimeSource* test_time_source, int sample_count, double estimation_percentile) - : TaskCostEstimator(sample_count, estimation_percentile) { - SetTimeSourceForTesting(make_scoped_ptr(new TestTimeSource(clock))); - } + : TaskCostEstimator(test_time_source, + sample_count, + estimation_percentile) {} }; TEST_F(TaskCostEstimatorTest, BasicEstimation) { - TaskCostEstimatorForTest estimator(&clock_, 1, 100); + TaskCostEstimatorForTest estimator(test_time_source_.get(), 1, 100); base::PendingTask task(FROM_HERE, base::Closure()); estimator.WillProcessTask(task); @@ -44,7 +47,7 @@ } TEST_F(TaskCostEstimatorTest, Clear) { - TaskCostEstimatorForTest estimator(&clock_, 1, 100); + TaskCostEstimatorForTest estimator(test_time_source_.get(), 1, 100); base::PendingTask task(FROM_HERE, base::Closure()); estimator.WillProcessTask(task); @@ -57,7 +60,7 @@ } TEST_F(TaskCostEstimatorTest, NestedRunLoop) { - TaskCostEstimatorForTest estimator(&clock_, 1, 100); + TaskCostEstimatorForTest estimator(test_time_source_.get(), 1, 100); base::PendingTask task(FROM_HERE, base::Closure()); // Make sure we ignore the tasks inside the nested run loop.
diff --git a/components/scheduler/renderer/web_frame_host_scheduler_impl_unittest.cc b/components/scheduler/renderer/web_frame_host_scheduler_impl_unittest.cc index 81defdf..794057a2 100644 --- a/components/scheduler/renderer/web_frame_host_scheduler_impl_unittest.cc +++ b/components/scheduler/renderer/web_frame_host_scheduler_impl_unittest.cc
@@ -8,7 +8,8 @@ #include "base/memory/scoped_ptr.h" #include "base/test/simple_test_tick_clock.h" #include "cc/test/ordered_simple_task_runner.h" -#include "components/scheduler/child/scheduler_task_runner_delegate_for_test.h" +#include "components/scheduler/base/test_time_source.h" +#include "components/scheduler/child/scheduler_tqm_delegate_for_test.h" #include "components/scheduler/renderer/renderer_scheduler_impl.h" #include "components/scheduler/renderer/web_frame_scheduler_impl.h" #include "testing/gtest/include/gtest/gtest.h" @@ -25,8 +26,8 @@ clock_->Advance(base::TimeDelta::FromMicroseconds(5000)); mock_task_runner_ = make_scoped_refptr( new cc::OrderedSimpleTaskRunner(clock_.get(), false)); - main_task_runner_ = - SchedulerTaskRunnerDelegateForTest::Create(mock_task_runner_); + main_task_runner_ = SchedulerTqmDelegateForTest::Create( + mock_task_runner_, make_scoped_ptr(new TestTimeSource(clock_.get()))); scheduler_.reset(new RendererSchedulerImpl(main_task_runner_)); frame_host_scheduler_.reset( new WebFrameHostSchedulerImpl(scheduler_.get())); @@ -38,7 +39,7 @@ scoped_ptr<base::SimpleTestTickClock> clock_; scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_; - scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner_; + scoped_refptr<SchedulerTqmDelegate> main_task_runner_; scoped_ptr<RendererSchedulerImpl> scheduler_; scoped_ptr<WebFrameHostSchedulerImpl> frame_host_scheduler_; };
diff --git a/components/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc b/components/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc index 9e3fbb2a..2f6d0b8 100644 --- a/components/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc +++ b/components/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc
@@ -7,7 +7,9 @@ #include "base/location.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" -#include "components/scheduler/child/scheduler_task_runner_delegate_impl.h" +#include "base/test/simple_test_tick_clock.h" +#include "components/scheduler/base/test_time_source.h" +#include "components/scheduler/child/scheduler_tqm_delegate_impl.h" #include "components/scheduler/renderer/renderer_scheduler_impl.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -34,7 +36,10 @@ class WebThreadImplForRendererSchedulerTest : public testing::Test { public: WebThreadImplForRendererSchedulerTest() - : scheduler_(SchedulerTaskRunnerDelegateImpl::Create(&message_loop_)), + : clock_(new base::SimpleTestTickClock()), + scheduler_(SchedulerTqmDelegateImpl::Create( + &message_loop_, + make_scoped_ptr(new TestTimeSource(clock_.get())))), default_task_runner_(scheduler_.DefaultTaskRunner()), thread_(&scheduler_) {} @@ -49,6 +54,7 @@ protected: base::MessageLoop message_loop_; + scoped_ptr<base::SimpleTestTickClock> clock_; RendererSchedulerImpl scheduler_; scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; WebThreadImplForRendererScheduler thread_;
diff --git a/components/scheduler/scheduler.gyp b/components/scheduler/scheduler.gyp index aa9a15a..cffc072 100644 --- a/components/scheduler/scheduler.gyp +++ b/components/scheduler/scheduler.gyp
@@ -14,10 +14,22 @@ ], 'targets': [ { + # GN version: //components/scheduler:common + 'target_name': 'scheduler_common', + 'type': 'static_library', + 'include_dirs': [ + '../..', + ], + 'sources': [ + '<@(scheduler_common_sources)', + ], + }, + { # GN version: //components/scheduler:scheduler 'target_name': 'scheduler', 'type': '<(component)', 'dependencies': [ + 'scheduler_common', '../../base/base.gyp:base', '../../cc/cc.gyp:cc', '../../third_party/WebKit/public/blink.gyp:blink',
diff --git a/components/scheduler/scheduler.gypi b/components/scheduler/scheduler.gypi index d285e45..208d110 100644 --- a/components/scheduler/scheduler.gypi +++ b/components/scheduler/scheduler.gypi
@@ -4,18 +4,22 @@ { 'variables': { + 'scheduler_common_sources': [ + 'common/scheduler_switches.cc', + 'common/scheduler_switches.h', + ], 'scheduler_sources': [ 'base/cancelable_closure_holder.cc', 'base/cancelable_closure_holder.h', 'base/lazy_now.cc', 'base/lazy_now.h', - 'base/nestable_single_thread_task_runner.h', 'base/task_queue.cc', 'base/task_queue.h', 'base/task_queue_impl.cc', 'base/task_queue_impl.h', 'base/task_queue_manager.cc', 'base/task_queue_manager.h', + 'base/task_queue_manager_delegate.h', 'base/task_queue_selector.cc', 'base/task_queue_selector.h', 'base/task_queue_sets.cc', @@ -27,11 +31,13 @@ 'child/idle_helper.h', 'child/scheduler_helper.cc', 'child/scheduler_helper.h', - 'child/scheduler_task_runner_delegate.h', - 'child/scheduler_task_runner_delegate_impl.cc', - 'child/scheduler_task_runner_delegate_impl.h', + 'child/scheduler_tqm_delegate.h', + 'child/scheduler_tqm_delegate_impl.cc', + 'child/scheduler_tqm_delegate_impl.h', 'child/single_thread_idle_task_runner.cc', 'child/single_thread_idle_task_runner.h', + 'child/virtual_time_tqm_delegate.cc', + 'child/virtual_time_tqm_delegate.h', 'child/web_scheduler_impl.cc', 'child/web_scheduler_impl.h', 'child/web_task_runner_impl.cc',
diff --git a/components/scheduler/test/lazy_scheduler_message_loop_delegate_for_tests.cc b/components/scheduler/test/lazy_scheduler_message_loop_delegate_for_tests.cc index 23c6997..c1aa479 100644 --- a/components/scheduler/test/lazy_scheduler_message_loop_delegate_for_tests.cc +++ b/components/scheduler/test/lazy_scheduler_message_loop_delegate_for_tests.cc
@@ -4,6 +4,8 @@ #include "components/scheduler/test/lazy_scheduler_message_loop_delegate_for_tests.h" +#include "base/time/default_tick_clock.h" + namespace scheduler { // static @@ -15,7 +17,8 @@ LazySchedulerMessageLoopDelegateForTests:: LazySchedulerMessageLoopDelegateForTests() : message_loop_(base::MessageLoop::current()), - thread_id_(base::PlatformThread::CurrentId()) { + thread_id_(base::PlatformThread::CurrentId()), + time_source_(make_scoped_ptr(new base::DefaultTickClock())) { if (message_loop_) original_task_runner_ = message_loop_->task_runner(); } @@ -82,4 +85,10 @@ return EnsureMessageLoop()->IsNested(); } +base::TimeTicks LazySchedulerMessageLoopDelegateForTests::NowTicks() { + return time_source_->NowTicks(); +} + +void LazySchedulerMessageLoopDelegateForTests::OnNoMoreImmediateWork() {} + } // namespace scheduler
diff --git a/components/scheduler/test/lazy_scheduler_message_loop_delegate_for_tests.h b/components/scheduler/test/lazy_scheduler_message_loop_delegate_for_tests.h index aaffb91..16c7d98 100644 --- a/components/scheduler/test/lazy_scheduler_message_loop_delegate_for_tests.h +++ b/components/scheduler/test/lazy_scheduler_message_loop_delegate_for_tests.h
@@ -6,7 +6,8 @@ #define COMPONENTS_SCHEDULER_TEST_LAZY_SCHEDULER_MESSAGE_LOOP_DELEGATE_FOR_TESTS_H_ #include "base/message_loop/message_loop.h" -#include "components/scheduler/child/scheduler_task_runner_delegate.h" +#include "base/time/tick_clock.h" +#include "components/scheduler/child/scheduler_tqm_delegate.h" namespace scheduler { @@ -17,12 +18,11 @@ // // TODO(skyostil): Fix the relevant test suites and remove this class // (crbug.com/495659). -class LazySchedulerMessageLoopDelegateForTests - : public SchedulerTaskRunnerDelegate { +class LazySchedulerMessageLoopDelegateForTests : public SchedulerTqmDelegate { public: static scoped_refptr<LazySchedulerMessageLoopDelegateForTests> Create(); - // SchedulerTaskRunnerDelegate implementation + // SchedulerTqmDelegate implementation void SetDefaultTaskRunner( scoped_refptr<base::SingleThreadTaskRunner> task_runner) override; void RestoreDefaultTaskRunner() override; @@ -34,6 +34,8 @@ base::TimeDelta delay) override; bool RunsTasksOnCurrentThread() const override; bool IsNested() const override; + base::TimeTicks NowTicks() override; + void OnNoMoreImmediateWork() override; private: LazySchedulerMessageLoopDelegateForTests(); @@ -48,6 +50,7 @@ // A task runner which hasn't yet been overridden in the message loop. mutable scoped_refptr<base::SingleThreadTaskRunner> pending_task_runner_; mutable scoped_refptr<base::SingleThreadTaskRunner> original_task_runner_; + scoped_ptr<base::TickClock> time_source_; DISALLOW_COPY_AND_ASSIGN(LazySchedulerMessageLoopDelegateForTests); };
diff --git a/components/startup_metric_utils.gypi b/components/startup_metric_utils.gypi index 55763c8d..f70e7a0 100644 --- a/components/startup_metric_utils.gypi +++ b/components/startup_metric_utils.gypi
@@ -5,7 +5,7 @@ { 'targets': [ { - 'target_name': 'startup_metric_utils', + 'target_name': 'startup_metric_utils_browser', 'type': 'static_library', 'dependencies': [ '../base/base.gyp:base', @@ -14,8 +14,8 @@ '..', ], 'sources': [ - 'startup_metric_utils/startup_metric_utils.cc', - 'startup_metric_utils/startup_metric_utils.h', + 'startup_metric_utils/browser/startup_metric_utils.cc', + 'startup_metric_utils/browser/startup_metric_utils.h', ], }, ],
diff --git a/components/startup_metric_utils/BUILD.gn b/components/startup_metric_utils/BUILD.gn deleted file mode 100644 index 428b2bd..0000000 --- a/components/startup_metric_utils/BUILD.gn +++ /dev/null
@@ -1,14 +0,0 @@ -# Copyright 2013 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("startup_metric_utils") { - sources = [ - "startup_metric_utils.cc", - "startup_metric_utils.h", - ] - - deps = [ - "//base", - ] -}
diff --git a/components/startup_metric_utils/browser/BUILD.gn b/components/startup_metric_utils/browser/BUILD.gn new file mode 100644 index 0000000..258e2106 --- /dev/null +++ b/components/startup_metric_utils/browser/BUILD.gn
@@ -0,0 +1,14 @@ +# Copyright 2013 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("browser") { + sources = [ + "startup_metric_utils.cc", + "startup_metric_utils.h", + ] + + deps = [ + "//base", + ] +}
diff --git a/components/startup_metric_utils/browser/startup_metric_utils.cc b/components/startup_metric_utils/browser/startup_metric_utils.cc new file mode 100644 index 0000000..622b966 --- /dev/null +++ b/components/startup_metric_utils/browser/startup_metric_utils.cc
@@ -0,0 +1,510 @@ +// Copyright 2013 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/startup_metric_utils/browser/startup_metric_utils.h" + +#include "base/containers/hash_tables.h" +#include "base/environment.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/metrics/histogram_macros.h" +#include "base/strings/string_number_conversions.h" +#include "base/sys_info.h" +#include "base/trace_event/trace_event.h" + +#if defined(OS_WIN) +#include <winternl.h> +#include "base/win/windows_version.h" +#endif + +namespace startup_metric_utils { + +namespace { + +// Mark as volatile to defensively make sure usage is thread-safe. +// Note that at the time of this writing, access is only on the UI thread. +volatile bool g_non_browser_ui_displayed = false; + +base::LazyInstance<base::Time>::Leaky g_process_creation_time = + LAZY_INSTANCE_INITIALIZER; + +base::LazyInstance<base::Time>::Leaky g_main_entry_point_time = + LAZY_INSTANCE_INITIALIZER; + +StartupTemperature g_startup_temperature = UNCERTAIN_STARTUP_TEMPERATURE; + +#if defined(OS_WIN) + +// These values are taken from the Startup.BrowserMessageLoopStartHardFaultCount +// histogram. If the cold start histogram starts looking strongly bimodal it may +// be because the binary/resource sizes have grown significantly larger than +// when these values were set. In this case the new values need to be chosen +// from the original histogram. +// +// Maximum number of hard faults tolerated for a startup to be classified as a +// warm start. Set at roughly the 40th percentile of the HardFaultCount +// histogram. +const uint32_t WARM_START_HARD_FAULT_COUNT_THRESHOLD = 5; +// Minimum number of hard faults expected for a startup to be classified as a +// cold start. Set at roughly the 60th percentile of the HardFaultCount +// histogram. +const uint32_t COLD_START_HARD_FAULT_COUNT_THRESHOLD = 1200; + +// The struct used to return system process information via the NT internal +// QuerySystemInformation call. This is partially documented at +// http://goo.gl/Ja9MrH and fully documented at http://goo.gl/QJ70rn +// This structure is laid out in the same format on both 32-bit and 64-bit +// systems, but has a different size due to the various pointer-sized fields. +struct SYSTEM_PROCESS_INFORMATION_EX { + ULONG NextEntryOffset; + ULONG NumberOfThreads; + LARGE_INTEGER WorkingSetPrivateSize; + ULONG HardFaultCount; + BYTE Reserved1[36]; + PVOID Reserved2[3]; + // This is labeled a handle so that it expands to the correct size for 32-bit + // and 64-bit operating systems. However, under the hood it's a 32-bit DWORD + // containing the process ID. + HANDLE UniqueProcessId; + PVOID Reserved3; + ULONG HandleCount; + BYTE Reserved4[4]; + PVOID Reserved5[11]; + SIZE_T PeakPagefileUsage; + SIZE_T PrivatePageCount; + LARGE_INTEGER Reserved6[6]; + // Array of SYSTEM_THREAD_INFORMATION structs follows. +}; + +// The signature of the NtQuerySystemInformation function. +typedef NTSTATUS (WINAPI *NtQuerySystemInformationPtr)( + SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); + +// Gets the hard fault count of the current process, returning it via +// |hard_fault_count|. Returns true on success, false otherwise. Also returns +// whether or not the system call was even possible for the current OS version +// via |has_os_support|. +bool GetHardFaultCountForCurrentProcess(uint32_t* hard_fault_count, + bool* has_os_support) { + DCHECK(hard_fault_count); + DCHECK(has_os_support); + + if (base::win::GetVersion() < base::win::VERSION_WIN7) { + *has_os_support = false; + return false; + } + // At this point the OS supports the required system call. + *has_os_support = true; + + // Get the function pointer. + NtQuerySystemInformationPtr query_sys_info = + reinterpret_cast<NtQuerySystemInformationPtr>( + ::GetProcAddress(GetModuleHandle(L"ntdll.dll"), + "NtQuerySystemInformation")); + if (query_sys_info == nullptr) + return false; + + // The output of this system call depends on the number of threads and + // processes on the entire system, and this can change between calls. Retry + // a small handful of times growing the buffer along the way. + // NOTE: The actual required size depends entirely on the number of processes + // and threads running on the system. The initial guess suffices for + // ~100s of processes and ~1000s of threads. + std::vector<uint8_t> buffer(32 * 1024); + for (size_t tries = 0; tries < 3; ++tries) { + ULONG return_length = 0; + NTSTATUS status = query_sys_info( + SystemProcessInformation, + buffer.data(), + static_cast<ULONG>(buffer.size()), + &return_length); + // Insufficient space in the buffer. + if (return_length > buffer.size()) { + buffer.resize(return_length); + continue; + } + if (NT_SUCCESS(status) && return_length <= buffer.size()) + break; + return false; + } + + // Look for the struct housing information for the current process. + DWORD proc_id = ::GetCurrentProcessId(); + size_t index = 0; + while (index < buffer.size()) { + DCHECK_LE(index + sizeof(SYSTEM_PROCESS_INFORMATION_EX), buffer.size()); + SYSTEM_PROCESS_INFORMATION_EX* proc_info = + reinterpret_cast<SYSTEM_PROCESS_INFORMATION_EX*>(buffer.data() + index); + if (reinterpret_cast<DWORD>(proc_info->UniqueProcessId) == proc_id) { + *hard_fault_count = proc_info->HardFaultCount; + return true; + } + // The list ends when NextEntryOffset is zero. This also prevents busy + // looping if the data is in fact invalid. + if (proc_info->NextEntryOffset <= 0) + return false; + index += proc_info->NextEntryOffset; + } + + return false; +} + +#endif // defined(OS_WIN) + + +// Helper macro for splitting out an UMA histogram based on cold or warm start. +// |type| is the histogram type, and corresponds to an UMA macro like +// UMA_HISTOGRAM_LONG_TIMES. It must be itself be a macro that only takes two +// parameters. +// |basename| is the basename of the histogram. A histogram of this name will +// always be recorded to. If the startup is either cold or warm then a value +// will also be recorded to the histogram with name |basename| and suffix +// ".ColdStart" or ".WarmStart", as appropriate. +// |value_expr| is an expression evaluating to the value to be recorded. This +// will be evaluated exactly once and cached, so side effects are not an issue. +#define UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(type, basename, value_expr) \ + { \ + const auto kValue = value_expr; \ + /* Always record to the base histogram. */ \ + type(basename, kValue); \ + /* Record to the cold/warm suffixed histogram as appropriate. */ \ + if (g_startup_temperature == COLD_STARTUP_TEMPERATURE) { \ + type(basename ".ColdStartup", kValue); \ + } else if (g_startup_temperature == WARM_STARTUP_TEMPERATURE) { \ + type(basename ".WarmStartup", kValue); \ + } \ + } + +#define UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(type, basename, \ + begin_time, end_time) \ + { \ + UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(type, basename, \ + end_time - begin_time) \ + TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1( \ + "startup", basename, 0, \ + StartupTimeToTraceTicks(begin_time).ToInternalValue(), "Temperature", \ + g_startup_temperature); \ + TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP1( \ + "startup", basename, 0, \ + StartupTimeToTraceTicks(end_time).ToInternalValue(), "Temperature", \ + g_startup_temperature); \ + } + +// On Windows, records the number of hard-faults that have occurred in the +// current chrome.exe process since it was started. This is a nop on other +// platforms. +// crbug.com/476923 +// TODO(chrisha): If this proves useful, use it to split startup stats in two. +void RecordHardFaultHistogram(bool is_first_run) { +#if defined(OS_WIN) + uint32_t hard_fault_count = 0; + bool has_os_support = false; + bool success = GetHardFaultCountForCurrentProcess( + &hard_fault_count, &has_os_support); + + // Log whether or not the system call was successful, assuming the OS was + // detected to support it. + if (has_os_support) { + UMA_HISTOGRAM_BOOLEAN( + "Startup.BrowserMessageLoopStartHardFaultCount.Success", + success); + } + + // Don't log a histogram value if unable to get the hard fault count. + if (!success) + return; + + // Hard fault counts are expected to be in the thousands range, + // corresponding to faulting in ~10s of MBs of code ~10s of KBs at a time. + // (Observed to vary from 1000 to 10000 on various test machines and + // platforms.) + if (is_first_run) { + UMA_HISTOGRAM_CUSTOM_COUNTS( + "Startup.BrowserMessageLoopStartHardFaultCount.FirstRun", + hard_fault_count, + 0, 40000, 50); + } else { + UMA_HISTOGRAM_CUSTOM_COUNTS( + "Startup.BrowserMessageLoopStartHardFaultCount", + hard_fault_count, + 0, 40000, 50); + } + + // Determine the startup type based on the number of observed hard faults. + DCHECK_EQ(UNCERTAIN_STARTUP_TEMPERATURE, g_startup_temperature); + if (hard_fault_count < WARM_START_HARD_FAULT_COUNT_THRESHOLD) { + g_startup_temperature = WARM_STARTUP_TEMPERATURE; + } else if (hard_fault_count >= COLD_START_HARD_FAULT_COUNT_THRESHOLD) { + g_startup_temperature = COLD_STARTUP_TEMPERATURE; + } + + // Record the startup 'temperature'. + UMA_HISTOGRAM_ENUMERATION( + "Startup.Temperature", g_startup_temperature, STARTUP_TEMPERATURE_MAX); +#endif // defined(OS_WIN) +} + +// Converts a base::Time value to a base::TraceTicks value. The conversion isn't +// exact, but is within the time delta taken to synchronously resolve +// base::Time::Now() and base::TraceTicks::Now() which in practice is pretty +// much instant compared to multi-seconds startup timings. +// TODO(gab): Find a precise way to do this (http://crbug.com/544131). +base::TraceTicks StartupTimeToTraceTicks(const base::Time& time) { + // First get a base which represents the same point in time in both units. + // The wall clock time it takes to gather both of these is the precision of + // this method. + static const base::Time time_base = base::Time::Now(); + static const base::TraceTicks trace_ticks_base = base::TraceTicks::Now(); + + // Then use the TimeDelta common ground between the two units to make the + // conversion. + const base::TimeDelta delta_since_base = time_base - time; + return trace_ticks_base - delta_since_base; +} + +// Record time of main entry so it can be read from Telemetry performance tests. +// TODO(jeremy): Remove once crbug.com/317481 is fixed. +void RecordMainEntryTimeHistogram() { + const int kLowWordMask = 0xFFFFFFFF; + const int kLower31BitsMask = 0x7FFFFFFF; + DCHECK(!MainEntryPointTime().is_null()); + base::TimeDelta browser_main_entry_time_absolute = + MainEntryPointTime() - base::Time::UnixEpoch(); + + uint64 browser_main_entry_time_raw_ms = + browser_main_entry_time_absolute.InMilliseconds(); + + base::TimeDelta browser_main_entry_time_raw_ms_high_word = + base::TimeDelta::FromMilliseconds( + (browser_main_entry_time_raw_ms >> 32) & kLowWordMask); + // Shift by one because histograms only support non-negative values. + base::TimeDelta browser_main_entry_time_raw_ms_low_word = + base::TimeDelta::FromMilliseconds( + (browser_main_entry_time_raw_ms >> 1) & kLower31BitsMask); + + // A timestamp is a 64 bit value, yet histograms can only store 32 bits. + LOCAL_HISTOGRAM_TIMES("Startup.BrowserMainEntryTimeAbsoluteHighWord", + browser_main_entry_time_raw_ms_high_word); + LOCAL_HISTOGRAM_TIMES("Startup.BrowserMainEntryTimeAbsoluteLowWord", + browser_main_entry_time_raw_ms_low_word); +} + +// Environment variable that stores the timestamp when the executable's main() +// function was entered. +const char kChromeMainTimeEnvVar[] = "CHROME_MAIN_TIME"; + +// Returns the time of main entry recorded from RecordExeMainEntryTime. +base::Time ExeMainEntryPointTime() { + scoped_ptr<base::Environment> env(base::Environment::Create()); + std::string time_string; + int64 time_int = 0; + if (env->GetVar(kChromeMainTimeEnvVar, &time_string) && + base::StringToInt64(time_string, &time_int)) { + return base::Time::FromInternalValue(time_int); + } + return base::Time(); +} + +} // namespace + +bool WasNonBrowserUIDisplayed() { + return g_non_browser_ui_displayed; +} + +void SetNonBrowserUIDisplayed() { + g_non_browser_ui_displayed = true; +} + +void RecordStartupProcessCreationTime(const base::Time& time) { + DCHECK(g_process_creation_time.Get().is_null()); + g_process_creation_time.Get() = time; + DCHECK(!g_process_creation_time.Get().is_null()); +} + +void RecordMainEntryPointTime(const base::Time& time) { + DCHECK(MainEntryPointTime().is_null()); + g_main_entry_point_time.Get() = time; + DCHECK(!MainEntryPointTime().is_null()); +} + +void RecordExeMainEntryPointTime(const base::Time& time) { + std::string exe_load_time = base::Int64ToString(time.ToInternalValue()); + scoped_ptr<base::Environment> env(base::Environment::Create()); + env->SetVar(kChromeMainTimeEnvVar, exe_load_time); +} + +void RecordBrowserMainMessageLoopStart(const base::Time& time, + bool is_first_run) { + RecordHardFaultHistogram(is_first_run); + RecordMainEntryTimeHistogram(); + + const base::Time& process_creation_time = g_process_creation_time.Get(); + if (!is_first_run && !process_creation_time.is_null()) { + UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( + UMA_HISTOGRAM_LONG_TIMES_100, "Startup.BrowserMessageLoopStartTime", + process_creation_time, time); + } + + // Bail if uptime < 7 minutes, to filter out cases where Chrome may have been + // autostarted and the machine is under io pressure. + const int64 kSevenMinutesInMilliseconds = + base::TimeDelta::FromMinutes(7).InMilliseconds(); + if (base::SysInfo::Uptime() < kSevenMinutesInMilliseconds) + return; + + // The Startup.BrowserMessageLoopStartTime histogram exhibits instability in + // the field which limits its usefulness in all scenarios except when we have + // a very large sample size. Attempt to mitigate this with a new metric: + // * Measure time from main entry rather than the OS' notion of process start. + // * Only measure launches that occur 7 minutes after boot to try to avoid + // cases where Chrome is auto-started and IO is heavily loaded. + const base::Time dll_main_time = MainEntryPointTime(); + if (is_first_run) { + UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( + UMA_HISTOGRAM_LONG_TIMES, + "Startup.BrowserMessageLoopStartTimeFromMainEntry.FirstRun", + dll_main_time, time); + } else { + UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( + UMA_HISTOGRAM_LONG_TIMES, + "Startup.BrowserMessageLoopStartTimeFromMainEntry", dll_main_time, + time); + } + + // Record timings between process creation, the main() in the executable being + // reached and the main() in the shared library being reached. + if (!process_creation_time.is_null()) { + const base::Time exe_main_time = ExeMainEntryPointTime(); + if (!exe_main_time.is_null()) { + // Process create to chrome.exe:main(). + UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( + UMA_HISTOGRAM_LONG_TIMES, "Startup.LoadTime.ProcessCreateToExeMain", + process_creation_time, exe_main_time); + + // chrome.exe:main() to chrome.dll:main(). + UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( + UMA_HISTOGRAM_LONG_TIMES, "Startup.LoadTime.ExeMainToDllMain", + exe_main_time, dll_main_time); + + // Process create to chrome.dll:main(). Reported as a histogram only as + // the other two events above are sufficient for tracing purposes. + UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE( + UMA_HISTOGRAM_LONG_TIMES, "Startup.LoadTime.ProcessCreateToDllMain", + dll_main_time - process_creation_time); + } + } +} + +void RecordBrowserWindowDisplay(const base::Time& time) { + static bool is_first_call = true; + if (!is_first_call || time.is_null()) + return; + is_first_call = false; + if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null()) + return; + + UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( + UMA_HISTOGRAM_LONG_TIMES, "Startup.BrowserWindowDisplay", + g_process_creation_time.Get(), time); +} + +void RecordBrowserOpenTabsDelta(const base::TimeDelta& delta) { + static bool is_first_call = true; + if (!is_first_call) + return; + is_first_call = false; + + UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(UMA_HISTOGRAM_LONG_TIMES_100, + "Startup.BrowserOpenTabs", delta); +} + +void RecordFirstWebContentsMainFrameLoad(const base::Time& time) { + static bool is_first_call = true; + if (!is_first_call || time.is_null()) + return; + is_first_call = false; + if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null()) + return; + + UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( + UMA_HISTOGRAM_LONG_TIMES_100, "Startup.FirstWebContents.MainFrameLoad2", + g_process_creation_time.Get(), time); +} + +void RecordDeprecatedFirstWebContentsMainFrameLoad(const base::Time& time) { + static bool is_first_call = true; + if (!is_first_call || time.is_null()) + return; + is_first_call = false; + if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null()) + return; + + UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE( + UMA_HISTOGRAM_LONG_TIMES_100, "Startup.FirstWebContents.MainFrameLoad", + time - g_process_creation_time.Get()); +} + +void RecordFirstWebContentsNonEmptyPaint(const base::Time& time) { + static bool is_first_call = true; + if (!is_first_call || time.is_null()) + return; + is_first_call = false; + if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null()) + return; + + UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( + UMA_HISTOGRAM_LONG_TIMES_100, "Startup.FirstWebContents.NonEmptyPaint2", + g_process_creation_time.Get(), time); +} + +void RecordDeprecatedFirstWebContentsNonEmptyPaint(const base::Time& time) { + static bool is_first_call = true; + if (!is_first_call || time.is_null()) + return; + is_first_call = false; + if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null()) + return; + + UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE( + UMA_HISTOGRAM_LONG_TIMES_100, "Startup.FirstWebContents.NonEmptyPaint", + time - g_process_creation_time.Get()); +} + +void RecordFirstWebContentsMainNavigationStart(const base::Time& time) { + static bool is_first_call = true; + if (!is_first_call || time.is_null()) + return; + is_first_call = false; + if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null()) + return; + + UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( + UMA_HISTOGRAM_LONG_TIMES_100, + "Startup.FirstWebContents.MainNavigationStart", + g_process_creation_time.Get(), time); +} + +void RecordFirstWebContentsMainNavigationFinished(const base::Time& time) { + static bool is_first_call = true; + if (!is_first_call || time.is_null()) + return; + is_first_call = false; + if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null()) + return; + + UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( + UMA_HISTOGRAM_LONG_TIMES_100, + "Startup.FirstWebContents.MainNavigationFinished", + g_process_creation_time.Get(), time); +} + +base::Time MainEntryPointTime() { + return g_main_entry_point_time.Get(); +} + +StartupTemperature GetStartupTemperature() { + return g_startup_temperature; +} + +} // namespace startup_metric_utils
diff --git a/components/startup_metric_utils/browser/startup_metric_utils.h b/components/startup_metric_utils/browser/startup_metric_utils.h new file mode 100644 index 0000000..b071321 --- /dev/null +++ b/components/startup_metric_utils/browser/startup_metric_utils.h
@@ -0,0 +1,107 @@ +// Copyright 2013 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_STARTUP_METRIC_UTILS_BROWSER_STARTUP_METRIC_UTILS_H_ +#define COMPONENTS_STARTUP_METRIC_UTILS_BROWSER_STARTUP_METRIC_UTILS_H_ + +#include <string> + +#include "base/time/time.h" + +// Utility functions to support metric collection for browser startup. + +namespace startup_metric_utils { + +// An enumeration of startup temperatures. This must be kept in sync with the +// UMA StartupType enumeration defined in histograms.xml. +enum StartupTemperature { + // The startup was a cold start: nearly all of the Chrome binaries and + // resources were brought into memory using hard faults. + COLD_STARTUP_TEMPERATURE = 0, + // The startup was a warm start: the Chrome binaries and resources were + // mostly already resident in memory and effectively no hard faults were + // observed. + WARM_STARTUP_TEMPERATURE = 1, + // The startup type couldn't quite be classified as warm of cold, but rather + // was somewhere in between. + UNCERTAIN_STARTUP_TEMPERATURE = 2, + // This must be last. + STARTUP_TEMPERATURE_MAX +}; + +// Returns true if any UI other than the browser window has been displayed +// so far. Useful to test if UI has been displayed before the first browser +// window was shown, which would invalidate any surrounding timing metrics. +bool WasNonBrowserUIDisplayed(); + +// Call this when displaying UI that might potentially delay the appearance +// of the initial browser window on Chrome startup. +// +// Note on usage: This function is idempotent and its overhead is low enough +// in comparison with UI display that it's OK to call it on every +// UI invocation regardless of whether the browser window has already +// been displayed or not. +void SetNonBrowserUIDisplayed(); + +// Call this with the creation time of the startup (initial/main) process. +void RecordStartupProcessCreationTime(const base::Time& time); + +// Call this with a time recorded as early as possible in the startup process. +// On Android, the entry point time is the time at which the Java code starts. +// In Mojo, the entry point time is the time at which the shell starts. +void RecordMainEntryPointTime(const base::Time& time); + +// Call this with the time when the executable is loaded and main() is entered. +// Can be different from |RecordMainEntryPointTime| when the startup process is +// contained in a separate dll, such as with chrome.exe / chrome.dll on Windows. +void RecordExeMainEntryPointTime(const base::Time& time); + +// Call this with the time recorded just before the message loop is started. +// |is_first_run| - is the current launch part of a first run. +void RecordBrowserMainMessageLoopStart(const base::Time& time, + bool is_first_run); + +// Call this with the time when the first browser window became visible. +void RecordBrowserWindowDisplay(const base::Time& time); + +// Call this with the time delta that the browser spent opening its tabs. +void RecordBrowserOpenTabsDelta(const base::TimeDelta& delta); + +// Call this with the time when the first web contents loaded its main frame, +// only if the first web contents was unimpended in its attempt to do so. +void RecordFirstWebContentsMainFrameLoad(const base::Time& time); + +// Call this with the time when the first web contents loaded its main frame. +// This records an old stat kept for comparison purposes until M49. +void RecordDeprecatedFirstWebContentsMainFrameLoad(const base::Time& time); + +// Call this with the time when the first web contents had a non-empty paint, +// only if the first web contents was unimpended in its attempt to do so. +void RecordFirstWebContentsNonEmptyPaint(const base::Time& time); + +// Call this with the time when the first web contents had a non-empty paint. +// This records an old stat kept for comparison purposes until M49. +void RecordDeprecatedFirstWebContentsNonEmptyPaint(const base::Time& time); + +// Call this with the time when the first web contents began navigating its main +// frame. +void RecordFirstWebContentsMainNavigationStart(const base::Time& time); + +// Call this with the time when the first web contents successfully committed +// its navigation for the main frame. +void RecordFirstWebContentsMainNavigationFinished(const base::Time& time); + +// Returns the time of main entry recorded from RecordMainEntryPointTime. +// Returns a null Time if a value has not been recorded yet. +// This method is expected to be called from the UI thread. +base::Time MainEntryPointTime(); + +// Returns the startup type. This is only currently supported on the Windows +// platform and will simply return UNCERTAIN_STARTUP_TYPE on other platforms. +// This is only valid after a call to RecordBrowserMainMessageLoopStart(). +StartupTemperature GetStartupTemperature(); + +} // namespace startup_metric_utils + +#endif // COMPONENTS_STARTUP_METRIC_UTILS_BROWSER_STARTUP_METRIC_UTILS_H_
diff --git a/components/startup_metric_utils/startup_metric_utils.cc b/components/startup_metric_utils/startup_metric_utils.cc deleted file mode 100644 index 5e243c5..0000000 --- a/components/startup_metric_utils/startup_metric_utils.cc +++ /dev/null
@@ -1,510 +0,0 @@ -// Copyright 2013 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/startup_metric_utils/startup_metric_utils.h" - -#include "base/containers/hash_tables.h" -#include "base/environment.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/metrics/histogram_macros.h" -#include "base/strings/string_number_conversions.h" -#include "base/sys_info.h" -#include "base/trace_event/trace_event.h" - -#if defined(OS_WIN) -#include <winternl.h> -#include "base/win/windows_version.h" -#endif - -namespace startup_metric_utils { - -namespace { - -// Mark as volatile to defensively make sure usage is thread-safe. -// Note that at the time of this writing, access is only on the UI thread. -volatile bool g_non_browser_ui_displayed = false; - -base::LazyInstance<base::Time>::Leaky g_process_creation_time = - LAZY_INSTANCE_INITIALIZER; - -base::LazyInstance<base::Time>::Leaky g_main_entry_point_time = - LAZY_INSTANCE_INITIALIZER; - -StartupTemperature g_startup_temperature = UNCERTAIN_STARTUP_TEMPERATURE; - -#if defined(OS_WIN) - -// These values are taken from the Startup.BrowserMessageLoopStartHardFaultCount -// histogram. If the cold start histogram starts looking strongly bimodal it may -// be because the binary/resource sizes have grown significantly larger than -// when these values were set. In this case the new values need to be chosen -// from the original histogram. -// -// Maximum number of hard faults tolerated for a startup to be classified as a -// warm start. Set at roughly the 40th percentile of the HardFaultCount -// histogram. -const uint32_t WARM_START_HARD_FAULT_COUNT_THRESHOLD = 5; -// Minimum number of hard faults expected for a startup to be classified as a -// cold start. Set at roughly the 60th percentile of the HardFaultCount -// histogram. -const uint32_t COLD_START_HARD_FAULT_COUNT_THRESHOLD = 1200; - -// The struct used to return system process information via the NT internal -// QuerySystemInformation call. This is partially documented at -// http://goo.gl/Ja9MrH and fully documented at http://goo.gl/QJ70rn -// This structure is laid out in the same format on both 32-bit and 64-bit -// systems, but has a different size due to the various pointer-sized fields. -struct SYSTEM_PROCESS_INFORMATION_EX { - ULONG NextEntryOffset; - ULONG NumberOfThreads; - LARGE_INTEGER WorkingSetPrivateSize; - ULONG HardFaultCount; - BYTE Reserved1[36]; - PVOID Reserved2[3]; - // This is labeled a handle so that it expands to the correct size for 32-bit - // and 64-bit operating systems. However, under the hood it's a 32-bit DWORD - // containing the process ID. - HANDLE UniqueProcessId; - PVOID Reserved3; - ULONG HandleCount; - BYTE Reserved4[4]; - PVOID Reserved5[11]; - SIZE_T PeakPagefileUsage; - SIZE_T PrivatePageCount; - LARGE_INTEGER Reserved6[6]; - // Array of SYSTEM_THREAD_INFORMATION structs follows. -}; - -// The signature of the NtQuerySystemInformation function. -typedef NTSTATUS (WINAPI *NtQuerySystemInformationPtr)( - SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); - -// Gets the hard fault count of the current process, returning it via -// |hard_fault_count|. Returns true on success, false otherwise. Also returns -// whether or not the system call was even possible for the current OS version -// via |has_os_support|. -bool GetHardFaultCountForCurrentProcess(uint32_t* hard_fault_count, - bool* has_os_support) { - DCHECK(hard_fault_count); - DCHECK(has_os_support); - - if (base::win::GetVersion() < base::win::VERSION_WIN7) { - *has_os_support = false; - return false; - } - // At this point the OS supports the required system call. - *has_os_support = true; - - // Get the function pointer. - NtQuerySystemInformationPtr query_sys_info = - reinterpret_cast<NtQuerySystemInformationPtr>( - ::GetProcAddress(GetModuleHandle(L"ntdll.dll"), - "NtQuerySystemInformation")); - if (query_sys_info == nullptr) - return false; - - // The output of this system call depends on the number of threads and - // processes on the entire system, and this can change between calls. Retry - // a small handful of times growing the buffer along the way. - // NOTE: The actual required size depends entirely on the number of processes - // and threads running on the system. The initial guess suffices for - // ~100s of processes and ~1000s of threads. - std::vector<uint8_t> buffer(32 * 1024); - for (size_t tries = 0; tries < 3; ++tries) { - ULONG return_length = 0; - NTSTATUS status = query_sys_info( - SystemProcessInformation, - buffer.data(), - static_cast<ULONG>(buffer.size()), - &return_length); - // Insufficient space in the buffer. - if (return_length > buffer.size()) { - buffer.resize(return_length); - continue; - } - if (NT_SUCCESS(status) && return_length <= buffer.size()) - break; - return false; - } - - // Look for the struct housing information for the current process. - DWORD proc_id = ::GetCurrentProcessId(); - size_t index = 0; - while (index < buffer.size()) { - DCHECK_LE(index + sizeof(SYSTEM_PROCESS_INFORMATION_EX), buffer.size()); - SYSTEM_PROCESS_INFORMATION_EX* proc_info = - reinterpret_cast<SYSTEM_PROCESS_INFORMATION_EX*>(buffer.data() + index); - if (reinterpret_cast<DWORD>(proc_info->UniqueProcessId) == proc_id) { - *hard_fault_count = proc_info->HardFaultCount; - return true; - } - // The list ends when NextEntryOffset is zero. This also prevents busy - // looping if the data is in fact invalid. - if (proc_info->NextEntryOffset <= 0) - return false; - index += proc_info->NextEntryOffset; - } - - return false; -} - -#endif // defined(OS_WIN) - - -// Helper macro for splitting out an UMA histogram based on cold or warm start. -// |type| is the histogram type, and corresponds to an UMA macro like -// UMA_HISTOGRAM_LONG_TIMES. It must be itself be a macro that only takes two -// parameters. -// |basename| is the basename of the histogram. A histogram of this name will -// always be recorded to. If the startup is either cold or warm then a value -// will also be recorded to the histogram with name |basename| and suffix -// ".ColdStart" or ".WarmStart", as appropriate. -// |value_expr| is an expression evaluating to the value to be recorded. This -// will be evaluated exactly once and cached, so side effects are not an issue. -#define UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(type, basename, value_expr) \ - { \ - const auto kValue = value_expr; \ - /* Always record to the base histogram. */ \ - type(basename, kValue); \ - /* Record to the cold/warm suffixed histogram as appropriate. */ \ - if (g_startup_temperature == COLD_STARTUP_TEMPERATURE) { \ - type(basename ".ColdStartup", kValue); \ - } else if (g_startup_temperature == WARM_STARTUP_TEMPERATURE) { \ - type(basename ".WarmStartup", kValue); \ - } \ - } - -#define UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(type, basename, \ - begin_time, end_time) \ - { \ - UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(type, basename, \ - end_time - begin_time) \ - TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1( \ - "startup", basename, 0, \ - StartupTimeToTraceTicks(begin_time).ToInternalValue(), "Temperature", \ - g_startup_temperature); \ - TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP1( \ - "startup", basename, 0, \ - StartupTimeToTraceTicks(end_time).ToInternalValue(), "Temperature", \ - g_startup_temperature); \ - } - -// On Windows, records the number of hard-faults that have occurred in the -// current chrome.exe process since it was started. This is a nop on other -// platforms. -// crbug.com/476923 -// TODO(chrisha): If this proves useful, use it to split startup stats in two. -void RecordHardFaultHistogram(bool is_first_run) { -#if defined(OS_WIN) - uint32_t hard_fault_count = 0; - bool has_os_support = false; - bool success = GetHardFaultCountForCurrentProcess( - &hard_fault_count, &has_os_support); - - // Log whether or not the system call was successful, assuming the OS was - // detected to support it. - if (has_os_support) { - UMA_HISTOGRAM_BOOLEAN( - "Startup.BrowserMessageLoopStartHardFaultCount.Success", - success); - } - - // Don't log a histogram value if unable to get the hard fault count. - if (!success) - return; - - // Hard fault counts are expected to be in the thousands range, - // corresponding to faulting in ~10s of MBs of code ~10s of KBs at a time. - // (Observed to vary from 1000 to 10000 on various test machines and - // platforms.) - if (is_first_run) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Startup.BrowserMessageLoopStartHardFaultCount.FirstRun", - hard_fault_count, - 0, 40000, 50); - } else { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Startup.BrowserMessageLoopStartHardFaultCount", - hard_fault_count, - 0, 40000, 50); - } - - // Determine the startup type based on the number of observed hard faults. - DCHECK_EQ(UNCERTAIN_STARTUP_TEMPERATURE, g_startup_temperature); - if (hard_fault_count < WARM_START_HARD_FAULT_COUNT_THRESHOLD) { - g_startup_temperature = WARM_STARTUP_TEMPERATURE; - } else if (hard_fault_count >= COLD_START_HARD_FAULT_COUNT_THRESHOLD) { - g_startup_temperature = COLD_STARTUP_TEMPERATURE; - } - - // Record the startup 'temperature'. - UMA_HISTOGRAM_ENUMERATION( - "Startup.Temperature", g_startup_temperature, STARTUP_TEMPERATURE_MAX); -#endif // defined(OS_WIN) -} - -// Converts a base::Time value to a base::TraceTicks value. The conversion isn't -// exact, but is within the time delta taken to synchronously resolve -// base::Time::Now() and base::TraceTicks::Now() which in practice is pretty -// much instant compared to multi-seconds startup timings. -// TODO(gab): Find a precise way to do this (http://crbug.com/544131). -base::TraceTicks StartupTimeToTraceTicks(const base::Time& time) { - // First get a base which represents the same point in time in both units. - // The wall clock time it takes to gather both of these is the precision of - // this method. - static const base::Time time_base = base::Time::Now(); - static const base::TraceTicks trace_ticks_base = base::TraceTicks::Now(); - - // Then use the TimeDelta common ground between the two units to make the - // conversion. - const base::TimeDelta delta_since_base = time_base - time; - return trace_ticks_base - delta_since_base; -} - -// Record time of main entry so it can be read from Telemetry performance tests. -// TODO(jeremy): Remove once crbug.com/317481 is fixed. -void RecordMainEntryTimeHistogram() { - const int kLowWordMask = 0xFFFFFFFF; - const int kLower31BitsMask = 0x7FFFFFFF; - DCHECK(!MainEntryPointTime().is_null()); - base::TimeDelta browser_main_entry_time_absolute = - MainEntryPointTime() - base::Time::UnixEpoch(); - - uint64 browser_main_entry_time_raw_ms = - browser_main_entry_time_absolute.InMilliseconds(); - - base::TimeDelta browser_main_entry_time_raw_ms_high_word = - base::TimeDelta::FromMilliseconds( - (browser_main_entry_time_raw_ms >> 32) & kLowWordMask); - // Shift by one because histograms only support non-negative values. - base::TimeDelta browser_main_entry_time_raw_ms_low_word = - base::TimeDelta::FromMilliseconds( - (browser_main_entry_time_raw_ms >> 1) & kLower31BitsMask); - - // A timestamp is a 64 bit value, yet histograms can only store 32 bits. - LOCAL_HISTOGRAM_TIMES("Startup.BrowserMainEntryTimeAbsoluteHighWord", - browser_main_entry_time_raw_ms_high_word); - LOCAL_HISTOGRAM_TIMES("Startup.BrowserMainEntryTimeAbsoluteLowWord", - browser_main_entry_time_raw_ms_low_word); -} - -// Environment variable that stores the timestamp when the executable's main() -// function was entered. -const char kChromeMainTimeEnvVar[] = "CHROME_MAIN_TIME"; - -// Returns the time of main entry recorded from RecordExeMainEntryTime. -base::Time ExeMainEntryPointTime() { - scoped_ptr<base::Environment> env(base::Environment::Create()); - std::string time_string; - int64 time_int = 0; - if (env->GetVar(kChromeMainTimeEnvVar, &time_string) && - base::StringToInt64(time_string, &time_int)) { - return base::Time::FromInternalValue(time_int); - } - return base::Time(); -} - -} // namespace - -bool WasNonBrowserUIDisplayed() { - return g_non_browser_ui_displayed; -} - -void SetNonBrowserUIDisplayed() { - g_non_browser_ui_displayed = true; -} - -void RecordStartupProcessCreationTime(const base::Time& time) { - DCHECK(g_process_creation_time.Get().is_null()); - g_process_creation_time.Get() = time; - DCHECK(!g_process_creation_time.Get().is_null()); -} - -void RecordMainEntryPointTime(const base::Time& time) { - DCHECK(MainEntryPointTime().is_null()); - g_main_entry_point_time.Get() = time; - DCHECK(!MainEntryPointTime().is_null()); -} - -void RecordExeMainEntryPointTime(const base::Time& time) { - std::string exe_load_time = base::Int64ToString(time.ToInternalValue()); - scoped_ptr<base::Environment> env(base::Environment::Create()); - env->SetVar(kChromeMainTimeEnvVar, exe_load_time); -} - -void RecordBrowserMainMessageLoopStart(const base::Time& time, - bool is_first_run) { - RecordHardFaultHistogram(is_first_run); - RecordMainEntryTimeHistogram(); - - const base::Time& process_creation_time = g_process_creation_time.Get(); - if (!is_first_run && !process_creation_time.is_null()) { - UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( - UMA_HISTOGRAM_LONG_TIMES_100, "Startup.BrowserMessageLoopStartTime", - process_creation_time, time); - } - - // Bail if uptime < 7 minutes, to filter out cases where Chrome may have been - // autostarted and the machine is under io pressure. - const int64 kSevenMinutesInMilliseconds = - base::TimeDelta::FromMinutes(7).InMilliseconds(); - if (base::SysInfo::Uptime() < kSevenMinutesInMilliseconds) - return; - - // The Startup.BrowserMessageLoopStartTime histogram exhibits instability in - // the field which limits its usefulness in all scenarios except when we have - // a very large sample size. Attempt to mitigate this with a new metric: - // * Measure time from main entry rather than the OS' notion of process start. - // * Only measure launches that occur 7 minutes after boot to try to avoid - // cases where Chrome is auto-started and IO is heavily loaded. - const base::Time dll_main_time = MainEntryPointTime(); - if (is_first_run) { - UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( - UMA_HISTOGRAM_LONG_TIMES, - "Startup.BrowserMessageLoopStartTimeFromMainEntry.FirstRun", - dll_main_time, time); - } else { - UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( - UMA_HISTOGRAM_LONG_TIMES, - "Startup.BrowserMessageLoopStartTimeFromMainEntry", dll_main_time, - time); - } - - // Record timings between process creation, the main() in the executable being - // reached and the main() in the shared library being reached. - if (!process_creation_time.is_null()) { - const base::Time exe_main_time = ExeMainEntryPointTime(); - if (!exe_main_time.is_null()) { - // Process create to chrome.exe:main(). - UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( - UMA_HISTOGRAM_LONG_TIMES, "Startup.LoadTime.ProcessCreateToExeMain", - process_creation_time, exe_main_time); - - // chrome.exe:main() to chrome.dll:main(). - UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( - UMA_HISTOGRAM_LONG_TIMES, "Startup.LoadTime.ExeMainToDllMain", - exe_main_time, dll_main_time); - - // Process create to chrome.dll:main(). Reported as a histogram only as - // the other two events above are sufficient for tracing purposes. - UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE( - UMA_HISTOGRAM_LONG_TIMES, "Startup.LoadTime.ProcessCreateToDllMain", - dll_main_time - process_creation_time); - } - } -} - -void RecordBrowserWindowDisplay(const base::Time& time) { - static bool is_first_call = true; - if (!is_first_call || time.is_null()) - return; - is_first_call = false; - if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null()) - return; - - UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( - UMA_HISTOGRAM_LONG_TIMES, "Startup.BrowserWindowDisplay", - g_process_creation_time.Get(), time); -} - -void RecordBrowserOpenTabsDelta(const base::TimeDelta& delta) { - static bool is_first_call = true; - if (!is_first_call) - return; - is_first_call = false; - - UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(UMA_HISTOGRAM_LONG_TIMES_100, - "Startup.BrowserOpenTabs", delta); -} - -void RecordFirstWebContentsMainFrameLoad(const base::Time& time) { - static bool is_first_call = true; - if (!is_first_call || time.is_null()) - return; - is_first_call = false; - if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null()) - return; - - UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( - UMA_HISTOGRAM_LONG_TIMES_100, "Startup.FirstWebContents.MainFrameLoad2", - g_process_creation_time.Get(), time); -} - -void RecordDeprecatedFirstWebContentsMainFrameLoad(const base::Time& time) { - static bool is_first_call = true; - if (!is_first_call || time.is_null()) - return; - is_first_call = false; - if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null()) - return; - - UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE( - UMA_HISTOGRAM_LONG_TIMES_100, "Startup.FirstWebContents.MainFrameLoad", - time - g_process_creation_time.Get()); -} - -void RecordFirstWebContentsNonEmptyPaint(const base::Time& time) { - static bool is_first_call = true; - if (!is_first_call || time.is_null()) - return; - is_first_call = false; - if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null()) - return; - - UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( - UMA_HISTOGRAM_LONG_TIMES_100, "Startup.FirstWebContents.NonEmptyPaint2", - g_process_creation_time.Get(), time); -} - -void RecordDeprecatedFirstWebContentsNonEmptyPaint(const base::Time& time) { - static bool is_first_call = true; - if (!is_first_call || time.is_null()) - return; - is_first_call = false; - if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null()) - return; - - UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE( - UMA_HISTOGRAM_LONG_TIMES_100, "Startup.FirstWebContents.NonEmptyPaint", - time - g_process_creation_time.Get()); -} - -void RecordFirstWebContentsMainNavigationStart(const base::Time& time) { - static bool is_first_call = true; - if (!is_first_call || time.is_null()) - return; - is_first_call = false; - if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null()) - return; - - UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( - UMA_HISTOGRAM_LONG_TIMES_100, - "Startup.FirstWebContents.MainNavigationStart", - g_process_creation_time.Get(), time); -} - -void RecordFirstWebContentsMainNavigationFinished(const base::Time& time) { - static bool is_first_call = true; - if (!is_first_call || time.is_null()) - return; - is_first_call = false; - if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null()) - return; - - UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( - UMA_HISTOGRAM_LONG_TIMES_100, - "Startup.FirstWebContents.MainNavigationFinished", - g_process_creation_time.Get(), time); -} - -base::Time MainEntryPointTime() { - return g_main_entry_point_time.Get(); -} - -StartupTemperature GetStartupTemperature() { - return g_startup_temperature; -} - -} // namespace startup_metric_utils
diff --git a/components/startup_metric_utils/startup_metric_utils.h b/components/startup_metric_utils/startup_metric_utils.h deleted file mode 100644 index 684046c..0000000 --- a/components/startup_metric_utils/startup_metric_utils.h +++ /dev/null
@@ -1,107 +0,0 @@ -// Copyright 2013 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_STARTUP_METRIC_UTILS_STARTUP_METRIC_UTILS_H_ -#define COMPONENTS_STARTUP_METRIC_UTILS_STARTUP_METRIC_UTILS_H_ - -#include <string> - -#include "base/time/time.h" - -// Utility functions to support metric collection for browser startup. - -namespace startup_metric_utils { - -// An enumeration of startup temperatures. This must be kept in sync with the -// UMA StartupType enumeration defined in histograms.xml. -enum StartupTemperature { - // The startup was a cold start: nearly all of the Chrome binaries and - // resources were brought into memory using hard faults. - COLD_STARTUP_TEMPERATURE = 0, - // The startup was a warm start: the Chrome binaries and resources were - // mostly already resident in memory and effectively no hard faults were - // observed. - WARM_STARTUP_TEMPERATURE = 1, - // The startup type couldn't quite be classified as warm of cold, but rather - // was somewhere in between. - UNCERTAIN_STARTUP_TEMPERATURE = 2, - // This must be last. - STARTUP_TEMPERATURE_MAX -}; - -// Returns true if any UI other than the browser window has been displayed -// so far. Useful to test if UI has been displayed before the first browser -// window was shown, which would invalidate any surrounding timing metrics. -bool WasNonBrowserUIDisplayed(); - -// Call this when displaying UI that might potentially delay the appearance -// of the initial browser window on Chrome startup. -// -// Note on usage: This function is idempotent and its overhead is low enough -// in comparison with UI display that it's OK to call it on every -// UI invocation regardless of whether the browser window has already -// been displayed or not. -void SetNonBrowserUIDisplayed(); - -// Call this with the creation time of the startup (initial/main) process. -void RecordStartupProcessCreationTime(const base::Time& time); - -// Call this with a time recorded as early as possible in the startup process. -// On Android, the entry point time is the time at which the Java code starts. -// In Mojo, the entry point time is the time at which the shell starts. -void RecordMainEntryPointTime(const base::Time& time); - -// Call this with the time when the executable is loaded and main() is entered. -// Can be different from |RecordMainEntryPointTime| when the startup process is -// contained in a separate dll, such as with chrome.exe / chrome.dll on Windows. -void RecordExeMainEntryPointTime(const base::Time& time); - -// Call this with the time recorded just before the message loop is started. -// |is_first_run| - is the current launch part of a first run. -void RecordBrowserMainMessageLoopStart(const base::Time& time, - bool is_first_run); - -// Call this with the time when the first browser window became visible. -void RecordBrowserWindowDisplay(const base::Time& time); - -// Call this with the time delta that the browser spent opening its tabs. -void RecordBrowserOpenTabsDelta(const base::TimeDelta& delta); - -// Call this with the time when the first web contents loaded its main frame, -// only if the first web contents was unimpended in its attempt to do so. -void RecordFirstWebContentsMainFrameLoad(const base::Time& time); - -// Call this with the time when the first web contents loaded its main frame. -// This records an old stat kept for comparison purposes until M49. -void RecordDeprecatedFirstWebContentsMainFrameLoad(const base::Time& time); - -// Call this with the time when the first web contents had a non-empty paint, -// only if the first web contents was unimpended in its attempt to do so. -void RecordFirstWebContentsNonEmptyPaint(const base::Time& time); - -// Call this with the time when the first web contents had a non-empty paint. -// This records an old stat kept for comparison purposes until M49. -void RecordDeprecatedFirstWebContentsNonEmptyPaint(const base::Time& time); - -// Call this with the time when the first web contents began navigating its main -// frame. -void RecordFirstWebContentsMainNavigationStart(const base::Time& time); - -// Call this with the time when the first web contents successfully committed -// its navigation for the main frame. -void RecordFirstWebContentsMainNavigationFinished(const base::Time& time); - -// Returns the time of main entry recorded from RecordMainEntryPointTime. -// Returns a null Time if a value has not been recorded yet. -// This method is expected to be called from the UI thread. -base::Time MainEntryPointTime(); - -// Returns the startup type. This is only currently supported on the Windows -// platform and will simply return UNCERTAIN_STARTUP_TYPE on other platforms. -// This is only valid after a call to RecordBrowserMainMessageLoopStart(). -StartupTemperature GetStartupTemperature(); - -} // namespace startup_metric_utils - -#endif // COMPONENTS_STARTUP_METRIC_UTILS_STARTUP_METRIC_UTILS_H_
diff --git a/components/sync_sessions.gypi b/components/sync_sessions.gypi index 6227235b..1e69018 100644 --- a/components/sync_sessions.gypi +++ b/components/sync_sessions.gypi
@@ -13,6 +13,7 @@ ], 'dependencies': [ '../base/base.gyp:base', + '../base/base.gyp:base_prefs', '../sync/sync.gyp:sync', '../url/url.gyp:url_lib', 'bookmarks_browser', @@ -28,24 +29,30 @@ 'sync_sessions/revisit/bookmarks_by_url_provider_impl.h', 'sync_sessions/revisit/bookmarks_page_revisit_observer.cc', 'sync_sessions/revisit/bookmarks_page_revisit_observer.h', - 'sync_sessions/synced_tab_delegate.cc', - 'sync_sessions/synced_tab_delegate.h', - 'sync_sessions/synced_session_tracker.cc', - 'sync_sessions/synced_session_tracker.h', - 'sync_sessions/sync_sessions_client.cc', - 'sync_sessions/sync_sessions_client.h', 'sync_sessions/revisit/current_tab_matcher.cc', 'sync_sessions/revisit/current_tab_matcher.h', 'sync_sessions/revisit/offset_tab_matcher.cc', 'sync_sessions/revisit/offset_tab_matcher.h', 'sync_sessions/revisit/page_equality.h', 'sync_sessions/revisit/page_visit_observer.h', + 'sync_sessions/revisit/page_revisit_broadcaster.cc', + 'sync_sessions/revisit/page_revisit_broadcaster.h', 'sync_sessions/revisit/sessions_page_revisit_observer.cc', 'sync_sessions/revisit/sessions_page_revisit_observer.h', 'sync_sessions/revisit/typed_url_page_revisit_observer.cc', 'sync_sessions/revisit/typed_url_page_revisit_observer.h', 'sync_sessions/revisit/typed_url_page_revisit_task.cc', 'sync_sessions/revisit/typed_url_page_revisit_task.h', + 'sync_sessions/session_data_type_controller.cc', + 'sync_sessions/session_data_type_controller.h', + 'sync_sessions/sessions_sync_manager.cc', + 'sync_sessions/sessions_sync_manager.h', + 'sync_sessions/synced_tab_delegate.cc', + 'sync_sessions/synced_tab_delegate.h', + 'sync_sessions/synced_session_tracker.cc', + 'sync_sessions/synced_session_tracker.h', + 'sync_sessions/sync_sessions_client.cc', + 'sync_sessions/sync_sessions_client.h', ], 'conditions': [ ['OS!="ios"', {
diff --git a/components/sync_sessions/BUILD.gn b/components/sync_sessions/BUILD.gn index a2fd2fb..2881335 100644 --- a/components/sync_sessions/BUILD.gn +++ b/components/sync_sessions/BUILD.gn
@@ -17,6 +17,8 @@ "revisit/offset_tab_matcher.cc", "revisit/offset_tab_matcher.h", "revisit/page_equality.h", + "revisit/page_revisit_broadcaster.cc", + "revisit/page_revisit_broadcaster.h", "revisit/page_visit_observer.h", "revisit/sessions_page_revisit_observer.cc", "revisit/sessions_page_revisit_observer.h", @@ -24,6 +26,10 @@ "revisit/typed_url_page_revisit_observer.h", "revisit/typed_url_page_revisit_task.cc", "revisit/typed_url_page_revisit_task.h", + "session_data_type_controller.cc", + "session_data_type_controller.h", + "sessions_sync_manager.cc", + "sessions_sync_manager.h", "sync_sessions_client.cc", "sync_sessions_client.h", "synced_session_tracker.cc", @@ -34,13 +40,15 @@ deps = [ "//base", + "//base:prefs", "//components/bookmarks/browser", "//components/favicon/core", "//components/history/core/browser", "//components/sessions", "//components/sync_driver", + "//components/variations", "//sync", - "//ui/base", + "//ui/base:base", "//ui/gfx", "//url", ] @@ -69,23 +77,29 @@ "revisit/bookmarks_page_revisit_observer_unittest.cc", "revisit/current_tab_matcher_unittest.cc", "revisit/offset_tab_matcher_unittest.cc", + "revisit/page_revisit_broadcaster_unittest.cc", "revisit/sessions_page_revisit_observer_unittest.cc", "revisit/typed_url_page_revisit_task_unittest.cc", + "session_data_type_controller_unittest.cc", "synced_session_tracker_unittest.cc", ] deps = [ ":sync_sessions", ":test_support", + "//base:prefs", + "//base:prefs_test_support", "//base/test:test_support", "//testing/gmock", "//components/bookmarks/browser", "//components/history/core/browser", "//components/sessions:test_support", "//components/sync_driver", + "//components/sync_driver:test_support", "//testing/gtest", "//sync", "//sync:test_support_sync_api", + "//ui/base:base", "//url", ] }
diff --git a/components/sync_sessions/DEPS b/components/sync_sessions/DEPS index 92906e7..00098e0 100644 --- a/components/sync_sessions/DEPS +++ b/components/sync_sessions/DEPS
@@ -4,6 +4,7 @@ "+components/history/core/browser", "+components/sessions", "+components/sync_driver", + "+components/variations", "+sync", "+ui/base/page_transition_types.h", "+ui/gfx",
diff --git a/components/sync_sessions/fake_sync_sessions_client.cc b/components/sync_sessions/fake_sync_sessions_client.cc index ca573a7..9471d98e 100644 --- a/components/sync_sessions/fake_sync_sessions_client.cc +++ b/components/sync_sessions/fake_sync_sessions_client.cc
@@ -12,6 +12,18 @@ FakeSyncSessionsClient::FakeSyncSessionsClient() {} FakeSyncSessionsClient::~FakeSyncSessionsClient() {} +bookmarks::BookmarkModel* FakeSyncSessionsClient::GetBookmarkModel() { + return nullptr; +} + +favicon::FaviconService* FakeSyncSessionsClient::GetFaviconService() { + return nullptr; +} + +history::HistoryService* FakeSyncSessionsClient::GetHistoryService() { + return nullptr; +} + bool FakeSyncSessionsClient::ShouldSyncURL(const GURL& url) const { return url.is_valid(); }
diff --git a/components/sync_sessions/fake_sync_sessions_client.h b/components/sync_sessions/fake_sync_sessions_client.h index 5d6a5fa0..5e332b8f 100644 --- a/components/sync_sessions/fake_sync_sessions_client.h +++ b/components/sync_sessions/fake_sync_sessions_client.h
@@ -17,6 +17,9 @@ ~FakeSyncSessionsClient() override; // SyncSessionsClient: + bookmarks::BookmarkModel* GetBookmarkModel() override; + favicon::FaviconService* GetFaviconService() override; + history::HistoryService* GetHistoryService() override; bool ShouldSyncURL(const GURL& url) const override; browser_sync::SyncedWindowDelegatesGetter* GetSyncedWindowDelegatesGetter() override;
diff --git a/components/sync_sessions/revisit/page_revisit_broadcaster.cc b/components/sync_sessions/revisit/page_revisit_broadcaster.cc new file mode 100644 index 0000000..094e666 --- /dev/null +++ b/components/sync_sessions/revisit/page_revisit_broadcaster.cc
@@ -0,0 +1,136 @@ +// Copyright 2015 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/sync_sessions/revisit/page_revisit_broadcaster.h" + +#include <string> +#include <vector> + +#include "base/memory/scoped_ptr.h" +#include "base/metrics/field_trial.h" +#include "components/bookmarks/browser/bookmark_model.h" +#include "components/history/core/browser/history_service.h" +#include "components/sync_sessions/revisit/bookmarks_by_url_provider_impl.h" +#include "components/sync_sessions/revisit/bookmarks_page_revisit_observer.h" +#include "components/sync_sessions/revisit/sessions_page_revisit_observer.h" +#include "components/sync_sessions/revisit/typed_url_page_revisit_observer.h" +#include "components/sync_sessions/sessions_sync_manager.h" +#include "components/sync_sessions/sync_sessions_client.h" + +namespace browser_sync { + +namespace { + +// Simple implementation of ForeignSessionsProvider that delegates to +// SessionsSyncManager. It holds onto a non-owning pointer, with the assumption +// that this class is only used by classes owned by SessionsSyncManager itself. +class SessionsSyncManagerWrapper + : public sync_sessions::ForeignSessionsProvider { + public: + explicit SessionsSyncManagerWrapper(SessionsSyncManager* manager) + : manager_(manager) {} + ~SessionsSyncManagerWrapper() override{}; + bool GetAllForeignSessions( + std::vector<const sync_driver::SyncedSession*>* sessions) override { + return manager_->GetAllForeignSessions(sessions); + } + + private: + SessionsSyncManager* manager_; + DISALLOW_COPY_AND_ASSIGN(SessionsSyncManagerWrapper); +}; + +} // namespace + +PageRevisitBroadcaster::PageRevisitBroadcaster( + SessionsSyncManager* manager, + sync_sessions::SyncSessionsClient* sessions_client) + : sessions_client_(sessions_client) { + const std::string group_name = + base::FieldTrialList::FindFullName("PageRevisitInstrumentation"); + bool shouldInstrument = group_name == "Enabled"; + if (shouldInstrument) { + revisit_observers_.push_back(new sync_sessions::SessionsPageRevisitObserver( + scoped_ptr<sync_sessions::ForeignSessionsProvider>( + new SessionsSyncManagerWrapper(manager)))); + + history::HistoryService* history = sessions_client_->GetHistoryService(); + if (history) { + revisit_observers_.push_back( + new sync_sessions::TypedUrlPageRevisitObserver(history)); + } + + bookmarks::BookmarkModel* bookmarks = sessions_client_->GetBookmarkModel(); + if (bookmarks) { + revisit_observers_.push_back( + new sync_sessions::BookmarksPageRevisitObserver( + scoped_ptr<sync_sessions::BookmarksByUrlProvider>( + new sync_sessions::BookmarksByUrlProviderImpl(bookmarks)))); + } + } +} + +PageRevisitBroadcaster::~PageRevisitBroadcaster() {} + +void PageRevisitBroadcaster::OnPageVisit(const GURL& url, + const ui::PageTransition transition) { + if (sessions_client_->ShouldSyncURL(url)) { + sync_sessions::PageVisitObserver::TransitionType converted( + ConvertTransitionEnum(transition)); + for (auto* observer : revisit_observers_) { + observer->OnPageVisit(url, converted); + } + } +} + +// Static +sync_sessions::PageVisitObserver::TransitionType +PageRevisitBroadcaster::ConvertTransitionEnum( + const ui::PageTransition original) { + switch (ui::PageTransitionStripQualifier(original)) { + case ui::PAGE_TRANSITION_LINK: + if (original & ui::PAGE_TRANSITION_FROM_ADDRESS_BAR) { + return sync_sessions::PageVisitObserver::kTransitionCopyPaste; + } else { + return sync_sessions::PageVisitObserver::kTransitionPage; + } + case ui::PAGE_TRANSITION_TYPED: + return sync_sessions::PageVisitObserver::kTransitionOmniboxUrl; + + case ui::PAGE_TRANSITION_AUTO_BOOKMARK: + return sync_sessions::PageVisitObserver::kTransitionBookmark; + + case ui::PAGE_TRANSITION_AUTO_SUBFRAME: + case ui::PAGE_TRANSITION_MANUAL_SUBFRAME: + // These are not expected, we only expect top-level frame transitions. + return sync_sessions::PageVisitObserver::kTransitionUnknown; + + case ui::PAGE_TRANSITION_GENERATED: + return sync_sessions::PageVisitObserver::kTransitionOmniboxDefaultSearch; + + case ui::PAGE_TRANSITION_AUTO_TOPLEVEL: + if (original & ui::PAGE_TRANSITION_FORWARD_BACK) { + return sync_sessions::PageVisitObserver::kTransitionForwardBackward; + } else { + return sync_sessions::PageVisitObserver::kTransitionUnknown; + } + + case ui::PAGE_TRANSITION_FORM_SUBMIT: + return sync_sessions::PageVisitObserver::kTransitionPage; + + case ui::PAGE_TRANSITION_RELOAD: + // Refreshing pages also carry PAGE_TRANSITION_RELOAD but the url never + // changes so we don't expect to ever get them. + return sync_sessions::PageVisitObserver::kTransitionRestore; + + case ui::PAGE_TRANSITION_KEYWORD: + case ui::PAGE_TRANSITION_KEYWORD_GENERATED: + return sync_sessions::PageVisitObserver::kTransitionOmniboxTemplateSearch; + + default: + return sync_sessions::PageVisitObserver::kTransitionUnknown; + } +} + +} // namespace browser_sync
diff --git a/components/sync_sessions/revisit/page_revisit_broadcaster.h b/components/sync_sessions/revisit/page_revisit_broadcaster.h new file mode 100644 index 0000000..8e56575 --- /dev/null +++ b/components/sync_sessions/revisit/page_revisit_broadcaster.h
@@ -0,0 +1,55 @@ +// Copyright 2015 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_SYNC_SESSIONS_REVISIT_PAGE_REVISIT_BROADCASTER_H_ +#define COMPONENTS_SYNC_SESSIONS_REVISIT_PAGE_REVISIT_BROADCASTER_H_ + +#include "base/macros.h" +#include "base/memory/scoped_vector.h" +#include "components/sync_sessions/revisit/page_visit_observer.h" +#include "ui/base/page_transition_types.h" +#include "url/gurl.h" + +namespace sync_sessions { +class SyncSessionsClient; +} + +namespace browser_sync { + +class SessionsSyncManager; + +// This class has the job of creating and holding onto the PageVisitObservers +// that are to be notified on page change for purposes of instrumenting +// revisists. +class PageRevisitBroadcaster { + public: + PageRevisitBroadcaster(SessionsSyncManager* manager, + sync_sessions::SyncSessionsClient* sessions_client); + ~PageRevisitBroadcaster(); + + // Broadcasts to all observers the given page visit event. Should only be + // called when the url changes. + void OnPageVisit(const GURL& url, const ui::PageTransition transition); + + private: + friend class SyncPageRevisitBroadcasterTest; + + // We convert between enums here for a couple reasons. We don't want to force + // observers to depend on ui/, and the high bit masks don't work for emitting + // histograms. Some of the high bit masks correspond to cases we're + // particularly interested in and want to treat as first class values. + static sync_sessions::PageVisitObserver::TransitionType ConvertTransitionEnum( + const ui::PageTransition original); + + // The client of this sync sessions datatype. + sync_sessions::SyncSessionsClient* const sessions_client_; + + ScopedVector<sync_sessions::PageVisitObserver> revisit_observers_; + + DISALLOW_COPY_AND_ASSIGN(PageRevisitBroadcaster); +}; + +} // namespace browser_sync + +#endif // COMPONENTS_SYNC_SESSIONS_REVISIT_PAGE_REVISIT_BROADCASTER_H_
diff --git a/components/sync_sessions/revisit/page_revisit_broadcaster_unittest.cc b/components/sync_sessions/revisit/page_revisit_broadcaster_unittest.cc new file mode 100644 index 0000000..95185474 --- /dev/null +++ b/components/sync_sessions/revisit/page_revisit_broadcaster_unittest.cc
@@ -0,0 +1,110 @@ +// Copyright 2015 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/sync_sessions/revisit/page_revisit_broadcaster.h" + +#include "components/sync_sessions/revisit/page_visit_observer.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/page_transition_types.h" + +using sync_sessions::PageVisitObserver; + +namespace browser_sync { + +class SyncPageRevisitBroadcasterTest : public ::testing::Test { + protected: + PageVisitObserver::TransitionType Convert( + const ui::PageTransition conversionInput) { + return PageRevisitBroadcaster::ConvertTransitionEnum(conversionInput); + } + + void Check(const PageVisitObserver::TransitionType expected, + const ui::PageTransition conversionInput) { + EXPECT_EQ(expected, Convert(conversionInput)); + } + + void Check(const PageVisitObserver::TransitionType expected, + const int32 conversionInput) { + Check(expected, ui::PageTransitionFromInt(conversionInput)); + } +}; + +TEST_F(SyncPageRevisitBroadcasterTest, ConvertPageInteraction) { + Check(PageVisitObserver::kTransitionPage, ui::PAGE_TRANSITION_LINK); + Check(PageVisitObserver::kTransitionPage, + ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_BLOCKED); + Check(PageVisitObserver::kTransitionPage, + ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_FORWARD_BACK); + // Don't check ui::PAGE_TRANSITION_FROM_ADDRESS_BAR, this is actually a copy + // and paste action when combined with ui::PAGE_TRANSITION_LINK. + Check(PageVisitObserver::kTransitionPage, + ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_HOME_PAGE); + Check(PageVisitObserver::kTransitionPage, + ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_FROM_API); + Check(PageVisitObserver::kTransitionPage, + ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CHAIN_START); + Check(PageVisitObserver::kTransitionPage, + ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CHAIN_END); + Check(PageVisitObserver::kTransitionPage, + ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT); + Check(PageVisitObserver::kTransitionPage, + ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_SERVER_REDIRECT); + Check(PageVisitObserver::kTransitionPage, + ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_IS_REDIRECT_MASK); +} + +TEST_F(SyncPageRevisitBroadcasterTest, ConvertOmniboxURL) { + Check(PageVisitObserver::kTransitionOmniboxUrl, ui::PAGE_TRANSITION_TYPED); + Check(PageVisitObserver::kTransitionOmniboxUrl, + ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); +} + +TEST_F(SyncPageRevisitBroadcasterTest, ConvertOmniboxDefaultSearch) { + Check(PageVisitObserver::kTransitionOmniboxDefaultSearch, + ui::PAGE_TRANSITION_GENERATED); + Check(PageVisitObserver::kTransitionOmniboxDefaultSearch, + ui::PAGE_TRANSITION_GENERATED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); +} + +TEST_F(SyncPageRevisitBroadcasterTest, ConvertOmniboxTemplateSearch) { + Check(PageVisitObserver::kTransitionOmniboxTemplateSearch, + ui::PAGE_TRANSITION_KEYWORD); + Check(PageVisitObserver::kTransitionOmniboxTemplateSearch, + ui::PAGE_TRANSITION_KEYWORD | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); + Check(PageVisitObserver::kTransitionOmniboxTemplateSearch, + ui::PAGE_TRANSITION_KEYWORD_GENERATED); + Check(PageVisitObserver::kTransitionOmniboxTemplateSearch, + ui::PAGE_TRANSITION_KEYWORD_GENERATED | + ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); +} + +TEST_F(SyncPageRevisitBroadcasterTest, ConvertBookmark) { + Check(PageVisitObserver::kTransitionBookmark, + ui::PAGE_TRANSITION_AUTO_BOOKMARK); +} + +TEST_F(SyncPageRevisitBroadcasterTest, ConvertCopyPaste) { + Check(PageVisitObserver::kTransitionCopyPaste, + ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); +} + +TEST_F(SyncPageRevisitBroadcasterTest, ConvertForwardBackward) { + Check(PageVisitObserver::kTransitionForwardBackward, + ui::PAGE_TRANSITION_AUTO_TOPLEVEL | ui::PAGE_TRANSITION_FORWARD_BACK); +} + +TEST_F(SyncPageRevisitBroadcasterTest, ConvertRestore) { + Check(PageVisitObserver::kTransitionRestore, ui::PAGE_TRANSITION_RELOAD); +} + +TEST_F(SyncPageRevisitBroadcasterTest, ConvertUnknown) { + Check(PageVisitObserver::kTransitionUnknown, + ui::PAGE_TRANSITION_AUTO_SUBFRAME); + Check(PageVisitObserver::kTransitionUnknown, + ui::PAGE_TRANSITION_MANUAL_SUBFRAME); + Check(PageVisitObserver::kTransitionUnknown, + ui::PAGE_TRANSITION_AUTO_TOPLEVEL); +} + +} // namespace browser_sync
diff --git a/components/sync_sessions/session_data_type_controller.cc b/components/sync_sessions/session_data_type_controller.cc new file mode 100644 index 0000000..4bcbfbf28 --- /dev/null +++ b/components/sync_sessions/session_data_type_controller.cc
@@ -0,0 +1,113 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/sync_sessions/session_data_type_controller.h" + +#include "base/prefs/pref_service.h" +#include "components/sync_driver/glue/synced_window_delegate.h" +#include "components/sync_driver/sessions/synced_window_delegates_getter.h" +#include "components/sync_driver/sync_client.h" + +namespace browser_sync { + +SessionDataTypeController::SessionDataTypeController( + const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread, + const base::Closure& error_callback, + sync_driver::SyncClient* sync_client, + SyncedWindowDelegatesGetter* synced_window_getter, + sync_driver::LocalDeviceInfoProvider* local_device, + const char* history_disabled_pref_name) + : UIDataTypeController(ui_thread, + error_callback, + syncer::SESSIONS, + sync_client), + sync_client_(sync_client), + synced_window_getter_(synced_window_getter), + local_device_(local_device), + history_disabled_pref_name_(history_disabled_pref_name), + waiting_on_session_restore_(false), + waiting_on_local_device_info_(false) { + DCHECK(local_device_); + pref_registrar_.Init(sync_client_->GetPrefService()); + pref_registrar_.Add( + history_disabled_pref_name_, + base::Bind(&SessionDataTypeController::OnSavingBrowserHistoryPrefChanged, + base::Unretained(this))); +} + +SessionDataTypeController::~SessionDataTypeController() {} + +bool SessionDataTypeController::StartModels() { + DCHECK(ui_thread()->BelongsToCurrentThread()); + std::set<const browser_sync::SyncedWindowDelegate*> window = + synced_window_getter_->GetSyncedWindowDelegates(); + for (std::set<const browser_sync::SyncedWindowDelegate*>::const_iterator i = + window.begin(); + i != window.end(); ++i) { + if ((*i)->IsSessionRestoreInProgress()) { + waiting_on_session_restore_ = true; + break; + } + } + + if (!local_device_->GetLocalDeviceInfo()) { + subscription_ = local_device_->RegisterOnInitializedCallback(base::Bind( + &SessionDataTypeController::OnLocalDeviceInfoInitialized, this)); + waiting_on_local_device_info_ = true; + } + + return !IsWaiting(); +} + +void SessionDataTypeController::StopModels() { + subscription_.reset(); +} + +bool SessionDataTypeController::ReadyForStart() const { + DCHECK(ui_thread()->BelongsToCurrentThread()); + return !sync_client_->GetPrefService()->GetBoolean( + history_disabled_pref_name_); +} + +void SessionDataTypeController::OnSessionRestoreComplete() { + DCHECK(ui_thread()->BelongsToCurrentThread()); + waiting_on_session_restore_ = false; + MaybeCompleteLoading(); +} + +bool SessionDataTypeController::IsWaiting() { + return waiting_on_session_restore_ || waiting_on_local_device_info_; +} + +void SessionDataTypeController::MaybeCompleteLoading() { + if (state_ == MODEL_STARTING && !IsWaiting()) { + OnModelLoaded(); + } +} + +void SessionDataTypeController::OnLocalDeviceInfoInitialized() { + DCHECK(ui_thread()->BelongsToCurrentThread()); + subscription_.reset(); + + waiting_on_local_device_info_ = false; + MaybeCompleteLoading(); +} + +void SessionDataTypeController::OnSavingBrowserHistoryPrefChanged() { + DCHECK(ui_thread()->BelongsToCurrentThread()); + if (sync_client_->GetPrefService()->GetBoolean(history_disabled_pref_name_)) { + // If history and tabs persistence is turned off then generate an + // unrecoverable error. SESSIONS won't be a registered type on the next + // Chrome restart. + if (state() != NOT_RUNNING && state() != STOPPING) { + syncer::SyncError error( + FROM_HERE, syncer::SyncError::DATATYPE_POLICY_ERROR, + "History and tab saving is now disabled by policy.", + syncer::SESSIONS); + OnSingleDataTypeUnrecoverableError(error); + } + } +} + +} // namespace browser_sync
diff --git a/components/sync_sessions/session_data_type_controller.h b/components/sync_sessions/session_data_type_controller.h new file mode 100644 index 0000000..c42394d --- /dev/null +++ b/components/sync_sessions/session_data_type_controller.h
@@ -0,0 +1,68 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SYNC_SESSIONS_SESSION_DATA_TYPE_CONTROLLER_H_ +#define COMPONENTS_SYNC_SESSIONS_SESSION_DATA_TYPE_CONTROLLER_H_ + +#include "base/macros.h" +#include "base/prefs/pref_change_registrar.h" +#include "components/sync_driver/local_device_info_provider.h" +#include "components/sync_driver/ui_data_type_controller.h" + +namespace browser_sync { + +class SyncedWindowDelegatesGetter; + +// Overrides StartModels to avoid sync contention with sessions during +// a session restore operation at startup and to wait for the local +// device info to become available. +class SessionDataTypeController : public sync_driver::UIDataTypeController { + public: + SessionDataTypeController( + const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread, + const base::Closure& error_callback, + sync_driver::SyncClient* sync_client, + SyncedWindowDelegatesGetter* synced_window_getter, + sync_driver::LocalDeviceInfoProvider* local_device, + const char* history_disabled_pref_name); + + // UIDataTypeController interface. + bool StartModels() override; + void StopModels() override; + bool ReadyForStart() const override; + + // Called when asynchronous session restore has completed. + void OnSessionRestoreComplete(); + + protected: + ~SessionDataTypeController() override; + + private: + bool IsWaiting(); + void MaybeCompleteLoading(); + void OnLocalDeviceInfoInitialized(); + void OnSavingBrowserHistoryPrefChanged(); + + sync_driver::SyncClient* const sync_client_; + + SyncedWindowDelegatesGetter* synced_window_getter_; + + sync_driver::LocalDeviceInfoProvider* const local_device_; + scoped_ptr<sync_driver::LocalDeviceInfoProvider::Subscription> subscription_; + + // Name of the pref that indicates whether saving history is disabled. + const char* history_disabled_pref_name_; + + // Flags that indicate the reason for pending loading models. + bool waiting_on_session_restore_; + bool waiting_on_local_device_info_; + + PrefChangeRegistrar pref_registrar_; + + DISALLOW_COPY_AND_ASSIGN(SessionDataTypeController); +}; + +} // namespace browser_sync + +#endif // COMPONENTS_SYNC_SESSIONS_SESSION_DATA_TYPE_CONTROLLER_H_
diff --git a/components/sync_sessions/session_data_type_controller_unittest.cc b/components/sync_sessions/session_data_type_controller_unittest.cc new file mode 100644 index 0000000..fbbe7cb --- /dev/null +++ b/components/sync_sessions/session_data_type_controller_unittest.cc
@@ -0,0 +1,252 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/sync_sessions/session_data_type_controller.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/files/file_path.h" +#include "base/memory/weak_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/prefs/pref_registry_simple.h" +#include "base/prefs/testing_pref_service.h" +#include "base/run_loop.h" +#include "base/thread_task_runner_handle.h" +#include "components/sync_driver/fake_sync_client.h" +#include "components/sync_driver/glue/synced_window_delegate.h" +#include "components/sync_driver/local_device_info_provider_mock.h" +#include "components/sync_driver/sessions/synced_window_delegates_getter.h" +#include "components/sync_driver/sync_api_component_factory_mock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using sync_driver::LocalDeviceInfoProviderMock; + +namespace browser_sync { + +namespace { + +const char* kSavingBrowserHistoryDisabled = "history_disabled"; + +class MockSyncedWindowDelegate : public SyncedWindowDelegate { + public: + MockSyncedWindowDelegate() : is_restore_in_progress_(false) {} + ~MockSyncedWindowDelegate() override {} + + bool HasWindow() const override { return false; } + SessionID::id_type GetSessionId() const override { return 0; } + int GetTabCount() const override { return 0; } + int GetActiveIndex() const override { return 0; } + bool IsApp() const override { return false; } + bool IsTypeTabbed() const override { return false; } + bool IsTypePopup() const override { return false; } + bool IsTabPinned(const SyncedTabDelegate* tab) const override { + return false; + } + SyncedTabDelegate* GetTabAt(int index) const override { return NULL; } + SessionID::id_type GetTabIdAt(int index) const override { return 0; } + + bool IsSessionRestoreInProgress() const override { + return is_restore_in_progress_; + } + + bool ShouldSync() const override { return false; } + + void SetSessionRestoreInProgress(bool is_restore_in_progress) { + is_restore_in_progress_ = is_restore_in_progress; + } + + private: + bool is_restore_in_progress_; +}; + +class MockSyncedWindowDelegatesGetter : public SyncedWindowDelegatesGetter { + public: + std::set<const SyncedWindowDelegate*> GetSyncedWindowDelegates() override { + return delegates_; + } + + const SyncedWindowDelegate* FindById(SessionID::id_type id) override { + return nullptr; + } + + void Add(SyncedWindowDelegate* delegate) { delegates_.insert(delegate); } + + private: + std::set<const SyncedWindowDelegate*> delegates_; +}; + +class SessionDataTypeControllerTest : public testing::Test, + public sync_driver::FakeSyncClient { + public: + SessionDataTypeControllerTest() + : sync_driver::FakeSyncClient(&profile_sync_factory_), + load_finished_(false), + last_type_(syncer::UNSPECIFIED), + weak_ptr_factory_(this) {} + ~SessionDataTypeControllerTest() override {} + + // FakeSyncClient overrides. + PrefService* GetPrefService() override { return &prefs_; } + + void SetUp() override { + prefs_.registry()->RegisterBooleanPref(kSavingBrowserHistoryDisabled, + false); + + synced_window_delegate_.reset(new MockSyncedWindowDelegate()); + synced_window_getter_.reset(new MockSyncedWindowDelegatesGetter()); + synced_window_getter_->Add(synced_window_delegate_.get()); + + local_device_.reset(new LocalDeviceInfoProviderMock( + "cache_guid", "Wayne Gretzky's Hacking Box", "Chromium 10k", + "Chrome 10k", sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id")); + + controller_ = new SessionDataTypeController( + base::ThreadTaskRunnerHandle::Get(), base::Bind(&base::DoNothing), this, + synced_window_getter_.get(), local_device_.get(), + kSavingBrowserHistoryDisabled); + + load_finished_ = false; + last_type_ = syncer::UNSPECIFIED; + last_error_ = syncer::SyncError(); + } + + void TearDown() override { + controller_ = NULL; + local_device_.reset(); + synced_window_getter_.reset(); + synced_window_delegate_.reset(); + } + + void Start() { + controller_->LoadModels( + base::Bind(&SessionDataTypeControllerTest::OnLoadFinished, + weak_ptr_factory_.GetWeakPtr())); + } + + void OnLoadFinished(syncer::ModelType type, syncer::SyncError error) { + load_finished_ = true; + last_type_ = type; + last_error_ = error; + } + + testing::AssertionResult LoadResult() { + if (!load_finished_) { + return testing::AssertionFailure() << "OnLoadFinished wasn't called"; + } + + if (last_error_.IsSet()) { + return testing::AssertionFailure() + << "OnLoadFinished was called with a SyncError: " + << last_error_.ToString(); + } + + if (last_type_ != syncer::SESSIONS) { + return testing::AssertionFailure() + << "OnLoadFinished was called with a wrong sync type: " + << last_type_; + } + + return testing::AssertionSuccess(); + } + + protected: + void SetSessionRestoreInProgress(bool is_restore_in_progress) { + synced_window_delegate_->SetSessionRestoreInProgress( + is_restore_in_progress); + + if (!is_restore_in_progress) + controller_->OnSessionRestoreComplete(); + } + + scoped_refptr<SessionDataTypeController> controller_; + scoped_ptr<MockSyncedWindowDelegatesGetter> synced_window_getter_; + scoped_ptr<LocalDeviceInfoProviderMock> local_device_; + scoped_ptr<MockSyncedWindowDelegate> synced_window_delegate_; + bool load_finished_; + + private: + base::MessageLoop message_loop_; + TestingPrefServiceSimple prefs_; + SyncApiComponentFactoryMock profile_sync_factory_; + syncer::ModelType last_type_; + syncer::SyncError last_error_; + base::WeakPtrFactory<SessionDataTypeControllerTest> weak_ptr_factory_; +}; + +TEST_F(SessionDataTypeControllerTest, StartModels) { + Start(); + EXPECT_EQ(sync_driver::DataTypeController::MODEL_LOADED, + controller_->state()); + EXPECT_TRUE(LoadResult()); +} + +TEST_F(SessionDataTypeControllerTest, StartModelsDelayedByLocalDevice) { + local_device_->SetInitialized(false); + Start(); + EXPECT_FALSE(load_finished_); + EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, + controller_->state()); + + local_device_->SetInitialized(true); + EXPECT_EQ(sync_driver::DataTypeController::MODEL_LOADED, + controller_->state()); + EXPECT_TRUE(LoadResult()); +} + +TEST_F(SessionDataTypeControllerTest, StartModelsDelayedByRestoreInProgress) { + SetSessionRestoreInProgress(true); + Start(); + EXPECT_FALSE(load_finished_); + EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, + controller_->state()); + + SetSessionRestoreInProgress(false); + EXPECT_EQ(sync_driver::DataTypeController::MODEL_LOADED, + controller_->state()); + EXPECT_TRUE(LoadResult()); +} + +TEST_F(SessionDataTypeControllerTest, + StartModelsDelayedByLocalDeviceThenRestoreInProgress) { + local_device_->SetInitialized(false); + SetSessionRestoreInProgress(true); + Start(); + EXPECT_FALSE(load_finished_); + EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, + controller_->state()); + + local_device_->SetInitialized(true); + EXPECT_FALSE(load_finished_); + EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, + controller_->state()); + + SetSessionRestoreInProgress(false); + EXPECT_EQ(sync_driver::DataTypeController::MODEL_LOADED, + controller_->state()); + EXPECT_TRUE(LoadResult()); +} + +TEST_F(SessionDataTypeControllerTest, + StartModelsDelayedByRestoreInProgressThenLocalDevice) { + local_device_->SetInitialized(false); + SetSessionRestoreInProgress(true); + Start(); + EXPECT_FALSE(load_finished_); + EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, + controller_->state()); + + SetSessionRestoreInProgress(false); + EXPECT_FALSE(load_finished_); + EXPECT_EQ(sync_driver::DataTypeController::MODEL_STARTING, + controller_->state()); + + local_device_->SetInitialized(true); + EXPECT_EQ(sync_driver::DataTypeController::MODEL_LOADED, + controller_->state()); + EXPECT_TRUE(LoadResult()); +} + +} // namespace + +} // namespace browser_sync
diff --git a/components/sync_sessions/sessions_sync_manager.cc b/components/sync_sessions/sessions_sync_manager.cc new file mode 100644 index 0000000..5075f584 --- /dev/null +++ b/components/sync_sessions/sessions_sync_manager.cc
@@ -0,0 +1,1059 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/sync_sessions/sessions_sync_manager.h" + +#include <algorithm> + +#include "base/metrics/field_trial.h" +#include "components/sync_driver/glue/synced_window_delegate.h" +#include "components/sync_driver/local_device_info_provider.h" +#include "components/sync_driver/sessions/synced_window_delegates_getter.h" +#include "components/sync_sessions/sync_sessions_client.h" +#include "components/sync_sessions/synced_tab_delegate.h" +#include "components/variations/variations_associated_data.h" +#include "sync/api/sync_error.h" +#include "sync/api/sync_error_factory.h" +#include "sync/api/sync_merge_result.h" +#include "sync/api/time.h" + +using sessions::SerializedNavigationEntry; +using sync_driver::DeviceInfo; +using sync_driver::LocalDeviceInfoProvider; +using syncer::SyncChange; +using syncer::SyncData; + +namespace browser_sync { + +namespace { + +// Maximum number of favicons to sync. +// TODO(zea): pull this from the server. +const int kMaxSyncFavicons = 200; + +// The maximum number of navigations in each direction we care to sync. +const int kMaxSyncNavigationCount = 6; + +// The URL at which the set of synced tabs is displayed. We treat it differently +// from all other URL's as accessing it triggers a sync refresh of Sessions. +const char kNTPOpenTabSyncURL[] = "chrome://newtab/#open_tabs"; + +// Default number of days without activity after which a session is considered +// stale and becomes a candidate for garbage collection. +const size_t kDefaultStaleSessionThresholdDays = 14; // 2 weeks. + +// Comparator function for use with std::sort that will sort tabs by +// descending timestamp (i.e., most recent first). +bool TabsRecencyComparator(const sessions::SessionTab* t1, + const sessions::SessionTab* t2) { + return t1->timestamp > t2->timestamp; +} + +// Comparator function for use with std::sort that will sort sessions by +// descending modified_time (i.e., most recent first). +bool SessionsRecencyComparator(const sync_driver::SyncedSession* s1, + const sync_driver::SyncedSession* s2) { + return s1->modified_time > s2->modified_time; +} + +} // namespace + +// |local_device| is owned by ProfileSyncService, its lifetime exceeds +// lifetime of SessionSyncManager. +SessionsSyncManager::SessionsSyncManager( + sync_sessions::SyncSessionsClient* sessions_client, + sync_driver::SyncPrefs* sync_prefs, + LocalDeviceInfoProvider* local_device, + scoped_ptr<LocalSessionEventRouter> router, + const base::Closure& sessions_updated_callback, + const base::Closure& datatype_refresh_callback) + : sessions_client_(sessions_client), + session_tracker_(sessions_client), + favicon_cache_(sessions_client->GetFaviconService(), + sessions_client->GetHistoryService(), + kMaxSyncFavicons), + local_tab_pool_out_of_sync_(true), + sync_prefs_(sync_prefs), + local_device_(local_device), + local_session_header_node_id_(TabNodePool::kInvalidTabNodeID), + stale_session_threshold_days_(kDefaultStaleSessionThresholdDays), + local_event_router_(router.Pass()), + page_revisit_broadcaster_(this, sessions_client), + sessions_updated_callback_(sessions_updated_callback), + datatype_refresh_callback_(datatype_refresh_callback) { + synced_window_getter_ = sessions_client_->GetSyncedWindowDelegatesGetter(); +} + +SessionsSyncManager::~SessionsSyncManager() {} + +// Returns the GUID-based string that should be used for +// |SessionsSyncManager::current_machine_tag_|. +static std::string BuildMachineTag(const std::string& cache_guid) { + std::string machine_tag = "session_sync"; + machine_tag.append(cache_guid); + return machine_tag; +} + +syncer::SyncMergeResult SessionsSyncManager::MergeDataAndStartSyncing( + syncer::ModelType type, + const syncer::SyncDataList& initial_sync_data, + scoped_ptr<syncer::SyncChangeProcessor> sync_processor, + scoped_ptr<syncer::SyncErrorFactory> error_handler) { + syncer::SyncMergeResult merge_result(type); + DCHECK(session_tracker_.Empty()); + DCHECK_EQ(0U, local_tab_pool_.Capacity()); + + error_handler_ = error_handler.Pass(); + sync_processor_ = sync_processor.Pass(); + + local_session_header_node_id_ = TabNodePool::kInvalidTabNodeID; + + // Make sure we have a machine tag. We do this now (versus earlier) as it's + // a conveniently safe time to assert sync is ready and the cache_guid is + // initialized. + if (current_machine_tag_.empty()) { + InitializeCurrentMachineTag(); + } + + // SessionDataTypeController ensures that the local device info + // is available before activating this datatype. + DCHECK(local_device_); + const DeviceInfo* local_device_info = local_device_->GetLocalDeviceInfo(); + if (local_device_info) { + current_session_name_ = local_device_info->client_name(); + } else { + merge_result.set_error(error_handler_->CreateAndUploadError( + FROM_HERE, "Failed to get local device info.")); + return merge_result; + } + + session_tracker_.SetLocalSessionTag(current_machine_tag_); + + syncer::SyncChangeList new_changes; + + // First, we iterate over sync data to update our session_tracker_. + syncer::SyncDataList restored_tabs; + if (!InitFromSyncModel(initial_sync_data, &restored_tabs, &new_changes)) { + // The sync db didn't have a header node for us. Create one. + sync_pb::EntitySpecifics specifics; + sync_pb::SessionSpecifics* base_specifics = specifics.mutable_session(); + base_specifics->set_session_tag(current_machine_tag()); + sync_pb::SessionHeader* header_s = base_specifics->mutable_header(); + header_s->set_client_name(current_session_name_); + header_s->set_device_type(local_device_info->device_type()); + syncer::SyncData data = syncer::SyncData::CreateLocalData( + current_machine_tag(), current_session_name_, specifics); + new_changes.push_back( + syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD, data)); + } + +#if defined(OS_ANDROID) + std::string sync_machine_tag( + BuildMachineTag(local_device_->GetLocalSyncCacheGUID())); + if (current_machine_tag_.compare(sync_machine_tag) != 0) + DeleteForeignSessionInternal(sync_machine_tag, &new_changes); +#endif + + // Check if anything has changed on the local client side. + AssociateWindows(RELOAD_TABS, restored_tabs, &new_changes); + local_tab_pool_out_of_sync_ = false; + + merge_result.set_error( + sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes)); + + local_event_router_->StartRoutingTo(this); + return merge_result; +} + +void SessionsSyncManager::AssociateWindows( + ReloadTabsOption option, + const syncer::SyncDataList& restored_tabs, + syncer::SyncChangeList* change_output) { + const std::string local_tag = current_machine_tag(); + sync_pb::SessionSpecifics specifics; + specifics.set_session_tag(local_tag); + sync_pb::SessionHeader* header_s = specifics.mutable_header(); + sync_driver::SyncedSession* current_session = + session_tracker_.GetSession(local_tag); + current_session->modified_time = base::Time::Now(); + header_s->set_client_name(current_session_name_); + // SessionDataTypeController ensures that the local device info + // is available before activating this datatype. + DCHECK(local_device_); + const DeviceInfo* local_device_info = local_device_->GetLocalDeviceInfo(); + header_s->set_device_type(local_device_info->device_type()); + + session_tracker_.ResetSessionTracking(local_tag); + std::set<const SyncedWindowDelegate*> windows = + GetSyncedWindowDelegatesGetter()->GetSyncedWindowDelegates(); + + for (std::set<const SyncedWindowDelegate*>::const_iterator i = + windows.begin(); + i != windows.end(); ++i) { + // Make sure the window has tabs and a viewable window. The viewable window + // check is necessary because, for example, when a browser is closed the + // destructor is not necessarily run immediately. This means its possible + // for us to get a handle to a browser that is about to be removed. If + // the tab count is 0 or the window is NULL, the browser is about to be + // deleted, so we ignore it. + if ((*i)->ShouldSync() && (*i)->GetTabCount() && (*i)->HasWindow()) { + sync_pb::SessionWindow window_s; + SessionID::id_type window_id = (*i)->GetSessionId(); + DVLOG(1) << "Associating window " << window_id << " with " + << (*i)->GetTabCount() << " tabs."; + window_s.set_window_id(window_id); + // Note: We don't bother to set selected tab index anymore. We still + // consume it when receiving foreign sessions, as reading it is free, but + // it triggers too many sync cycles with too little value to make setting + // it worthwhile. + if ((*i)->IsTypeTabbed()) { + window_s.set_browser_type( + sync_pb::SessionWindow_BrowserType_TYPE_TABBED); + } else { + window_s.set_browser_type( + sync_pb::SessionWindow_BrowserType_TYPE_POPUP); + } + + bool found_tabs = false; + for (int j = 0; j < (*i)->GetTabCount(); ++j) { + SessionID::id_type tab_id = (*i)->GetTabIdAt(j); + SyncedTabDelegate* synced_tab = (*i)->GetTabAt(j); + + // GetTabAt can return a null tab; in that case just skip it. + if (!synced_tab) + continue; + + if (synced_tab->IsPlaceholderTab()) { + // For tabs without WebContents update the |tab_id|, as it could have + // changed after a session restore. + // Note: We cannot check if a tab is valid if it has no WebContents. + // We assume any such tab is valid and leave the contents of + // corresponding sync node unchanged. + if (synced_tab->GetSyncId() > TabNodePool::kInvalidTabNodeID && + tab_id > TabNodePool::kInvalidTabID) { + AssociateRestoredPlaceholderTab(*synced_tab, tab_id, restored_tabs, + change_output); + found_tabs = true; + window_s.add_tab(tab_id); + } + continue; + } + + if (RELOAD_TABS == option) + AssociateTab(synced_tab, change_output); + + // If the tab is valid, it would have been added to the tracker either + // by the above AssociateTab call (at association time), or by the + // change processor calling AssociateTab for all modified tabs. + // Therefore, we can key whether this window has valid tabs based on + // the tab's presence in the tracker. + const sessions::SessionTab* tab = NULL; + if (session_tracker_.LookupSessionTab(local_tag, tab_id, &tab)) { + found_tabs = true; + window_s.add_tab(tab_id); + } + } + if (found_tabs) { + sync_pb::SessionWindow* header_window = header_s->add_window(); + *header_window = window_s; + + // Update this window's representation in the synced session tracker. + session_tracker_.PutWindowInSession(local_tag, window_id); + BuildSyncedSessionFromSpecifics(local_tag, window_s, + current_session->modified_time, + current_session->windows[window_id]); + } + } + } + local_tab_pool_.DeleteUnassociatedTabNodes(change_output); + session_tracker_.CleanupSession(local_tag); + + // Always update the header. Sync takes care of dropping this update + // if the entity specifics are identical (i.e windows, client name did + // not change). + sync_pb::EntitySpecifics entity; + entity.mutable_session()->CopyFrom(specifics); + syncer::SyncData data = syncer::SyncData::CreateLocalData( + current_machine_tag(), current_session_name_, entity); + change_output->push_back( + syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); +} + +void SessionsSyncManager::AssociateTab(SyncedTabDelegate* const tab, + syncer::SyncChangeList* change_output) { + DCHECK(!tab->IsPlaceholderTab()); + SessionID::id_type tab_id = tab->GetSessionId(); + + if (tab->IsBeingDestroyed()) { + // This tab is closing. + TabLinksMap::iterator tab_iter = local_tab_map_.find(tab_id); + if (tab_iter == local_tab_map_.end()) { + // We aren't tracking this tab (for example, sync setting page). + return; + } + local_tab_pool_.FreeTabNode(tab_iter->second->tab_node_id(), change_output); + local_tab_map_.erase(tab_iter); + return; + } + + if (!tab->ShouldSync(sessions_client_)) + return; + + TabLinksMap::iterator local_tab_map_iter = local_tab_map_.find(tab_id); + TabLink* tab_link = NULL; + + if (local_tab_map_iter == local_tab_map_.end()) { + int tab_node_id = tab->GetSyncId(); + // If there is an old sync node for the tab, reuse it. If this is a new + // tab, get a sync node for it. + if (!local_tab_pool_.IsUnassociatedTabNode(tab_node_id)) { + tab_node_id = local_tab_pool_.GetFreeTabNode(change_output); + tab->SetSyncId(tab_node_id); + } + local_tab_pool_.AssociateTabNode(tab_node_id, tab_id); + tab_link = new TabLink(tab_node_id, tab); + local_tab_map_[tab_id] = make_linked_ptr<TabLink>(tab_link); + } else { + // This tab is already associated with a sync node, reuse it. + // Note: on some platforms the tab object may have changed, so we ensure + // the tab link is up to date. + tab_link = local_tab_map_iter->second.get(); + local_tab_map_iter->second->set_tab(tab); + } + DCHECK(tab_link); + DCHECK_NE(tab_link->tab_node_id(), TabNodePool::kInvalidTabNodeID); + DVLOG(1) << "Reloading tab " << tab_id << " from window " + << tab->GetWindowId(); + + // Write to sync model. + sync_pb::EntitySpecifics specifics; + LocalTabDelegateToSpecifics(*tab, specifics.mutable_session()); + syncer::SyncData data = syncer::SyncData::CreateLocalData( + TabNodePool::TabIdToTag(current_machine_tag_, tab_link->tab_node_id()), + current_session_name_, specifics); + change_output->push_back( + syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); + + int current_index = tab->GetCurrentEntryIndex(); + const GURL new_url = tab->GetVirtualURLAtIndex(current_index); + if (new_url != tab_link->url()) { + tab_link->set_url(new_url); + favicon_cache_.OnFaviconVisited(new_url, + tab->GetFaviconURLAtIndex(current_index)); + page_revisit_broadcaster_.OnPageVisit( + new_url, tab->GetTransitionAtIndex(current_index)); + } + + session_tracker_.GetSession(current_machine_tag())->modified_time = + base::Time::Now(); +} + +void SessionsSyncManager::RebuildAssociations() { + syncer::SyncDataList data(sync_processor_->GetAllSyncData(syncer::SESSIONS)); + scoped_ptr<syncer::SyncErrorFactory> error_handler(error_handler_.Pass()); + scoped_ptr<syncer::SyncChangeProcessor> processor(sync_processor_.Pass()); + + StopSyncing(syncer::SESSIONS); + MergeDataAndStartSyncing(syncer::SESSIONS, data, processor.Pass(), + error_handler.Pass()); +} + +bool SessionsSyncManager::IsValidSessionHeader( + const sync_pb::SessionHeader& header) { + // Verify that tab IDs appear only once within a session. + // Intended to prevent http://crbug.com/360822. + std::set<int> session_tab_ids; + for (int i = 0; i < header.window_size(); ++i) { + const sync_pb::SessionWindow& window = header.window(i); + for (int j = 0; j < window.tab_size(); ++j) { + const int tab_id = window.tab(j); + bool success = session_tab_ids.insert(tab_id).second; + if (!success) + return false; + } + } + + return true; +} + +void SessionsSyncManager::OnLocalTabModified(SyncedTabDelegate* modified_tab) { + GURL virtual_url = + modified_tab->GetVirtualURLAtIndex(modified_tab->GetCurrentEntryIndex()); + if (!modified_tab->IsBeingDestroyed() && virtual_url.is_valid() && + virtual_url.spec() == kNTPOpenTabSyncURL) { + DVLOG(1) << "Triggering sync refresh for sessions datatype."; + if (!datatype_refresh_callback_.is_null()) + datatype_refresh_callback_.Run(); + } + + if (local_tab_pool_out_of_sync_) { + // If our tab pool is corrupt, pay the price of a full re-association to + // fix things up. This takes care of the new tab modification as well. + RebuildAssociations(); + DCHECK(!local_tab_pool_out_of_sync_); + return; + } + + syncer::SyncChangeList changes; + AssociateTab(modified_tab, &changes); + // Note, we always associate windows because it's possible a tab became + // "interesting" by going to a valid URL, in which case it needs to be added + // to the window's tab information. Similarly, if a tab became + // "uninteresting", we remove it from the window's tab information. + AssociateWindows(DONT_RELOAD_TABS, syncer::SyncDataList(), &changes); + sync_processor_->ProcessSyncChanges(FROM_HERE, changes); +} + +void SessionsSyncManager::OnFaviconsChanged(const std::set<GURL>& page_urls, + const GURL& /* icon_url */) { + // TODO(zea): consider a separate container for tabs with outstanding favicon + // loads so we don't have to iterate through all tabs comparing urls. + for (const GURL& page_url : page_urls) { + for (TabLinksMap::iterator tab_iter = local_tab_map_.begin(); + tab_iter != local_tab_map_.end(); ++tab_iter) { + if (tab_iter->second->url() == page_url) + favicon_cache_.OnPageFaviconUpdated(page_url); + } + } +} + +void SessionsSyncManager::StopSyncing(syncer::ModelType type) { + local_event_router_->Stop(); + sync_processor_.reset(NULL); + error_handler_.reset(); + session_tracker_.Clear(); + local_tab_map_.clear(); + local_tab_pool_.Clear(); + current_machine_tag_.clear(); + current_session_name_.clear(); + local_session_header_node_id_ = TabNodePool::kInvalidTabNodeID; +} + +syncer::SyncDataList SessionsSyncManager::GetAllSyncData( + syncer::ModelType type) const { + syncer::SyncDataList list; + const sync_driver::SyncedSession* session = NULL; + if (!session_tracker_.LookupLocalSession(&session)) + return syncer::SyncDataList(); + + // First construct the header node. + sync_pb::EntitySpecifics header_entity; + header_entity.mutable_session()->set_session_tag(current_machine_tag()); + sync_pb::SessionHeader* header_specifics = + header_entity.mutable_session()->mutable_header(); + header_specifics->MergeFrom(session->ToSessionHeader()); + syncer::SyncData data = syncer::SyncData::CreateLocalData( + current_machine_tag(), current_session_name_, header_entity); + list.push_back(data); + + sync_driver::SyncedSession::SyncedWindowMap::const_iterator win_iter; + for (win_iter = session->windows.begin(); win_iter != session->windows.end(); + ++win_iter) { + std::vector<sessions::SessionTab*>::const_iterator tabs_iter; + for (tabs_iter = win_iter->second->tabs.begin(); + tabs_iter != win_iter->second->tabs.end(); ++tabs_iter) { + sync_pb::EntitySpecifics entity; + sync_pb::SessionSpecifics* specifics = entity.mutable_session(); + specifics->mutable_tab()->MergeFrom((*tabs_iter)->ToSyncData()); + specifics->set_session_tag(current_machine_tag_); + + TabLinksMap::const_iterator tab_map_iter = + local_tab_map_.find((*tabs_iter)->tab_id.id()); + DCHECK(tab_map_iter != local_tab_map_.end()); + specifics->set_tab_node_id(tab_map_iter->second->tab_node_id()); + syncer::SyncData data = syncer::SyncData::CreateLocalData( + TabNodePool::TabIdToTag(current_machine_tag_, + specifics->tab_node_id()), + current_session_name_, entity); + list.push_back(data); + } + } + return list; +} + +bool SessionsSyncManager::GetLocalSession( + const sync_driver::SyncedSession** local_session) { + if (current_machine_tag_.empty()) + return false; + *local_session = session_tracker_.GetSession(current_machine_tag()); + return true; +} + +syncer::SyncError SessionsSyncManager::ProcessSyncChanges( + const tracked_objects::Location& from_here, + const syncer::SyncChangeList& change_list) { + if (!sync_processor_.get()) { + syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, + "Models not yet associated.", syncer::SESSIONS); + return error; + } + + for (syncer::SyncChangeList::const_iterator it = change_list.begin(); + it != change_list.end(); ++it) { + DCHECK(it->IsValid()); + DCHECK(it->sync_data().GetSpecifics().has_session()); + const sync_pb::SessionSpecifics& session = + it->sync_data().GetSpecifics().session(); + switch (it->change_type()) { + case syncer::SyncChange::ACTION_DELETE: + // Deletions are all or nothing (since we only ever delete entire + // sessions). Therefore we don't care if it's a tab node or meta node, + // and just ensure we've disassociated. + if (current_machine_tag() == session.session_tag()) { + // Another client has attempted to delete our local data (possibly by + // error or a clock is inaccurate). Just ignore the deletion for now + // to avoid any possible ping-pong delete/reassociate sequence, but + // remember that this happened as our TabNodePool is inconsistent. + local_tab_pool_out_of_sync_ = true; + LOG(WARNING) << "Local session data deleted. Ignoring until next " + << "local navigation event."; + } else if (session.has_header()) { + // Disassociate only when header node is deleted. For tab node + // deletions, the header node will be updated and foreign tab will + // get deleted. + DisassociateForeignSession(session.session_tag()); + } + break; + case syncer::SyncChange::ACTION_ADD: + case syncer::SyncChange::ACTION_UPDATE: + if (current_machine_tag() == session.session_tag()) { + // We should only ever receive a change to our own machine's session + // info if encryption was turned on. In that case, the data is still + // the same, so we can ignore. + // TODO(skym): Is it really safe to return here? Why not continue? + // Couldn't there be multiple SessionSpecifics in the SyncChangeList + // that contain different session tags? + LOG(WARNING) << "Dropping modification to local session."; + return syncer::SyncError(); + } + UpdateTrackerWithForeignSession( + session, syncer::SyncDataRemote(it->sync_data()).GetModifiedTime()); + break; + default: + NOTREACHED() << "Processing sync changes failed, unknown change type."; + } + } + + if (!sessions_updated_callback_.is_null()) + sessions_updated_callback_.Run(); + return syncer::SyncError(); +} + +syncer::SyncChange SessionsSyncManager::TombstoneTab( + const sync_pb::SessionSpecifics& tab) { + if (!tab.has_tab_node_id()) { + LOG(WARNING) << "Old sessions node without tab node id; can't tombstone."; + return syncer::SyncChange(); + } else { + return syncer::SyncChange( + FROM_HERE, SyncChange::ACTION_DELETE, + SyncData::CreateLocalDelete( + TabNodePool::TabIdToTag(current_machine_tag(), tab.tab_node_id()), + syncer::SESSIONS)); + } +} + +bool SessionsSyncManager::GetAllForeignSessions( + std::vector<const sync_driver::SyncedSession*>* sessions) { + if (!session_tracker_.LookupAllForeignSessions(sessions)) + return false; + std::sort(sessions->begin(), sessions->end(), SessionsRecencyComparator); + return true; +} + +bool SessionsSyncManager::InitFromSyncModel( + const syncer::SyncDataList& sync_data, + syncer::SyncDataList* restored_tabs, + syncer::SyncChangeList* new_changes) { + bool found_current_header = false; + for (syncer::SyncDataList::const_iterator it = sync_data.begin(); + it != sync_data.end(); ++it) { + // TODO(skym): Why don't we ever look at data.change_type()? Why is this + // code path so much different from ProcessSyncChanges? + const syncer::SyncData& data = *it; + DCHECK(data.GetSpecifics().has_session()); + const sync_pb::SessionSpecifics& specifics = data.GetSpecifics().session(); + if (specifics.session_tag().empty() || + (specifics.has_tab() && + (!specifics.has_tab_node_id() || !specifics.tab().has_tab_id()))) { + syncer::SyncChange tombstone(TombstoneTab(specifics)); + if (tombstone.IsValid()) + new_changes->push_back(tombstone); + } else if (specifics.session_tag() != current_machine_tag()) { + UpdateTrackerWithForeignSession( + specifics, syncer::SyncDataRemote(data).GetModifiedTime()); + } else { + // This is previously stored local session information. + if (specifics.has_header() && !found_current_header) { + // This is our previous header node, reuse it. + found_current_header = true; + if (specifics.header().has_client_name()) + current_session_name_ = specifics.header().client_name(); + } else { + if (specifics.has_header() || !specifics.has_tab()) { + LOG(WARNING) << "Found more than one session header node with local " + << "tag."; + syncer::SyncChange tombstone(TombstoneTab(specifics)); + if (tombstone.IsValid()) + new_changes->push_back(tombstone); + } else { + // This is a valid old tab node, add it to the pool so it can be + // reused for reassociation. + local_tab_pool_.AddTabNode(specifics.tab_node_id()); + restored_tabs->push_back(*it); + } + } + } + } + return found_current_header; +} + +void SessionsSyncManager::UpdateTrackerWithForeignSession( + const sync_pb::SessionSpecifics& specifics, + const base::Time& modification_time) { + std::string foreign_session_tag = specifics.session_tag(); + DCHECK_NE(foreign_session_tag, current_machine_tag()); + + sync_driver::SyncedSession* foreign_session = + session_tracker_.GetSession(foreign_session_tag); + if (specifics.has_header()) { + // Read in the header data for this foreign session. Header data is + // essentially a collection of windows, each of which has an ordered id list + // for their tabs. + + if (!IsValidSessionHeader(specifics.header())) { + LOG(WARNING) << "Ignoring foreign session node with invalid header " + << "and tag " << foreign_session_tag << "."; + return; + } + + // Load (or create) the SyncedSession object for this client. + const sync_pb::SessionHeader& header = specifics.header(); + PopulateSessionHeaderFromSpecifics(header, modification_time, + foreign_session); + + // Reset the tab/window tracking for this session (must do this before + // we start calling PutWindowInSession and PutTabInWindow so that all + // unused tabs/windows get cleared by the CleanupSession(...) call). + session_tracker_.ResetSessionTracking(foreign_session_tag); + + // Process all the windows and their tab information. + int num_windows = header.window_size(); + DVLOG(1) << "Associating " << foreign_session_tag << " with " << num_windows + << " windows."; + + for (int i = 0; i < num_windows; ++i) { + const sync_pb::SessionWindow& window_s = header.window(i); + SessionID::id_type window_id = window_s.window_id(); + session_tracker_.PutWindowInSession(foreign_session_tag, window_id); + BuildSyncedSessionFromSpecifics(foreign_session_tag, window_s, + modification_time, + foreign_session->windows[window_id]); + } + // Delete any closed windows and unused tabs as necessary. + session_tracker_.CleanupSession(foreign_session_tag); + } else if (specifics.has_tab()) { + const sync_pb::SessionTab& tab_s = specifics.tab(); + SessionID::id_type tab_id = tab_s.tab_id(); + + const sessions::SessionTab* existing_tab; + if (session_tracker_.LookupSessionTab(foreign_session_tag, tab_id, + &existing_tab) && + existing_tab->timestamp > modification_time) { + DVLOG(1) << "Ignoring " << foreign_session_tag << "'s session tab " + << tab_id << " with earlier modification time"; + return; + } + + sessions::SessionTab* tab = session_tracker_.GetTab( + foreign_session_tag, tab_id, specifics.tab_node_id()); + + // Update SessionTab based on protobuf. + tab->SetFromSyncData(tab_s, modification_time); + + // If a favicon or favicon urls are present, load the URLs and visit + // times into the in-memory favicon cache. + RefreshFaviconVisitTimesFromForeignTab(tab_s, modification_time); + + // Update the last modified time. + if (foreign_session->modified_time < modification_time) + foreign_session->modified_time = modification_time; + } else { + LOG(WARNING) << "Ignoring foreign session node with missing header/tab " + << "fields and tag " << foreign_session_tag << "."; + } +} + +void SessionsSyncManager::InitializeCurrentMachineTag() { + DCHECK(current_machine_tag_.empty()); + std::string persisted_guid; + persisted_guid = sync_prefs_->GetSyncSessionsGUID(); + if (!persisted_guid.empty()) { + current_machine_tag_ = persisted_guid; + DVLOG(1) << "Restoring persisted session sync guid: " << persisted_guid; + } else { + DCHECK(local_device_); + std::string cache_guid = local_device_->GetLocalSyncCacheGUID(); + DCHECK(!cache_guid.empty()); + current_machine_tag_ = BuildMachineTag(cache_guid); + DVLOG(1) << "Creating session sync guid: " << current_machine_tag_; + sync_prefs_->SetSyncSessionsGUID(current_machine_tag_); + } + + local_tab_pool_.SetMachineTag(current_machine_tag_); +} + +// static +void SessionsSyncManager::PopulateSessionHeaderFromSpecifics( + const sync_pb::SessionHeader& header_specifics, + base::Time mtime, + sync_driver::SyncedSession* session_header) { + if (header_specifics.has_client_name()) + session_header->session_name = header_specifics.client_name(); + if (header_specifics.has_device_type()) { + switch (header_specifics.device_type()) { + case sync_pb::SyncEnums_DeviceType_TYPE_WIN: + session_header->device_type = sync_driver::SyncedSession::TYPE_WIN; + break; + case sync_pb::SyncEnums_DeviceType_TYPE_MAC: + session_header->device_type = sync_driver::SyncedSession::TYPE_MACOSX; + break; + case sync_pb::SyncEnums_DeviceType_TYPE_LINUX: + session_header->device_type = sync_driver::SyncedSession::TYPE_LINUX; + break; + case sync_pb::SyncEnums_DeviceType_TYPE_CROS: + session_header->device_type = sync_driver::SyncedSession::TYPE_CHROMEOS; + break; + case sync_pb::SyncEnums_DeviceType_TYPE_PHONE: + session_header->device_type = sync_driver::SyncedSession::TYPE_PHONE; + break; + case sync_pb::SyncEnums_DeviceType_TYPE_TABLET: + session_header->device_type = sync_driver::SyncedSession::TYPE_TABLET; + break; + case sync_pb::SyncEnums_DeviceType_TYPE_OTHER: + // Intentionally fall-through + default: + session_header->device_type = sync_driver::SyncedSession::TYPE_OTHER; + break; + } + } + session_header->modified_time = mtime; +} + +// static +void SessionsSyncManager::BuildSyncedSessionFromSpecifics( + const std::string& session_tag, + const sync_pb::SessionWindow& specifics, + base::Time mtime, + sessions::SessionWindow* session_window) { + if (specifics.has_window_id()) + session_window->window_id.set_id(specifics.window_id()); + if (specifics.has_selected_tab_index()) + session_window->selected_tab_index = specifics.selected_tab_index(); + if (specifics.has_browser_type()) { + // TODO(skuhne): Sync data writes |BrowserType| not + // |SessionWindow::WindowType|. This should get changed. + if (specifics.browser_type() == + sync_pb::SessionWindow_BrowserType_TYPE_TABBED) { + session_window->type = sessions::SessionWindow::TYPE_TABBED; + } else { + session_window->type = sessions::SessionWindow::TYPE_POPUP; + } + } + session_window->timestamp = mtime; + session_window->tabs.resize(specifics.tab_size(), NULL); + for (int i = 0; i < specifics.tab_size(); i++) { + SessionID::id_type tab_id = specifics.tab(i); + session_tracker_.PutTabInWindow(session_tag, session_window->window_id.id(), + tab_id, i); + } +} + +void SessionsSyncManager::RefreshFaviconVisitTimesFromForeignTab( + const sync_pb::SessionTab& tab, + const base::Time& modification_time) { + // First go through and iterate over all the navigations, checking if any + // have valid favicon urls. + for (int i = 0; i < tab.navigation_size(); ++i) { + if (!tab.navigation(i).favicon_url().empty()) { + const std::string& page_url = tab.navigation(i).virtual_url(); + const std::string& favicon_url = tab.navigation(i).favicon_url(); + favicon_cache_.OnReceivedSyncFavicon( + GURL(page_url), GURL(favicon_url), std::string(), + syncer::TimeToProtoTime(modification_time)); + } + } +} + +bool SessionsSyncManager::GetSyncedFaviconForPageURL( + const std::string& page_url, + scoped_refptr<base::RefCountedMemory>* favicon_png) const { + return favicon_cache_.GetSyncedFaviconForPageURL(GURL(page_url), favicon_png); +} + +void SessionsSyncManager::DeleteForeignSession(const std::string& tag) { + syncer::SyncChangeList changes; + DeleteForeignSessionInternal(tag, &changes); + sync_processor_->ProcessSyncChanges(FROM_HERE, changes); +} + +void SessionsSyncManager::DeleteForeignSessionInternal( + const std::string& tag, + syncer::SyncChangeList* change_output) { + if (tag == current_machine_tag()) { + LOG(ERROR) << "Attempting to delete local session. This is not currently " + << "supported."; + return; + } + + std::set<int> tab_node_ids_to_delete; + session_tracker_.LookupTabNodeIds(tag, &tab_node_ids_to_delete); + if (!DisassociateForeignSession(tag)) { + // We don't have any data for this session, our work here is done! + return; + } + + // Prepare deletes for the meta-node as well as individual tab nodes. + change_output->push_back( + syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, + SyncData::CreateLocalDelete(tag, syncer::SESSIONS))); + + for (std::set<int>::const_iterator it = tab_node_ids_to_delete.begin(); + it != tab_node_ids_to_delete.end(); ++it) { + change_output->push_back(syncer::SyncChange( + FROM_HERE, SyncChange::ACTION_DELETE, + SyncData::CreateLocalDelete(TabNodePool::TabIdToTag(tag, *it), + syncer::SESSIONS))); + } + if (!sessions_updated_callback_.is_null()) + sessions_updated_callback_.Run(); +} + +bool SessionsSyncManager::DisassociateForeignSession( + const std::string& foreign_session_tag) { + if (foreign_session_tag == current_machine_tag()) { + DVLOG(1) << "Local session deleted! Doing nothing until a navigation is " + << "triggered."; + return false; + } + DVLOG(1) << "Disassociating session " << foreign_session_tag; + return session_tracker_.DeleteSession(foreign_session_tag); +} + +bool SessionsSyncManager::GetForeignSession( + const std::string& tag, + std::vector<const sessions::SessionWindow*>* windows) { + return session_tracker_.LookupSessionWindows(tag, windows); +} + +bool SessionsSyncManager::GetForeignSessionTabs( + const std::string& tag, + std::vector<const sessions::SessionTab*>* tabs) { + std::vector<const sessions::SessionWindow*> windows; + if (!session_tracker_.LookupSessionWindows(tag, &windows)) + return false; + + // Prune those tabs that are not syncable or are NewTabPage, then sort them + // from most recent to least recent, independent of which window the tabs were + // from. + for (size_t j = 0; j < windows.size(); ++j) { + const sessions::SessionWindow* window = windows[j]; + for (size_t t = 0; t < window->tabs.size(); ++t) { + sessions::SessionTab* const tab = window->tabs[t]; + if (tab->navigations.empty()) + continue; + const sessions::SerializedNavigationEntry& current_navigation = + tab->navigations.at(tab->normalized_navigation_index()); + if (!sessions_client_->ShouldSyncURL(current_navigation.virtual_url())) + continue; + tabs->push_back(tab); + } + } + std::sort(tabs->begin(), tabs->end(), TabsRecencyComparator); + return true; +} + +bool SessionsSyncManager::GetForeignTab(const std::string& tag, + const SessionID::id_type tab_id, + const sessions::SessionTab** tab) { + const sessions::SessionTab* synced_tab = NULL; + bool success = session_tracker_.LookupSessionTab(tag, tab_id, &synced_tab); + if (success) + *tab = synced_tab; + return success; +} + +void SessionsSyncManager::LocalTabDelegateToSpecifics( + const SyncedTabDelegate& tab_delegate, + sync_pb::SessionSpecifics* specifics) { + sessions::SessionTab* session_tab = NULL; + session_tab = session_tracker_.GetTab(current_machine_tag(), + tab_delegate.GetSessionId(), + tab_delegate.GetSyncId()); + SetSessionTabFromDelegate(GetSyncedWindowDelegatesGetter(), tab_delegate, + base::Time::Now(), session_tab); + SetVariationIds(session_tab); + sync_pb::SessionTab tab_s = session_tab->ToSyncData(); + specifics->set_session_tag(current_machine_tag_); + specifics->set_tab_node_id(tab_delegate.GetSyncId()); + specifics->mutable_tab()->CopyFrom(tab_s); +} + +void SessionsSyncManager::AssociateRestoredPlaceholderTab( + const SyncedTabDelegate& tab_delegate, + SessionID::id_type new_tab_id, + const syncer::SyncDataList& restored_tabs, + syncer::SyncChangeList* change_output) { + DCHECK_NE(tab_delegate.GetSyncId(), TabNodePool::kInvalidTabNodeID); + // Rewrite the tab using |restored_tabs| to retrieve the specifics. + if (restored_tabs.empty()) { + DLOG(WARNING) << "Can't Update tab ID."; + return; + } + + for (syncer::SyncDataList::const_iterator it = restored_tabs.begin(); + it != restored_tabs.end(); ++it) { + if (it->GetSpecifics().session().tab_node_id() != + tab_delegate.GetSyncId()) { + continue; + } + + sync_pb::EntitySpecifics entity; + sync_pb::SessionSpecifics* specifics = entity.mutable_session(); + specifics->CopyFrom(it->GetSpecifics().session()); + DCHECK(specifics->has_tab()); + + // Update tab node pool with the new association. + local_tab_pool_.ReassociateTabNode(tab_delegate.GetSyncId(), new_tab_id); + TabLink* tab_link = new TabLink(tab_delegate.GetSyncId(), &tab_delegate); + local_tab_map_[new_tab_id] = make_linked_ptr<TabLink>(tab_link); + + if (specifics->tab().tab_id() == new_tab_id) + return; + + // The tab_id changed (e.g due to session restore), so update sync. + specifics->mutable_tab()->set_tab_id(new_tab_id); + syncer::SyncData data = syncer::SyncData::CreateLocalData( + TabNodePool::TabIdToTag(current_machine_tag_, specifics->tab_node_id()), + current_session_name_, entity); + change_output->push_back( + syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); + return; + } +} + +// static +void SessionsSyncManager::SetSessionTabFromDelegate( + SyncedWindowDelegatesGetter* synced_window_getter, + const SyncedTabDelegate& tab_delegate, + base::Time mtime, + sessions::SessionTab* session_tab) { + DCHECK(session_tab); + session_tab->window_id.set_id(tab_delegate.GetWindowId()); + session_tab->tab_id.set_id(tab_delegate.GetSessionId()); + session_tab->tab_visual_index = 0; + // Use -1 to indicate that the index hasn't been set properly yet. + session_tab->current_navigation_index = -1; + const SyncedWindowDelegate* window_delegate = + synced_window_getter->FindById(tab_delegate.GetWindowId()); + session_tab->pinned = + window_delegate ? window_delegate->IsTabPinned(&tab_delegate) : false; + session_tab->extension_app_id = tab_delegate.GetExtensionAppId(); + session_tab->user_agent_override.clear(); + session_tab->timestamp = mtime; + const int current_index = tab_delegate.GetCurrentEntryIndex(); + const int min_index = std::max(0, current_index - kMaxSyncNavigationCount); + const int max_index = std::min(current_index + kMaxSyncNavigationCount, + tab_delegate.GetEntryCount()); + bool is_supervised = tab_delegate.ProfileIsSupervised(); + session_tab->navigations.clear(); + + for (int i = min_index; i < max_index; ++i) { + if (!tab_delegate.GetVirtualURLAtIndex(i).is_valid()) + continue; + sessions::SerializedNavigationEntry serialized_entry; + tab_delegate.GetSerializedNavigationAtIndex(i, &serialized_entry); + + // Set current_navigation_index to the index in navigations. + if (i == current_index) + session_tab->current_navigation_index = session_tab->navigations.size(); + + session_tab->navigations.push_back(serialized_entry); + if (is_supervised) { + session_tab->navigations.back().set_blocked_state( + SerializedNavigationEntry::STATE_ALLOWED); + } + } + + // If the current navigation is invalid, set the index to the end of the + // navigation array. + if (session_tab->current_navigation_index < 0) { + session_tab->current_navigation_index = session_tab->navigations.size() - 1; + } + + if (is_supervised) { + int offset = session_tab->navigations.size(); + const std::vector<const SerializedNavigationEntry*>& blocked_navigations = + *tab_delegate.GetBlockedNavigations(); + for (size_t i = 0; i < blocked_navigations.size(); ++i) { + session_tab->navigations.push_back(*blocked_navigations[i]); + session_tab->navigations.back().set_index(offset + i); + session_tab->navigations.back().set_blocked_state( + SerializedNavigationEntry::STATE_BLOCKED); + // TODO(bauerb): Add categories + } + } + session_tab->session_storage_persistent_id.clear(); +} + +// static +void SessionsSyncManager::SetVariationIds(sessions::SessionTab* session_tab) { + base::FieldTrial::ActiveGroups active_groups; + base::FieldTrialList::GetActiveFieldTrialGroups(&active_groups); + for (const base::FieldTrial::ActiveGroup& group : active_groups) { + const variations::VariationID id = variations::GetGoogleVariationID( + variations::CHROME_SYNC_SERVICE, group.trial_name, group.group_name); + if (id != variations::EMPTY_ID) + session_tab->variation_ids.push_back(id); + } +} + +FaviconCache* SessionsSyncManager::GetFaviconCache() { + return &favicon_cache_; +} + +SyncedWindowDelegatesGetter* +SessionsSyncManager::GetSyncedWindowDelegatesGetter() const { + return synced_window_getter_; +} + +void SessionsSyncManager::DoGarbageCollection() { + std::vector<const sync_driver::SyncedSession*> sessions; + if (!GetAllForeignSessions(&sessions)) + return; // No foreign sessions. + + // Iterate through all the sessions and delete any with age older than + // |stale_session_threshold_days_|. + syncer::SyncChangeList changes; + for (std::vector<const sync_driver::SyncedSession*>::const_iterator iter = + sessions.begin(); + iter != sessions.end(); ++iter) { + const sync_driver::SyncedSession* session = *iter; + int session_age_in_days = + (base::Time::Now() - session->modified_time).InDays(); + std::string session_tag = session->session_tag; + if (session_age_in_days > 0 && // If false, local clock is not trustworty. + static_cast<size_t>(session_age_in_days) > + stale_session_threshold_days_) { + DVLOG(1) << "Found stale session " << session_tag << " with age " + << session_age_in_days << ", deleting."; + DeleteForeignSessionInternal(session_tag, &changes); + } + } + + if (!changes.empty()) + sync_processor_->ProcessSyncChanges(FROM_HERE, changes); +} + +}; // namespace browser_sync
diff --git a/components/sync_sessions/sessions_sync_manager.h b/components/sync_sessions/sessions_sync_manager.h new file mode 100644 index 0000000..e58b545 --- /dev/null +++ b/components/sync_sessions/sessions_sync_manager.h
@@ -0,0 +1,365 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SYNC_SESSIONS_SESSIONS_SYNC_MANAGER_H_ +#define COMPONENTS_SYNC_SESSIONS_SESSIONS_SYNC_MANAGER_H_ + +#include <map> +#include <set> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/callback_forward.h" +#include "base/gtest_prod_util.h" +#include "base/memory/weak_ptr.h" +#include "base/time/time.h" +#include "components/sessions/core/session_id.h" +#include "components/sessions/core/session_types.h" +#include "components/sync_driver/device_info.h" +#include "components/sync_driver/glue/synced_session.h" +#include "components/sync_driver/open_tabs_ui_delegate.h" +#include "components/sync_driver/sync_prefs.h" +#include "components/sync_driver/tab_node_pool.h" +#include "components/sync_sessions/favicon_cache.h" +#include "components/sync_sessions/local_session_event_router.h" +#include "components/sync_sessions/revisit/page_revisit_broadcaster.h" +#include "components/sync_sessions/synced_session_tracker.h" +#include "sync/api/syncable_service.h" + +namespace syncer { +class SyncErrorFactory; +} + +namespace sync_driver { +class LocalDeviceInfoProvider; +class SyncPrefs; +} + +namespace sync_pb { +class SessionHeader; +class SessionSpecifics; +class SessionTab; +class SessionWindow; +class TabNavigation; +} // namespace sync_pb + +namespace browser_sync { + +class DataTypeErrorHandler; +class SyncedTabDelegate; +class SyncedWindowDelegatesGetter; + +// Contains all logic for associating the Chrome sessions model and +// the sync sessions model. +class SessionsSyncManager : public syncer::SyncableService, + public sync_driver::OpenTabsUIDelegate, + public LocalSessionEventHandler { + public: + SessionsSyncManager(sync_sessions::SyncSessionsClient* sessions_client, + sync_driver::SyncPrefs* sync_prefs, + sync_driver::LocalDeviceInfoProvider* local_device, + scoped_ptr<LocalSessionEventRouter> router, + const base::Closure& sessions_updated_callback, + const base::Closure& datatype_refresh_callback); + ~SessionsSyncManager() override; + + // syncer::SyncableService implementation. + syncer::SyncMergeResult MergeDataAndStartSyncing( + syncer::ModelType type, + const syncer::SyncDataList& initial_sync_data, + scoped_ptr<syncer::SyncChangeProcessor> sync_processor, + scoped_ptr<syncer::SyncErrorFactory> error_handler) override; + void StopSyncing(syncer::ModelType type) override; + syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override; + syncer::SyncError ProcessSyncChanges( + const tracked_objects::Location& from_here, + const syncer::SyncChangeList& change_list) override; + + // OpenTabsUIDelegate implementation. + bool GetSyncedFaviconForPageURL( + const std::string& pageurl, + scoped_refptr<base::RefCountedMemory>* favicon_png) const override; + bool GetAllForeignSessions( + std::vector<const sync_driver::SyncedSession*>* sessions) override; + bool GetForeignSession( + const std::string& tag, + std::vector<const sessions::SessionWindow*>* windows) override; + bool GetForeignTab(const std::string& tag, + const SessionID::id_type tab_id, + const sessions::SessionTab** tab) override; + bool GetForeignSessionTabs( + const std::string& tag, + std::vector<const sessions::SessionTab*>* tabs) override; + void DeleteForeignSession(const std::string& tag) override; + bool GetLocalSession( + const sync_driver::SyncedSession** local_session) override; + + // LocalSessionEventHandler implementation. + void OnLocalTabModified(SyncedTabDelegate* modified_tab) override; + void OnFaviconsChanged(const std::set<GURL>& page_urls, + const GURL& icon_url) override; + + // Returns the tag used to uniquely identify this machine's session in the + // sync model. + const std::string& current_machine_tag() const { + DCHECK(!current_machine_tag_.empty()); + return current_machine_tag_; + } + + FaviconCache* GetFaviconCache(); + + SyncedWindowDelegatesGetter* GetSyncedWindowDelegatesGetter() const; + + // Triggers garbage collection of stale sessions (as defined by + // |stale_session_threshold_days_|). This is called automatically every + // time we start up (via AssociateModels) and when new sessions data is + // downloaded (sync cycles complete). + void DoGarbageCollection(); + + private: + // Keep all the links to local tab data in one place. A tab_node_id and tab + // must be passed at creation. The tab_node_id is not mutable, although + // all other fields are. + class TabLink { + public: + TabLink(int tab_node_id, const SyncedTabDelegate* tab) + : tab_node_id_(tab_node_id), tab_(tab) {} + + void set_tab(const SyncedTabDelegate* tab) { tab_ = tab; } + void set_url(const GURL& url) { url_ = url; } + + int tab_node_id() const { return tab_node_id_; } + const SyncedTabDelegate* tab() const { return tab_; } + const GURL& url() const { return url_; } + + private: + // The id for the sync node this tab is stored in. + const int tab_node_id_; + + // The tab object itself. + const SyncedTabDelegate* tab_; + + // The currently visible url of the tab (used for syncing favicons). + GURL url_; + + DISALLOW_COPY_AND_ASSIGN(TabLink); + }; + + // Container for accessing local tab data by tab id. + typedef std::map<SessionID::id_type, linked_ptr<TabLink>> TabLinksMap; + + FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, PopulateSessionHeader); + FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, PopulateSessionWindow); + FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, ValidTabs); + FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, SetSessionTabFromDelegate); + FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, + SetSessionTabFromDelegateNavigationIndex); + FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, + SetSessionTabFromDelegateCurrentInvalid); + FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, BlockedNavigations); + FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, DeleteForeignSession); + FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, + SaveUnassociatedNodesForReassociation); + FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, MergeDeletesCorruptNode); + FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, + MergeLocalSessionExistingTabs); + FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, + CheckPrerenderedWebContentsSwap); + FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, + AssociateWindowsDontReloadTabs); + FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, SwappedOutOnRestore); + FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, + ProcessRemoteDeleteOfLocalSession); + FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, SetVariationIds); + + void InitializeCurrentMachineTag(); + + // Load and add window or tab data for a foreign session to our internal + // tracking. + void UpdateTrackerWithForeignSession( + const sync_pb::SessionSpecifics& specifics, + const base::Time& modification_time); + + // Returns true if |sync_data| contained a header node for the current + // machine, false otherwise. |restored_tabs| is a filtered tab-only + // subset of |sync_data| returned by this function for convenience. + // |new_changes| is a link to the SyncChange pipeline that exists in the + // caller's context. This function will append necessary changes for + // processing later. + bool InitFromSyncModel(const syncer::SyncDataList& sync_data, + syncer::SyncDataList* restored_tabs, + syncer::SyncChangeList* new_changes); + + // Helper to construct a deletion SyncChange for a *tab node*. + // Caller should check IsValid() on the returned change, as it's possible + // this node could not be deleted. + syncer::SyncChange TombstoneTab(const sync_pb::SessionSpecifics& tab); + + // Helper method to load the favicon data from the tab specifics. If the + // favicon is valid, stores the favicon data into the favicon cache. + void RefreshFaviconVisitTimesFromForeignTab( + const sync_pb::SessionTab& tab, + const base::Time& modification_time); + + // Removes a foreign session from our internal bookkeeping. + // Returns true if the session was found and deleted, false if no data was + // found for that session. This will *NOT* trigger sync deletions. See + // DeleteForeignSession below. + bool DisassociateForeignSession(const std::string& foreign_session_tag); + + // Delete a foreign session and all its sync data. + // |change_output| *must* be provided as a link to the SyncChange pipeline + // that exists in the caller's context. This function will append necessary + // changes for processing later. + void DeleteForeignSessionInternal(const std::string& tag, + syncer::SyncChangeList* change_output); + + // Used to populate a session header from the session specifics header + // provided. + static void PopulateSessionHeaderFromSpecifics( + const sync_pb::SessionHeader& header_specifics, + base::Time mtime, + sync_driver::SyncedSession* session_header); + + // Builds |session_window| from the session specifics window + // provided and updates the SessionTracker with foreign session data created. + void BuildSyncedSessionFromSpecifics(const std::string& session_tag, + const sync_pb::SessionWindow& specifics, + base::Time mtime, + sessions::SessionWindow* session_window); + + // Resync local window information. Updates the local sessions header node + // with the status of open windows and the order of tabs they contain. Should + // only be called for changes that affect a window, not a change within a + // single tab. + // + // RELOAD_TABS will additionally cause a resync of all tabs (same as calling + // AssociateTabs with a vector of all tabs). + // + // |restored_tabs| is a filtered tab-only subset of initial sync data, if + // available (during MergeDataAndStartSyncing). It can be used to obtain + // baseline SessionSpecifics for tabs we can't fully associate any other + // way because they don't yet have a WebContents. + // + // Returns: false if the local session's sync nodes were deleted and + // reassociation is necessary, true otherwise. + // + // |change_output| *must* be provided as a link to the SyncChange pipeline + // that exists in the caller's context. This function will append necessary + // changes for processing later. + enum ReloadTabsOption { RELOAD_TABS, DONT_RELOAD_TABS }; + void AssociateWindows(ReloadTabsOption option, + const syncer::SyncDataList& restored_tabs, + syncer::SyncChangeList* change_output); + + // Loads and reassociates the local tabs referenced in |tabs|. + // |change_output| *must* be provided as a link to the SyncChange pipeline + // that exists in the caller's context. This function will append necessary + // changes for processing later. + void AssociateTab(SyncedTabDelegate* const tab, + syncer::SyncChangeList* change_output); + + // Set |session_tab| from |tab_delegate| and |mtime|. + static void SetSessionTabFromDelegate( + SyncedWindowDelegatesGetter* synced_window_getter, + const SyncedTabDelegate& tab_delegate, + base::Time mtime, + sessions::SessionTab* session_tab); + + // Sets |variation_ids| field of |session_tab| with the ids of the currently + // assigned variations which should be sent to sync. + static void SetVariationIds(sessions::SessionTab* session_tab); + + // Populates |specifics| based on the data in |tab_delegate|. + void LocalTabDelegateToSpecifics(const SyncedTabDelegate& tab_delegate, + sync_pb::SessionSpecifics* specifics); + + // It's possible that when we associate windows, tabs aren't all loaded + // into memory yet (e.g on android) and we don't have a WebContents. In this + // case we can't do a full association, but we still want to update tab IDs + // as they may have changed after a session was restored. This method + // compares new_tab_id against the previously persisted tab ID (from + // our TabNodePool) and updates it if it differs. + // |restored_tabs| is a filtered tab-only subset of initial sync data, if + // available (during MergeDataAndStartSyncing). It can be used to obtain + // baseline SessionSpecifics for tabs we can't fully associate any other + // way because they don't yet have a WebContents. + // TODO(tim): Bug 98892. We should be able to test this for this on android + // even though we didn't have tests for old API-based sessions sync. + void AssociateRestoredPlaceholderTab( + const SyncedTabDelegate& tab_delegate, + SessionID::id_type new_tab_id, + const syncer::SyncDataList& restored_tabs, + syncer::SyncChangeList* change_output); + + // Stops and re-starts syncing to rebuild association mappings. + // See |local_tab_pool_out_of_sync_|. + void RebuildAssociations(); + + // Validates the content of a SessionHeader protobuf. + // Returns false if validation fails. + static bool IsValidSessionHeader(const sync_pb::SessionHeader& header); + + // The client of this sync sessions datatype. + sync_sessions::SyncSessionsClient* const sessions_client_; + + // Mapping of current open (local) tabs to their sync identifiers. + TabLinksMap local_tab_map_; + + SyncedSessionTracker session_tracker_; + FaviconCache favicon_cache_; + + // Pool of used/available sync nodes associated with local tabs. + TabNodePool local_tab_pool_; + + // Tracks whether our local representation of which sync nodes map to what + // tabs (belonging to the current local session) is inconsistent. This can + // happen if a foreign client deems our session as "stale" and decides to + // delete it. Rather than respond by bullishly re-creating our nodes + // immediately, which could lead to ping-pong sequences, we give the benefit + // of the doubt and hold off until another local navigation occurs, which + // proves that we are still relevant. + bool local_tab_pool_out_of_sync_; + + sync_driver::SyncPrefs* sync_prefs_; + + scoped_ptr<syncer::SyncErrorFactory> error_handler_; + scoped_ptr<syncer::SyncChangeProcessor> sync_processor_; + + // Local device info provider, owned by ProfileSyncService. + const sync_driver::LocalDeviceInfoProvider* const local_device_; + + // Unique client tag. + std::string current_machine_tag_; + + // User-visible machine name. + std::string current_session_name_; + + // SyncID for the sync node containing all the window information for this + // client. + int local_session_header_node_id_; + + // Number of days without activity after which we consider a session to be + // stale and a candidate for garbage collection. + size_t stale_session_threshold_days_; + + scoped_ptr<LocalSessionEventRouter> local_event_router_; + SyncedWindowDelegatesGetter* synced_window_getter_; + + // Owns revisiting instrumentation logic for page visit events. + PageRevisitBroadcaster page_revisit_broadcaster_; + + // Callback to inform interested observer that new sessions data has arrived. + base::Closure sessions_updated_callback_; + + // Callback to inform sync that a sync data refresh is requested. + base::Closure datatype_refresh_callback_; + + DISALLOW_COPY_AND_ASSIGN(SessionsSyncManager); +}; + +} // namespace browser_sync + +#endif // COMPONENTS_SYNC_SESSIONS_SESSIONS_SYNC_MANAGER_H_
diff --git a/components/sync_sessions/sync_sessions_client.h b/components/sync_sessions/sync_sessions_client.h index 2defc985..94cfebd9 100644 --- a/components/sync_sessions/sync_sessions_client.h +++ b/components/sync_sessions/sync_sessions_client.h
@@ -10,11 +10,23 @@ class GURL; +namespace bookmarks { +class BookmarkModel; +} + namespace browser_sync { class LocalSessionEventRouter; class SyncedWindowDelegatesGetter; } +namespace favicon { +class FaviconService; +} + +namespace history { +class HistoryService; +} + namespace sync_sessions { // Interface for clients of a sync sessions datatype. Should be used as a getter @@ -24,6 +36,11 @@ SyncSessionsClient(); virtual ~SyncSessionsClient(); + // Getters for services that sessions depends on. + virtual bookmarks::BookmarkModel* GetBookmarkModel() = 0; + virtual favicon::FaviconService* GetFaviconService() = 0; + virtual history::HistoryService* GetHistoryService() = 0; + // Checks if the given url is considered interesting enough to sync. Most urls // are considered interesting. Examples of ones that are not are invalid urls, // files, and chrome internal pages.
diff --git a/components/test_runner/test_plugin.cc b/components/test_runner/test_plugin.cc index 5e2791df..76f608c 100644 --- a/components/test_runner/test_plugin.cc +++ b/components/test_runner/test_plugin.cc
@@ -313,8 +313,9 @@ context_->genMailboxCHROMIUM(mailbox.name); context_->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); context_->flush(); - uint32 sync_point = context_->insertSyncPoint(); - texture_mailbox_ = cc::TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point); + gpu::SyncToken sync_token; + context_->insertSyncPoint(sync_token.GetData()); + texture_mailbox_ = cc::TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D); } else { scoped_ptr<cc::SharedBitmap> bitmap = delegate_->GetSharedBitmapManager()->AllocateSharedBitmap( @@ -341,13 +342,12 @@ return false; } -static void IgnoreReleaseCallback(uint32 sync_point, bool lost) { +static void IgnoreReleaseCallback(const gpu::SyncToken& sync_token, bool lost) { } static void ReleaseSharedMemory(scoped_ptr<cc::SharedBitmap> bitmap, - uint32 sync_point, - bool lost) { -} + const gpu::SyncToken& sync_token, + bool lost) {} bool TestPlugin::PrepareTextureMailbox( cc::TextureMailbox* mailbox,
diff --git a/components/web_modal/BUILD.gn b/components/web_modal/BUILD.gn index 77083a71..839715e 100644 --- a/components/web_modal/BUILD.gn +++ b/components/web_modal/BUILD.gn
@@ -43,3 +43,21 @@ "//ui/gfx/geometry", ] } + +if (!is_android && !is_ios) { + source_set("unit_tests") { + testonly = true + + sources = [ + "web_contents_modal_dialog_manager_unittest.cc", + ] + + deps = [ + ":test_support", + ":web_modal", + "//base", + "//content/test:test_support", + "//testing/gtest", + ] + } +}
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index a334f00..909f664 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -109,6 +109,7 @@ deps += [ "//cc", "//cc/surfaces", + "//components/scheduler:common", "//content/app/resources", "//content/app/strings", "//content/browser/devtools:gen_devtools_protocol_handler",
diff --git a/content/browser/accessibility/site_per_process_accessibility_browsertest.cc b/content/browser/accessibility/site_per_process_accessibility_browsertest.cc index 647985c..2a8f72c6 100644 --- a/content/browser/accessibility/site_per_process_accessibility_browsertest.cc +++ b/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
@@ -27,6 +27,7 @@ #include "content/test/accessibility_browser_test_utils.h" #include "content/test/content_browser_test_utils_internal.h" #include "net/dns/mock_host_resolver.h" +#include "net/test/embedded_test_server/embedded_test_server.h" #include "url/gurl.h" #include "url/url_constants.h" @@ -69,8 +70,7 @@ BrowserAccessibilityState::GetInstance()->EnableAccessibility(); host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(test_server()->Start()); - GURL main_url(test_server()->GetURL("files/site_per_process_main.html")); + GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); NavigateToURL(shell(), main_url); // It is safe to obtain the root frame tree node here, as it doesn't change. @@ -80,7 +80,7 @@ // Load same-site page into iframe. FrameTreeNode* child = root->child_at(0); - GURL http_url(test_server()->GetURL("files/title1.html")); + GURL http_url(embedded_test_server()->GetURL("/title1.html")); NavigateFrameToURL(child, http_url); // Load cross-site page into iframe. @@ -88,7 +88,7 @@ child->render_manager()->current_frame_host(); RenderFrameDeletedObserver deleted_observer(child_rfh); GURL::Replacements replace_host; - GURL cross_site_url(test_server()->GetURL("files/title2.html")); + GURL cross_site_url(embedded_test_server()->GetURL("/title2.html")); replace_host.SetHostStr("foo.com"); cross_site_url = cross_site_url.ReplaceComponents(replace_host); NavigateFrameToURL(root->child_at(0), cross_site_url);
diff --git a/content/browser/android/content_readback_handler.cc b/content/browser/android/content_readback_handler.cc index a7c9b67..d1db971 100644 --- a/content/browser/android/content_readback_handler.cc +++ b/content/browser/android/content_readback_handler.cc
@@ -18,22 +18,6 @@ namespace content { -namespace { - -void OnFinishCopyOutputRequest( - const ReadbackRequestCallback& result_callback, - scoped_ptr<cc::CopyOutputResult> copy_output_result) { - if (!copy_output_result->HasBitmap()) { - result_callback.Run(SkBitmap(), READBACK_FAILED); - return; - } - - scoped_ptr<SkBitmap> bitmap = copy_output_result->TakeBitmap(); - result_callback.Run(*bitmap, READBACK_SUCCESS); -} - -} // anonymous namespace - // static bool ContentReadbackHandler::RegisterContentReadbackHandler(JNIEnv* env) { return RegisterNativesImpl(env); @@ -72,34 +56,6 @@ scale, sk_color_type, gfx::Rect(x, y, width, height), result_callback); } -void ContentReadbackHandler::GetCompositorBitmap(JNIEnv* env, - jobject obj, - jint readback_id, - jlong native_window_android) { - ui::WindowAndroid* window_android = - reinterpret_cast<ui::WindowAndroid*>(native_window_android); - DCHECK(window_android); - - const ReadbackRequestCallback result_callback = - base::Bind(&ContentReadbackHandler::OnFinishReadback, - weak_factory_.GetWeakPtr(), - readback_id); - - base::Callback<void(scoped_ptr<cc::CopyOutputResult>)> copy_output_callback = - base::Bind(&OnFinishCopyOutputRequest, - result_callback); - - ui::WindowAndroidCompositor* compositor = window_android->GetCompositor(); - - if (!compositor) { - copy_output_callback.Run(cc::CopyOutputResult::CreateEmptyResult()); - return; - } - - compositor->RequestCopyOfOutputOnRootLayer( - cc::CopyOutputRequest::CreateBitmapRequest(copy_output_callback)); -} - ContentReadbackHandler::~ContentReadbackHandler() {} void ContentReadbackHandler::OnFinishReadback(int readback_id,
diff --git a/content/browser/android/content_readback_handler.h b/content/browser/android/content_readback_handler.h index 66b2c85..44d2a3d 100644 --- a/content/browser/android/content_readback_handler.h +++ b/content/browser/android/content_readback_handler.h
@@ -40,10 +40,6 @@ jfloat width, jfloat height, jobject content_view_core); - void GetCompositorBitmap(JNIEnv* env, - jobject obj, - jint readback_id, - jlong native_window_android); private: virtual ~ContentReadbackHandler();
diff --git a/content/browser/background_sync/background_sync_browsertest.cc b/content/browser/background_sync/background_sync_browsertest.cc index 3026345..4305c55 100644 --- a/content/browser/background_sync/background_sync_browsertest.cc +++ b/content/browser/background_sync/background_sync_browsertest.cc
@@ -27,6 +27,7 @@ #include "content/public/test/test_utils.h" #include "content/shell/browser/shell.h" #include "net/base/network_change_notifier.h" +#include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gtest/include/gtest/gtest.h" using net::NetworkChangeNotifier; @@ -35,7 +36,7 @@ namespace { -const char kDefaultTestURL[] = "files/background_sync/test.html"; +const char kDefaultTestURL[] = "/background_sync/test.html"; const char kSuccessfulOperationPrefix[] = "ok - "; @@ -127,11 +128,9 @@ } void SetUpOnMainThread() override { - https_server_.reset(new net::SpawnedTestServer( - net::SpawnedTestServer::TYPE_HTTPS, - net::BaseTestServer::SSLOptions( - net::BaseTestServer::SSLOptions::CERT_OK), - base::FilePath(FILE_PATH_LITERAL("content/test/data/")))); + https_server_.reset( + new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS)); + https_server_->ServeFilesFromSourceDirectory("content/test/data"); ASSERT_TRUE(https_server_->Start()); SetIncognitoMode(false); @@ -189,7 +188,7 @@ bool StoreRegistrationOneShot(const std::string& tag); private: - scoped_ptr<net::SpawnedTestServer> https_server_; + scoped_ptr<net::EmbeddedTestServer> https_server_; Shell* shell_ = nullptr; DISALLOW_COPY_AND_ASSIGN(BackgroundSyncBrowserTest);
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index af8dfa7..9d49564 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -502,13 +502,6 @@ } #endif // !defined(OS_IOS) - // TODO(boliu): kSingleProcess check is a temporary workaround for - // in-process Android WebView. crbug.com/503724 tracks proper fix. - if (!parsed_command_line_.HasSwitch(switches::kSingleProcess)) { - base::DiscardableMemoryAllocator::SetInstance( - HostDiscardableSharedMemoryManager::current()); - } - if (parts_) parts_->PostEarlyInitialization(); } @@ -592,6 +585,13 @@ system_message_window_.reset(new SystemMessageWindowWin); #endif + // TODO(boliu): kSingleProcess check is a temporary workaround for + // in-process Android WebView. crbug.com/503724 tracks proper fix. + if (!parsed_command_line_.HasSwitch(switches::kSingleProcess)) { + base::DiscardableMemoryAllocator::SetInstance( + HostDiscardableSharedMemoryManager::current()); + } + if (parts_) parts_->PostMainMessageLoopStart();
diff --git a/content/browser/browser_side_navigation_browsertest.cc b/content/browser/browser_side_navigation_browsertest.cc index 98a265e8..cf081e7 100644 --- a/content/browser/browser_side_navigation_browsertest.cc +++ b/content/browser/browser_side_navigation_browsertest.cc
@@ -31,7 +31,7 @@ void SetUpOnMainThread() override { host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); } };
diff --git a/content/browser/compositor/delegated_frame_host.cc b/content/browser/compositor/delegated_frame_host.cc index 0fb6657..293f96f9 100644 --- a/content/browser/compositor/delegated_frame_host.cc +++ b/content/browser/compositor/delegated_frame_host.cc
@@ -300,10 +300,9 @@ request->set_source(frame_subscriber()); request->set_area(gfx::Rect(current_frame_size_in_dip_)); if (subscriber_texture.get()) { - request->SetTextureMailbox( - cc::TextureMailbox(subscriber_texture->mailbox(), - subscriber_texture->target(), - subscriber_texture->sync_point())); + request->SetTextureMailbox(cc::TextureMailbox( + subscriber_texture->mailbox(), subscriber_texture->sync_token(), + subscriber_texture->target())); } RequestCopyOfOutput(request.Pass()); } @@ -591,14 +590,14 @@ bool result) { bitmap_pixels_lock.reset(); - uint32 sync_point = 0; + gpu::SyncToken sync_token; if (result) { GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper(); if (gl_helper) - sync_point = gl_helper->InsertSyncPoint(); + sync_token = gpu::SyncToken(gl_helper->InsertSyncPoint()); } - bool lost_resource = sync_point == 0; - release_callback->Run(sync_point, lost_resource); + const bool lost_resource = !sync_token.HasData(); + release_callback->Run(sync_token, lost_resource); callback.Run(*bitmap, result ? content::READBACK_SUCCESS : content::READBACK_FAILED); @@ -643,17 +642,10 @@ ignore_result(scoped_callback_runner.Release()); gl_helper->CropScaleReadbackAndCleanMailbox( - texture_mailbox.mailbox(), - texture_mailbox.sync_point(), - result->size(), - gfx::Rect(result->size()), - dst_size_in_pixel, - pixels, - color_type, - base::Bind(&CopyFromCompositingSurfaceFinished, - callback, - base::Passed(&release_callback), - base::Passed(&bitmap), + texture_mailbox.mailbox(), texture_mailbox.sync_token(), result->size(), + gfx::Rect(result->size()), dst_size_in_pixel, pixels, color_type, + base::Bind(&CopyFromCompositingSurfaceFinished, callback, + base::Passed(&release_callback), base::Passed(&bitmap), base::Passed(&bitmap_pixels_lock)), GLHelper::SCALER_QUALITY_GOOD); } @@ -713,13 +705,13 @@ void DelegatedFrameHost::ReturnSubscriberTexture( base::WeakPtr<DelegatedFrameHost> dfh, scoped_refptr<OwnedMailbox> subscriber_texture, - uint32 sync_point) { + const gpu::SyncToken& sync_token) { if (!subscriber_texture.get()) return; if (!dfh) return; - subscriber_texture->UpdateSyncPoint(sync_point); + subscriber_texture->UpdateSyncToken(sync_token); if (dfh->frame_subscriber_ && subscriber_texture->texture_id()) dfh->idle_frame_subscriber_textures_.push_back(subscriber_texture); @@ -734,19 +726,19 @@ bool result) { callback.Run(result); - uint32 sync_point = 0; + gpu::SyncToken sync_token; if (result) { GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper(); - sync_point = gl_helper->InsertSyncPoint(); + sync_token = gpu::SyncToken(gl_helper->InsertSyncPoint()); } if (release_callback) { // A release callback means the texture came from the compositor, so there // should be no |subscriber_texture|. DCHECK(!subscriber_texture.get()); - bool lost_resource = sync_point == 0; - release_callback->Run(sync_point, lost_resource); + const bool lost_resource = !sync_token.HasData(); + release_callback->Run(sync_token, lost_resource); } - ReturnSubscriberTexture(dfh, subscriber_texture, sync_point); + ReturnSubscriberTexture(dfh, subscriber_texture, sync_token); } // static @@ -757,8 +749,8 @@ const base::Callback<void(bool)>& callback, scoped_ptr<cc::CopyOutputResult> result) { base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false)); - base::ScopedClosureRunner scoped_return_subscriber_texture( - base::Bind(&ReturnSubscriberTexture, dfh, subscriber_texture, 0)); + base::ScopedClosureRunner scoped_return_subscriber_texture(base::Bind( + &ReturnSubscriberTexture, dfh, subscriber_texture, gpu::SyncToken())); if (!dfh) return; @@ -866,11 +858,9 @@ callback, subscriber_texture, base::Passed(&release_callback)); - yuv_readback_pipeline->ReadbackYUV(texture_mailbox.mailbox(), - texture_mailbox.sync_point(), - video_frame.get(), - region_in_frame.origin(), - finished_callback); + yuv_readback_pipeline->ReadbackYUV( + texture_mailbox.mailbox(), texture_mailbox.sync_token(), + video_frame.get(), region_in_frame.origin(), finished_callback); } ////////////////////////////////////////////////////////////////////////////////
diff --git a/content/browser/compositor/delegated_frame_host.h b/content/browser/compositor/delegated_frame_host.h index 6482bb5..0f2b28c 100644 --- a/content/browser/compositor/delegated_frame_host.h +++ b/content/browser/compositor/delegated_frame_host.h
@@ -240,7 +240,7 @@ static void ReturnSubscriberTexture( base::WeakPtr<DelegatedFrameHost> rwhva, scoped_refptr<OwnedMailbox> subscriber_texture, - uint32 sync_point); + const gpu::SyncToken& sync_token); void SendDelegatedFrameAck(uint32 output_surface_id); void SurfaceDrawn(uint32 output_surface_id, cc::SurfaceDrawStatus drawn);
diff --git a/content/browser/compositor/owned_mailbox.cc b/content/browser/compositor/owned_mailbox.cc index 9c7b3786..912d4d56 100644 --- a/content/browser/compositor/owned_mailbox.cc +++ b/content/browser/compositor/owned_mailbox.cc
@@ -22,14 +22,14 @@ Destroy(); } -void OwnedMailbox::UpdateSyncPoint(uint32 sync_point) { - if (sync_point) - mailbox_holder_.sync_point = sync_point; +void OwnedMailbox::UpdateSyncToken(const gpu::SyncToken& sync_token) { + if (sync_token.HasData()) + mailbox_holder_.sync_token = sync_token; } void OwnedMailbox::Destroy() { ImageTransportFactory::GetInstance()->RemoveObserver(this); - gl_helper_->WaitSyncPoint(mailbox_holder_.sync_point); + gl_helper_->WaitSyncToken(mailbox_holder_.sync_token); gl_helper_->DeleteTexture(texture_id_); texture_id_ = 0; mailbox_holder_ = gpu::MailboxHolder();
diff --git a/content/browser/compositor/owned_mailbox.h b/content/browser/compositor/owned_mailbox.h index c886814..07aac97 100644 --- a/content/browser/compositor/owned_mailbox.h +++ b/content/browser/compositor/owned_mailbox.h
@@ -24,10 +24,12 @@ const gpu::MailboxHolder& holder() const { return mailbox_holder_; } const gpu::Mailbox& mailbox() const { return mailbox_holder_.mailbox; } + const gpu::SyncToken& sync_token() const { + return mailbox_holder_.sync_token; + } uint32 texture_id() const { return texture_id_; } uint32 target() const { return mailbox_holder_.texture_target; } - uint32 sync_point() const { return mailbox_holder_.sync_point; } - void UpdateSyncPoint(uint32 sync_point); + void UpdateSyncToken(const gpu::SyncToken& sync_token); void Destroy(); protected:
diff --git a/content/browser/compositor/reflector_impl.cc b/content/browser/compositor/reflector_impl.cc index 19945ae..c7259dc0 100644 --- a/content/browser/compositor/reflector_impl.cc +++ b/content/browser/compositor/reflector_impl.cc
@@ -169,9 +169,9 @@ } static void ReleaseMailbox(scoped_refptr<OwnedMailbox> mailbox, - unsigned int sync_point, + const gpu::SyncToken& sync_token, bool is_lost) { - mailbox->UpdateSyncPoint(sync_point); + mailbox->UpdateSyncToken(sync_token); } ScopedVector<ReflectorImpl::LayerData>::iterator ReflectorImpl::FindLayerData(
diff --git a/content/browser/compositor/reflector_impl_unittest.cc b/content/browser/compositor/reflector_impl_unittest.cc index 88c82c3..77c48e8c 100644 --- a/content/browser/compositor/reflector_impl_unittest.cc +++ b/content/browser/compositor/reflector_impl_unittest.cc
@@ -158,7 +158,7 @@ cc::TextureMailbox mailbox; scoped_ptr<cc::SingleReleaseCallback> release; if (mirroring_layer_->PrepareTextureMailbox(&mailbox, &release, false)) { - release->Run(0, false); + release->Run(gpu::SyncToken(), false); } compositor_.reset(); ui::TerminateContextFactoryForTests();
diff --git a/content/browser/compositor/reflector_texture.cc b/content/browser/compositor/reflector_texture.cc index ed6a3bd..2310662 100644 --- a/content/browser/compositor/reflector_texture.cc +++ b/content/browser/compositor/reflector_texture.cc
@@ -21,8 +21,8 @@ gl_helper_.reset(new GLHelper(gl, context_provider->ContextSupport())); - texture_id_ = gl_helper_->ConsumeMailboxToTexture( - mailbox_->mailbox(), mailbox_->sync_point()); + texture_id_ = gl_helper_->ConsumeMailboxToTexture(mailbox_->mailbox(), + mailbox_->sync_token()); } ReflectorTexture::~ReflectorTexture() {
diff --git a/content/browser/cross_site_transfer_browsertest.cc b/content/browser/cross_site_transfer_browsertest.cc index c9d58161..ce57011 100644 --- a/content/browser/cross_site_transfer_browsertest.cc +++ b/content/browser/cross_site_transfer_browsertest.cc
@@ -177,7 +177,7 @@ base::Bind(&CrossSiteTransferTest::InjectResourceDispatcherHostDelegate, base::Unretained(this))); host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); content::SetupCrossSiteRedirector(embedded_test_server()); }
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc index c2fc38f..2a7bf35 100644 --- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc +++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -331,8 +331,8 @@ #endif // defined(OS_ANDROID) IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, NavigationPreservesMessages) { - ASSERT_TRUE(test_server()->Start()); - GURL test_url = test_server()->GetURL("files/devtools/navigation.html"); + ASSERT_TRUE(embedded_test_server()->Start()); + GURL test_url = embedded_test_server()->GetURL("/devtools/navigation.html"); NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1); Attach(); SendCommand("Page.enable", nullptr, false); @@ -361,7 +361,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CrossSiteNoDetach) { host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); content::SetupCrossSiteRedirector(embedded_test_server()); GURL test_url1 = embedded_test_server()->GetURL( @@ -377,8 +377,8 @@ } IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ReconnectPreservesState) { - ASSERT_TRUE(test_server()->Start()); - GURL test_url = test_server()->GetURL("files/devtools/navigation.html"); + ASSERT_TRUE(embedded_test_server()->Start()); + GURL test_url = embedded_test_server()->GetURL("/devtools/navigation.html"); NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1); Shell* second = CreateBrowser(); @@ -394,7 +394,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CrossSitePauseInBeforeUnload) { host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); content::SetupCrossSiteRedirector(embedded_test_server()); NavigateToURLBlockUntilNavigationsComplete(shell(),
diff --git a/content/browser/devtools/site_per_process_devtools_browsertest.cc b/content/browser/devtools/site_per_process_devtools_browsertest.cc index 80f1523..661ab8f 100644 --- a/content/browser/devtools/site_per_process_devtools_browsertest.cc +++ b/content/browser/devtools/site_per_process_devtools_browsertest.cc
@@ -53,8 +53,7 @@ MAYBE_CrossSiteIframeAgentHost) { DevToolsAgentHost::List list; host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(test_server()->Start()); - GURL main_url(test_server()->GetURL("files/site_per_process_main.html")); + GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); NavigateToURL(shell(), main_url); // It is safe to obtain the root frame tree node here, as it doesn't change. @@ -69,7 +68,7 @@ // Load same-site page into iframe. FrameTreeNode* child = root->child_at(0); - GURL http_url(test_server()->GetURL("files/title1.html")); + GURL http_url(embedded_test_server()->GetURL("/title1.html")); NavigateFrameToURL(child, http_url); list = DevToolsAgentHost::GetOrCreateAll(); @@ -79,7 +78,7 @@ // Load cross-site page into iframe. GURL::Replacements replace_host; - GURL cross_site_url(test_server()->GetURL("files/title2.html")); + GURL cross_site_url(embedded_test_server()->GetURL("/title2.html")); replace_host.SetHostStr("foo.com"); cross_site_url = cross_site_url.ReplaceComponents(replace_host); NavigateFrameToURL(root->child_at(0), cross_site_url);
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc index 93a9c9a..9bad4d3 100644 --- a/content/browser/download/download_browsertest.cc +++ b/content/browser/download/download_browsertest.cc
@@ -48,7 +48,6 @@ #include "content/browser/plugin_service_impl.h" #endif -using ::net::test_server::EmbeddedTestServer; using ::testing::AllOf; using ::testing::Field; using ::testing::InSequence; @@ -521,7 +520,7 @@ // Creates a request handler for EmbeddedTestServer that responds with a HTTP // 302 redirect if the request URL matches |relative_url|. -EmbeddedTestServer::HandleRequestCallback CreateRedirectHandler( +net::EmbeddedTestServer::HandleRequestCallback CreateRedirectHandler( const std::string& relative_url, const GURL& target_url) { return base::Bind( @@ -545,7 +544,7 @@ // Creates a request handler for an EmbeddedTestServer that response with an // HTTP 200 status code, a Content-Type header and a body. -EmbeddedTestServer::HandleRequestCallback CreateBasicResponseHandler( +net::EmbeddedTestServer::HandleRequestCallback CreateBasicResponseHandler( const std::string& relative_url, const std::string& content_type, const std::string& body) { @@ -702,7 +701,7 @@ void ReleaseRSTAndConfirmInterruptForResume(DownloadItem* download) { scoped_ptr<DownloadTestObserver> rst_observer( CreateInterruptedWaiter(shell(), 1)); - NavigateToURL(shell(), test_server()->GetURL("download-finish")); + NavigateToURL(shell(), spawned_test_server()->GetURL("download-finish")); rst_observer->WaitForFinished(); EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState()); } @@ -1072,11 +1071,11 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownload) { base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableDownloadResumption); - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(spawned_test_server()->Start()); - GURL url = test_server()->GetURL( + GURL url = spawned_test_server()->GetURL( base::StringPrintf("rangereset?size=%d&rst_boundary=%d", - GetSafeBufferChunk() * 3, GetSafeBufferChunk())); + GetSafeBufferChunk() * 3, GetSafeBufferChunk())); MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell())); EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1); @@ -1139,15 +1138,14 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownloadNoRange) { base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableDownloadResumption); - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(spawned_test_server()->Start()); // Auto-restart if server doesn't handle ranges. - GURL url = test_server()->GetURL( - base::StringPrintf( - // First download hits an RST, rest don't, no ranges. - "rangereset?size=%d&rst_boundary=%d&" - "token=NoRange&rst_limit=1&bounce_range", - GetSafeBufferChunk() * 3, GetSafeBufferChunk())); + GURL url = spawned_test_server()->GetURL(base::StringPrintf( + // First download hits an RST, rest don't, no ranges. + "rangereset?size=%d&rst_boundary=%d&" + "token=NoRange&rst_limit=1&bounce_range", + GetSafeBufferChunk() * 3, GetSafeBufferChunk())); // Start the download and wait for first data chunk. DownloadItem* download(StartDownloadAndReturnItem(url)); @@ -1188,14 +1186,13 @@ ResumeInterruptedDownloadBadPrecondition) { base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableDownloadResumption); - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(spawned_test_server()->Start()); - GURL url = test_server()->GetURL(base::StringPrintf( + GURL url = spawned_test_server()->GetURL(base::StringPrintf( // First download hits an RST, rest don't, precondition fail. "rangereset?size=%d&rst_boundary=%d&" "token=BadPrecondition&rst_limit=1&fail_precondition=2", - GetSafeBufferChunk() * 3, - GetSafeBufferChunk())); + GetSafeBufferChunk() * 3, GetSafeBufferChunk())); // Start the download and wait for first data chunk. DownloadItem* download(StartDownloadAndReturnItem(url)); @@ -1240,14 +1237,13 @@ ResumeInterruptedDownloadNoVerifiers) { base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableDownloadResumption); - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(spawned_test_server()->Start()); - GURL url = test_server()->GetURL( - base::StringPrintf( - // First download hits an RST, rest don't, no verifiers. - "rangereset?size=%d&rst_boundary=%d&" - "token=NoRange&rst_limit=1&no_verifiers", - GetSafeBufferChunk() * 3, GetSafeBufferChunk())); + GURL url = spawned_test_server()->GetURL(base::StringPrintf( + // First download hits an RST, rest don't, no verifiers. + "rangereset?size=%d&rst_boundary=%d&" + "token=NoRange&rst_limit=1&no_verifiers", + GetSafeBufferChunk() * 3, GetSafeBufferChunk())); // Start the download and wait for first data chunk. DownloadItem* download(StartDownloadAndReturnItem(url)); @@ -1284,14 +1280,13 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithDeletedFile) { base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableDownloadResumption); - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(spawned_test_server()->Start()); - GURL url = test_server()->GetURL( - base::StringPrintf( - // First download hits an RST, rest don't - "rangereset?size=%d&rst_boundary=%d&" - "token=NoRange&rst_limit=1", - GetSafeBufferChunk() * 3, GetSafeBufferChunk())); + GURL url = spawned_test_server()->GetURL(base::StringPrintf( + // First download hits an RST, rest don't + "rangereset?size=%d&rst_boundary=%d&" + "token=NoRange&rst_limit=1", + GetSafeBufferChunk() * 3, GetSafeBufferChunk())); // Start the download and wait for first data chunk. DownloadItem* download(StartDownloadAndReturnItem(url)); @@ -1488,9 +1483,9 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelInterruptedDownload) { base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableDownloadResumption); - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(spawned_test_server()->Start()); - GURL url1 = test_server()->GetURL( + GURL url1 = spawned_test_server()->GetURL( base::StringPrintf("rangereset?size=%d&rst_boundary=%d", GetSafeBufferChunk() * 3, GetSafeBufferChunk())); @@ -1518,12 +1513,12 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveDownload) { base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableDownloadResumption); - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(spawned_test_server()->Start()); // An interrupted download should remove the intermediate file when it is // removed. { - GURL url1 = test_server()->GetURL( + GURL url1 = spawned_test_server()->GetURL( base::StringPrintf("rangereset?size=%d&rst_boundary=%d", GetSafeBufferChunk() * 3, GetSafeBufferChunk())); @@ -1572,9 +1567,9 @@ SetupEnsureNoPendingDownloads(); base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableDownloadResumption); - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(spawned_test_server()->Start()); - GURL url = test_server()->GetURL( + GURL url = spawned_test_server()->GetURL( base::StringPrintf("rangereset?size=%d&rst_boundary=%d", GetSafeBufferChunk() * 3, GetSafeBufferChunk())); @@ -1609,7 +1604,8 @@ // Start the second download and wait until it's done. The test server is // single threaded. The response to this download request should follow the // response to the previous resumption request. - GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x")); + GURL url2( + spawned_test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x")); NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE); EXPECT_TRUE(EnsureNoPendingDownloads()); @@ -1619,9 +1615,9 @@ SetupEnsureNoPendingDownloads(); base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableDownloadResumption); - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(spawned_test_server()->Start()); - GURL url = test_server()->GetURL( + GURL url = spawned_test_server()->GetURL( base::StringPrintf("rangereset?size=%d&rst_boundary=%d", GetSafeBufferChunk() * 3, GetSafeBufferChunk())); @@ -1657,7 +1653,8 @@ // Start the second download and wait until it's done. The test server is // single threaded. The response to this download request should follow the // response to the previous resumption request. - GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x")); + GURL url2( + spawned_test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x")); NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE); EXPECT_TRUE(EnsureNoPendingDownloads()); @@ -1666,8 +1663,8 @@ // Check that the cookie policy is correctly updated when downloading a file // that redirects cross origin. IN_PROC_BROWSER_TEST_F(DownloadContentTest, CookiePolicy) { - ASSERT_TRUE(test_server()->Start()); - net::HostPortPair host_port = test_server()->host_port_pair(); + ASSERT_TRUE(spawned_test_server()->Start()); + net::HostPortPair host_port = spawned_test_server()->host_port_pair(); DCHECK_EQ(host_port.host(), std::string("127.0.0.1")); // Block third-party cookies. @@ -1677,7 +1674,7 @@ // cookie. std::string download(base::StringPrintf( "http://localhost:%d/set-cookie?A=B", host_port.port())); - GURL url(test_server()->GetURL("server-redirect?" + download)); + GURL url(spawned_test_server()->GetURL("server-redirect?" + download)); // Download the file. SetupEnsureNoPendingDownloads(); @@ -1706,10 +1703,10 @@ // download URL. IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeCrossOriginRedirect) { - EmbeddedTestServer origin_one; - EmbeddedTestServer origin_two; - ASSERT_TRUE(origin_one.InitializeAndWaitUntilReady()); - ASSERT_TRUE(origin_two.InitializeAndWaitUntilReady()); + net::EmbeddedTestServer origin_one; + net::EmbeddedTestServer origin_two; + ASSERT_TRUE(origin_one.Start()); + ASSERT_TRUE(origin_two.Start()); // The download-attribute.html page contains an anchor element whose href is // set to the value of the query parameter (specified as |target| in the URL @@ -1751,10 +1748,10 @@ // of the redirect chain. IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeSameOriginRedirect) { - EmbeddedTestServer origin_one; - EmbeddedTestServer origin_two; - ASSERT_TRUE(origin_one.InitializeAndWaitUntilReady()); - ASSERT_TRUE(origin_two.InitializeAndWaitUntilReady()); + net::EmbeddedTestServer origin_one; + net::EmbeddedTestServer origin_two; + ASSERT_TRUE(origin_one.Start()); + ASSERT_TRUE(origin_two.Start()); // The download-attribute.html page contains an anchor element whose href is // set to the value of the query parameter (specified as |target| in the URL @@ -1797,8 +1794,8 @@ // The content body is empty. Make sure this case is handled properly and we // don't regress on http://crbug.com/320394. IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadGZipWithNoContent) { - EmbeddedTestServer test_server; - ASSERT_TRUE(test_server.InitializeAndWaitUntilReady()); + net::EmbeddedTestServer test_server; + ASSERT_TRUE(test_server.Start()); GURL url = test_server.GetURL("/empty.bin"); test_server.ServeFilesFromDirectory(GetTestFilePath("download", "")); @@ -1808,7 +1805,7 @@ } IN_PROC_BROWSER_TEST_F(DownloadContentTest, Spam) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); NavigateToURLAndWaitForDownload( shell(),
diff --git a/content/browser/download/mhtml_generation_browsertest.cc b/content/browser/download/mhtml_generation_browsertest.cc index 771df828..8bffabbe 100644 --- a/content/browser/download/mhtml_generation_browsertest.cc +++ b/content/browser/download/mhtml_generation_browsertest.cc
@@ -31,7 +31,7 @@ protected: void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); ContentBrowserTest::SetUp(); } @@ -145,7 +145,7 @@ MHTMLGenerationTest::SetUpOnMainThread(); host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); content::SetupCrossSiteRedirector(embedded_test_server()); }
diff --git a/content/browser/download/save_package_browsertest.cc b/content/browser/download/save_package_browsertest.cc index 5b3bc1736..cca77cf 100644 --- a/content/browser/download/save_package_browsertest.cc +++ b/content/browser/download/save_package_browsertest.cc
@@ -7,10 +7,11 @@ #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" #include "content/shell/browser/shell.h" +#include "net/test/embedded_test_server/embedded_test_server.h" namespace content { -const char kTestFile[] = "files/simple_page.html"; +const char kTestFile[] = "/simple_page.html"; class SavePackageBrowserTest : public ContentBrowserTest { protected: @@ -34,22 +35,21 @@ // Create a SavePackage and delete it without calling Init. // SavePackage dtor has various asserts/checks that should not fire. IN_PROC_BROWSER_TEST_F(SavePackageBrowserTest, ImplicitCancel) { - ASSERT_TRUE(test_server()->Start()); - GURL url = test_server()->GetURL(kTestFile); + ASSERT_TRUE(embedded_test_server()->Start()); + GURL url = embedded_test_server()->GetURL(kTestFile); NavigateToURL(shell(), url); base::FilePath full_file_name, dir; GetDestinationPaths("a", &full_file_name, &dir); scoped_refptr<SavePackage> save_package(new SavePackage( shell()->web_contents(), SAVE_PAGE_TYPE_AS_ONLY_HTML, full_file_name, dir)); - ASSERT_TRUE(test_server()->Stop()); } // Create a SavePackage, call Cancel, then delete it. // SavePackage dtor has various asserts/checks that should not fire. IN_PROC_BROWSER_TEST_F(SavePackageBrowserTest, ExplicitCancel) { - ASSERT_TRUE(test_server()->Start()); - GURL url = test_server()->GetURL(kTestFile); + ASSERT_TRUE(embedded_test_server()->Start()); + GURL url = embedded_test_server()->GetURL(kTestFile); NavigateToURL(shell(), url); base::FilePath full_file_name, dir; GetDestinationPaths("a", &full_file_name, &dir); @@ -57,7 +57,6 @@ shell()->web_contents(), SAVE_PAGE_TYPE_AS_ONLY_HTML, full_file_name, dir)); save_package->Cancel(true); - ASSERT_TRUE(test_server()->Stop()); } } // namespace content
diff --git a/content/browser/frame_host/frame_tree_browsertest.cc b/content/browser/frame_host/frame_tree_browsertest.cc index a0450de..b9e3b43 100644 --- a/content/browser/frame_host/frame_tree_browsertest.cc +++ b/content/browser/frame_host/frame_tree_browsertest.cc
@@ -33,7 +33,7 @@ void SetUpOnMainThread() override { host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); SetupCrossSiteRedirector(embedded_test_server()); } @@ -322,7 +322,7 @@ void SetUpOnMainThread() override { host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); SetupCrossSiteRedirector(embedded_test_server()); }
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc index 4264c625..6ceff9a 100644 --- a/content/browser/frame_host/navigation_controller_impl.cc +++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -145,6 +145,13 @@ return last_entry && last_entry->GetIsOverridingUserAgent(); } +// Helper method for FrameTree::ForEach to set the nav_entry_id on each current +// RenderFrameHost in the tree. +bool SetFrameNavEntryID(int nav_entry_id, FrameTreeNode* node) { + node->current_frame_host()->set_nav_entry_id(nav_entry_id); + return true; +} + } // namespace // NavigationControllerImpl ---------------------------------------------------- @@ -947,13 +954,13 @@ NotifyNavigationEntryCommitted(details); - // Update the RenderViewHost of the top-level RenderFrameHost's notion of what - // entry it's showing for use later. - RenderFrameHostImpl* main_frame = - rfh->frame_tree_node()->frame_tree()->root()->current_frame_host(); - static_cast<RenderViewHostImpl*>(main_frame->GetRenderViewHost())-> - set_nav_entry_id(active_entry->GetUniqueID()); - + // Update the nav_entry_id for each RenderFrameHost in the tree, so that each + // one knows the latest NavigationEntry it is showing (whether it has + // committed anything in this navigation or not). This allows things like + // state and title updates from RenderFrames to apply to the latest relevant + // NavigationEntry. + delegate_->GetFrameTree()->ForEach( + base::Bind(&SetFrameNavEntryID, active_entry->GetUniqueID())); return true; }
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc index 1adbd7f..fe2616c 100644 --- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc +++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -37,7 +37,7 @@ protected: void SetUpOnMainThread() override { host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); } };
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 53524e4..d54b02b 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -190,6 +190,7 @@ unload_ack_is_for_navigation_(false), is_loading_(false), pending_commit_(false), + nav_entry_id_(0), accessibility_reset_token_(0), accessibility_reset_count_(0), no_create_browser_accessibility_manager_for_testing_(false),
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index a845ca40..7f4f9a5 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -254,6 +254,14 @@ // TODO(creis): Make bindings frame-specific, to support cases like <webview>. int GetEnabledBindings(); + // The unique ID of the latest NavigationEntry that this RenderFrameHost is + // showing. This may change even when this frame hasn't committed a page, + // such as for a new subframe navigation in a different frame. + int nav_entry_id() const { return nav_entry_id_; } + void set_nav_entry_id(int nav_entry_id) { nav_entry_id_ = nav_entry_id; } + + // A NavigationHandle for the pending navigation in this frame, if any. This + // is cleared when the navigation commits. NavigationHandleImpl* navigation_handle() const { return navigation_handle_.get(); } @@ -755,6 +763,13 @@ // tests. bool pending_commit_; + // The unique ID of the latest NavigationEntry that this RenderFrameHost is + // showing. This may change even when this frame hasn't committed a page, + // such as for a new subframe navigation in a different frame. Tracking this + // allows us to send things like title and state updates to the latest + // relevant NavigationEntry. + int nav_entry_id_; + // Used to swap out or shut down this RFH when the unload event is taking too // long to execute, depending on the number of active frames in the // SiteInstance.
diff --git a/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/content/browser/frame_host/render_frame_host_manager_browsertest.cc index ef0919d..d06b2ff 100644 --- a/content/browser/frame_host/render_frame_host_manager_browsertest.cc +++ b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -10,6 +10,7 @@ #include "base/memory/ref_counted.h" #include "base/path_service.h" #include "base/single_thread_task_runner.h" +#include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" #include "base/thread_task_runner_handle.h" #include "base/values.h" @@ -45,7 +46,7 @@ #include "net/base/net_util.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" -#include "net/test/spawned_test_server/spawned_test_server.h" +#include "net/test/embedded_test_server/request_handler_util.h" using base::ASCIIToUTF16; @@ -76,36 +77,36 @@ replace_host_.SetHostStr(foo_com_); } - static bool GetFilePathWithHostAndPortReplacement( + static void GetFilePathWithHostAndPortReplacement( const std::string& original_file_path, const net::HostPortPair& host_port_pair, std::string* replacement_path) { - std::vector<net::SpawnedTestServer::StringPair> replacement_text; + base::StringPairs replacement_text; replacement_text.push_back( make_pair("REPLACE_WITH_HOST_AND_PORT", host_port_pair.ToString())); - return net::SpawnedTestServer::GetFilePathWithReplacements( + net::test_server::GetFilePathWithReplacements( original_file_path, replacement_text, replacement_path); } void StartServer() { // Support multiple sites on the test server. host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(embedded_test_server()->Start()); - foo_host_port_ = test_server()->host_port_pair(); + foo_host_port_ = embedded_test_server()->host_port_pair(); foo_host_port_.set_host(foo_com_); } void StartEmbeddedServer() { // Support multiple sites on the embedded test server. host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); SetupCrossSiteRedirector(embedded_test_server()); } // Returns a URL on foo.com with the given path. GURL GetCrossSiteURL(const std::string& path) { - GURL cross_site_url(test_server()->GetURL(path)); + GURL cross_site_url(embedded_test_server()->GetURL(path)); return cross_site_url.ReplaceComponents(replace_host_); } @@ -999,8 +1000,8 @@ EXPECT_TRUE(orig_site_instance.get() != NULL); // Load a cross-site page that fails with a 204 error. - EXPECT_TRUE(NavigateToURLAndExpectNoCommit(shell(), - GetCrossSiteURL("nocontent"))); + EXPECT_TRUE( + NavigateToURLAndExpectNoCommit(shell(), GetCrossSiteURL("/nocontent"))); // We should still be looking at the normal page. Because we started from a // blank new tab, the typed URL will still be visible until the user clears it @@ -1016,7 +1017,7 @@ // Renderer-initiated navigations should work. base::string16 expected_title = ASCIIToUTF16("Title Of Awesomeness"); TitleWatcher title_watcher(shell()->web_contents(), expected_title); - GURL url = test_server()->GetURL("files/title2.html"); + GURL url = embedded_test_server()->GetURL("/title2.html"); EXPECT_TRUE(ExecuteScript( shell()->web_contents(), base::StringPrintf("location.href = '%s'", url.spec().c_str()))); @@ -1024,7 +1025,7 @@ // Opens in same tab. EXPECT_EQ(1u, Shell::windows().size()); - EXPECT_EQ("/files/title2.html", + EXPECT_EQ("/title2.html", shell()->web_contents()->GetLastCommittedURL().path()); // Should have the same SiteInstance. @@ -1038,11 +1039,11 @@ // about:blank page is modified by another window. At that point, we should // revert to showing about:blank to prevent a URL spoof. IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, ShowLoadingURLUntilSpoof) { - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(embedded_test_server()->Start()); // Load a page that can open a URL that won't commit in a new window. - NavigateToURL( - shell(), test_server()->GetURL("files/click-nocontent-link.html")); + NavigateToURL(shell(), + embedded_test_server()->GetURL("/click-nocontent-link.html")); WebContents* orig_contents = shell()->web_contents(); // Click a /nocontent link that opens in a new window but never commits. @@ -1088,11 +1089,11 @@ // show the pending URL without allowing a spoof. IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, DontShowLoadingURLIfNotInitialNav) { - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(embedded_test_server()->Start()); // Load a page that can open a URL that won't commit in a new window. - NavigateToURL( - shell(), test_server()->GetURL("files/click-nocontent-link.html")); + NavigateToURL(shell(), + embedded_test_server()->GetURL("/click-nocontent-link.html")); WebContents* orig_contents = shell()->web_contents(); // Click a /nocontent link that opens in a new window but never commits. @@ -1714,7 +1715,7 @@ file = file.AppendASCII("bar"); // Navigate to url and get it to reference a file in its PageState. - GURL url1(test_server()->GetURL("files/file_input.html")); + GURL url1(embedded_test_server()->GetURL("/file_input.html")); NavigateToURL(shell(), url1); int process_id = shell()->web_contents()->GetRenderProcessHost()->GetID(); scoped_ptr<FileChooserDelegate> delegate(new FileChooserDelegate(file)); @@ -1730,7 +1731,7 @@ RenderProcessHostWatcher exit_observer( shell()->web_contents()->GetRenderProcessHost(), RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION); - NavigateToURL(shell(), GetCrossSiteURL("files/title1.html")); + NavigateToURL(shell(), GetCrossSiteURL("/title1.html")); exit_observer.Wait(); EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile( shell()->web_contents()->GetRenderProcessHost()->GetID(), file)); @@ -1758,7 +1759,7 @@ // Navigate to a same site page to trigger a PageState update and ensure the // renderer is not killed. EXPECT_TRUE( - NavigateToURL(shell(), test_server()->GetURL("files/title2.html"))); + NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html"))); } // Test for http://crbug.com/441966. @@ -1770,7 +1771,7 @@ file = file.AppendASCII("bar"); // Navigate to url and get it to reference a file in its PageState. - GURL url1(test_server()->GetURL("files/file_input_subframe.html")); + GURL url1(embedded_test_server()->GetURL("/file_input_subframe.html")); NavigateToURL(shell(), url1); WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents()); FrameTreeNode* root = wc->GetFrameTree()->root(); @@ -1788,7 +1789,7 @@ RenderProcessHostWatcher exit_observer( shell()->web_contents()->GetRenderProcessHost(), RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION); - NavigateToURL(shell(), GetCrossSiteURL("files/title1.html")); + NavigateToURL(shell(), GetCrossSiteURL("/title1.html")); exit_observer.Wait(); EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile( shell()->web_contents()->GetRenderProcessHost()->GetID(), file));
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame_browsertest.cc b/content/browser/frame_host/render_widget_host_view_child_frame_browsertest.cc index e560382e..0f40c90 100644 --- a/content/browser/frame_host/render_widget_host_view_child_frame_browsertest.cc +++ b/content/browser/frame_host/render_widget_host_view_child_frame_browsertest.cc
@@ -27,7 +27,7 @@ void SetUpOnMainThread() override { host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); SetupCrossSiteRedirector(embedded_test_server()); }
diff --git a/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc b/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc index b3f658e..a7b4f93 100644 --- a/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc +++ b/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc
@@ -27,6 +27,7 @@ const char kUsbSubsystem[] = "usb"; const char kUsbDeviceType[] = "usb_device"; const float kMaxLinuxAxisValue = 32767.0; +const float kMinAxisResetValue = 0.1; void CloseFileDescriptorIfValid(int fd) { if (fd >= 0) @@ -69,9 +70,14 @@ using blink::WebGamepads; GamepadPlatformDataFetcherLinux::GamepadPlatformDataFetcherLinux() { - for (size_t i = 0; i < arraysize(device_fds_); ++i) - device_fds_[i] = -1; - memset(mappers_, 0, sizeof(mappers_)); + for (size_t i = 0; i < arraysize(pad_state_); ++i) { + pad_state_[i].device_fd = -1; + pad_state_[i].mapper = 0; + for (size_t j = 0; j < arraysize(pad_state_[i].is_axes_ever_reset); ++j) + pad_state_[i].is_axes_ever_reset[j] = false; + for (size_t j = 0; j < arraysize(pad_state_[i].is_buttons_ever_reset); ++j) + pad_state_[i].is_buttons_ever_reset[j] = false; + } std::vector<UdevLinux::UdevMonitorFilter> filters; filters.push_back(UdevLinux::UdevMonitorFilter(kInputSubsystem, NULL)); @@ -85,29 +91,27 @@ GamepadPlatformDataFetcherLinux::~GamepadPlatformDataFetcherLinux() { for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) - CloseFileDescriptorIfValid(device_fds_[i]); + CloseFileDescriptorIfValid(pad_state_[i].device_fd); } void GamepadPlatformDataFetcherLinux::GetGamepadData(WebGamepads* pads, bool) { TRACE_EVENT0("GAMEPAD", "GetGamepadData"); - data_.length = WebGamepads::itemsLengthCap; - // Update our internal state. for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { - if (device_fds_[i] >= 0) { + if (pad_state_[i].device_fd >= 0) { ReadDeviceData(i); } } // Copy to the current state to the output buffer, using the mapping // function, if there is one available. - pads->length = data_.length; + pads->length = WebGamepads::itemsLengthCap; for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { - if (mappers_[i]) - mappers_[i](data_.items[i], &pads->items[i]); + if (pad_state_[i].mapper) + pad_state_[i].mapper(pad_state_[i].data, &pads->items[i]); else - pads->items[i] = data_.items[i]; + pads->items[i] = pad_state_[i].data; } } @@ -115,10 +119,12 @@ void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) { int index; std::string node_path; - if (IsGamepad(dev, &index, &node_path)) { - int& device_fd = device_fds_[index]; - WebGamepad& pad = data_.items[index]; - GamepadStandardMappingFunction& mapper = mappers_[index]; + if (IsGamepad(dev, &index, &node_path)) { + int& device_fd = pad_state_[index].device_fd; + WebGamepad& pad = pad_state_[index].data; + GamepadStandardMappingFunction& mapper = pad_state_[index].mapper; + bool* axes_reset = pad_state_[index].is_axes_ever_reset; + bool* buttons_reset = pad_state_[index].is_buttons_ever_reset; CloseFileDescriptorIfValid(device_fd); @@ -203,6 +209,11 @@ pad.mapping[0] = 0; } + for (size_t j = 0; j < blink::WebGamepad::axesLengthCap; ++j) + axes_reset[j] = false; + for (size_t j = 0; j < blink::WebGamepad::buttonsLengthCap; ++j) + buttons_reset[j] = false; + pad.connected = true; } } @@ -242,8 +253,10 @@ return; } - const int& fd = device_fds_[index]; - WebGamepad& pad = data_.items[index]; + const int& fd = pad_state_[index].device_fd; + WebGamepad& pad = pad_state_[index].data; + bool* axes_reset = pad_state_[index].is_axes_ever_reset; + bool* buttons_reset = pad_state_[index].is_buttons_ever_reset; DCHECK_GE(fd, 0); js_event event; @@ -252,14 +265,33 @@ if (event.type & JS_EVENT_AXIS) { if (item >= WebGamepad::axesLengthCap) continue; - pad.axes[item] = event.value / kMaxLinuxAxisValue; + + float val = event.value / kMaxLinuxAxisValue; + if (fabs(val) < kMinAxisResetValue) + axes_reset[item] = true; + + if (axes_reset[item]) + pad.axes[item] = val; + else + pad.axes[item] = 0.0; + if (item >= pad.axesLength) pad.axesLength = item + 1; } else if (event.type & JS_EVENT_BUTTON) { if (item >= WebGamepad::buttonsLengthCap) continue; - pad.buttons[item].pressed = event.value; - pad.buttons[item].value = event.value ? 1.0 : 0.0; + + if (!event.value) + buttons_reset[item] = true; + + if (buttons_reset[item]) { + pad.buttons[item].pressed = event.value; + pad.buttons[item].value = event.value ? 1.0 : 0.0; + } else { + pad.buttons[item].pressed = false; + pad.buttons[item].value = 0.0; + } + if (item >= pad.buttonsLength) pad.buttonsLength = item + 1; }
diff --git a/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h b/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h index dab9497..3742d60c 100644 --- a/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h +++ b/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h
@@ -36,15 +36,21 @@ void EnumerateDevices(); void ReadDeviceData(size_t index); - // File descriptors for the /dev/input/js* devices. -1 if not in use. - int device_fds_[blink::WebGamepads::itemsLengthCap]; + struct PadState { + // File descriptor for the /dev/input/js* devices. -1 if not in use. + int device_fd; - // Functions to map from device data to standard layout, if available. May - // be null if no mapping is available. - GamepadStandardMappingFunction mappers_[blink::WebGamepads::itemsLengthCap]; + // Functions to map from device data to standard layout, if available. May + // be null if no mapping is available. + GamepadStandardMappingFunction mapper; - // Data that's returned to the consumer. - blink::WebGamepads data_; + bool is_axes_ever_reset[blink::WebGamepad::axesLengthCap]; + bool is_buttons_ever_reset[blink::WebGamepad::buttonsLengthCap]; + + // Data that's returned to the consumer. + blink::WebGamepad data; + }; + PadState pad_state_[blink::WebGamepads::itemsLengthCap]; scoped_ptr<UdevLinux> udev_;
diff --git a/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc b/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc index aca00960..88aa7ec0 100644 --- a/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc +++ b/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc
@@ -30,6 +30,8 @@ static const BYTE kDeviceSubTypeGuitarBass = 11; static const BYTE kDeviceSubTypeArcadePad = 19; +static const float kMinAxisResetValue = 0.1f; + float NormalizeXInputAxis(SHORT value) { return ((value + 32768.f) / 32767.5f) - 1.f; } @@ -55,8 +57,13 @@ GamepadPlatformDataFetcherWin::GamepadPlatformDataFetcherWin() : xinput_dll_(base::FilePath(FILE_PATH_LITERAL("xinput1_3.dll"))), xinput_available_(GetXInputDllFunctions()) { - for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) + for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { pad_state_[i].status = DISCONNECTED; + for (size_t j = 0; j < arraysize(pad_state_[i].is_axes_ever_reset); ++j) + pad_state_[i].is_axes_ever_reset[j] = false; + for (size_t j = 0; j < arraysize(pad_state_[i].is_buttons_ever_reset); ++j) + pad_state_[i].is_buttons_ever_reset[j] = false; + } raw_input_fetcher_.reset(new RawInputDataFetcher()); raw_input_fetcher_->StartMonitor(); @@ -115,6 +122,12 @@ pad_state_[pad_index].xinput_index = i; pad_state_[pad_index].mapper = NULL; } + bool* axes_reset = pad_state_[pad_index].is_axes_ever_reset; + bool* buttons_reset = pad_state_[pad_index].is_buttons_ever_reset; + for (size_t j = 0; j < blink::WebGamepad::axesLengthCap; ++j) + axes_reset[j] = false; + for (size_t j = 0; j < blink::WebGamepad::buttonsLengthCap; ++j) + buttons_reset[j] = false; } if (raw_input_fetcher_->Available()) { @@ -149,6 +162,12 @@ else pad.mapping[0] = 0; + bool* axes_reset = pad_state_[pad_index].is_axes_ever_reset; + bool* buttons_reset = pad_state_[pad_index].is_buttons_ever_reset; + for (size_t j = 0; j < blink::WebGamepad::axesLengthCap; ++j) + axes_reset[j] = false; + for (size_t j = 0; j < blink::WebGamepad::buttonsLengthCap; ++j) + buttons_reset[j] = false; } } } @@ -175,6 +194,7 @@ EnumerateDevices(pads); pads->length = 0; + for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { // We rely on device_changed and GetCapabilities to tell us that // something's been connected, but we will mark as disconnected if @@ -232,24 +252,45 @@ if (dwResult == ERROR_SUCCESS) { pad->timestamp = state.dwPacketNumber; pad->buttonsLength = 0; -#define ADD(b) pad->buttons[pad->buttonsLength].pressed = \ - (state.Gamepad.wButtons & (b)) != 0; \ - pad->buttons[pad->buttonsLength++].value = \ - ((state.Gamepad.wButtons & (b)) ? 1.f : 0.f); + WORD val = state.Gamepad.wButtons; +#define ADD(b) if (!val) \ + pad_state_[i].is_buttons_ever_reset[pad->buttonsLength] = true; \ + if (pad_state_[i].is_buttons_ever_reset[pad->buttonsLength]) { \ + pad->buttons[pad->buttonsLength].pressed = (val & (b)) != 0; \ + pad->buttons[pad->buttonsLength++].value = ((val & (b)) ? 1.f : 0.f); \ + } else { \ + pad->buttons[pad->buttonsLength].pressed = false; \ + pad->buttons[pad->buttonsLength++].value = 0.0; \ + } ADD(XINPUT_GAMEPAD_A); ADD(XINPUT_GAMEPAD_B); ADD(XINPUT_GAMEPAD_X); ADD(XINPUT_GAMEPAD_Y); ADD(XINPUT_GAMEPAD_LEFT_SHOULDER); ADD(XINPUT_GAMEPAD_RIGHT_SHOULDER); - pad->buttons[pad->buttonsLength].pressed = + if (state.Gamepad.bLeftTrigger < XINPUT_GAMEPAD_TRIGGER_THRESHOLD) + pad_state_[i].is_buttons_ever_reset[pad->buttonsLength] = true; + if (pad_state_[i].is_buttons_ever_reset[pad->buttonsLength]) { + pad->buttons[pad->buttonsLength].pressed = state.Gamepad.bLeftTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD; - pad->buttons[pad->buttonsLength++].value = + pad->buttons[pad->buttonsLength++].value = state.Gamepad.bLeftTrigger / 255.f; - pad->buttons[pad->buttonsLength].pressed = + } else { + pad->buttons[pad->buttonsLength].pressed = false; + pad->buttons[pad->buttonsLength++].value = 0.0; + } + + if (state.Gamepad.bRightTrigger < XINPUT_GAMEPAD_TRIGGER_THRESHOLD) + pad_state_[i].is_buttons_ever_reset[pad->buttonsLength] = true; + if (pad_state_[i].is_buttons_ever_reset[pad->buttonsLength]) { + pad->buttons[pad->buttonsLength].pressed = state.Gamepad.bRightTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD; - pad->buttons[pad->buttonsLength++].value = + pad->buttons[pad->buttonsLength++].value = state.Gamepad.bRightTrigger / 255.f; + } else { + pad->buttons[pad->buttonsLength].pressed = false; + pad->buttons[pad->buttonsLength++].value = 0.0; + } ADD(XINPUT_GAMEPAD_BACK); ADD(XINPUT_GAMEPAD_START); ADD(XINPUT_GAMEPAD_LEFT_THUMB); @@ -260,11 +301,22 @@ ADD(XINPUT_GAMEPAD_DPAD_RIGHT); #undef ADD pad->axesLength = 0; + + float value = 0.0; +#define ADD(a, factor) value = factor * NormalizeXInputAxis(a); \ + if (fabs(value) < kMinAxisResetValue) \ + pad_state_[i].is_axes_ever_reset[pad->axesLength] = true; \ + if (pad_state_[i].is_axes_ever_reset[pad->axesLength]) \ + pad->axes[pad->axesLength++] = value; \ + else \ + pad->axes[pad->axesLength++] = 0.0; + // XInput are +up/+right, -down/-left, we want -up/-left. - pad->axes[pad->axesLength++] = NormalizeXInputAxis(state.Gamepad.sThumbLX); - pad->axes[pad->axesLength++] = -NormalizeXInputAxis(state.Gamepad.sThumbLY); - pad->axes[pad->axesLength++] = NormalizeXInputAxis(state.Gamepad.sThumbRX); - pad->axes[pad->axesLength++] = -NormalizeXInputAxis(state.Gamepad.sThumbRY); + ADD(state.Gamepad.sThumbLX, 1); + ADD(state.Gamepad.sThumbLY, -1); + ADD(state.Gamepad.sThumbRX, 1); + ADD(state.Gamepad.sThumbRY, -1); +#undef ADD } else { pad->connected = false; } @@ -287,12 +339,27 @@ raw_pad.axesLength = gamepad->axes_length; for (unsigned int i = 0; i < raw_pad.buttonsLength; i++) { - raw_pad.buttons[i].pressed = gamepad->buttons[i]; - raw_pad.buttons[i].value = gamepad->buttons[i] ? 1.0 : 0.0; + if (!gamepad->buttons[i]) + pad_state_[index].is_buttons_ever_reset[i] = true; + + if (pad_state_[index].is_buttons_ever_reset[i]) { + raw_pad.buttons[i].pressed = gamepad->buttons[i]; + raw_pad.buttons[i].value = gamepad->buttons[i] ? 1.0 : 0.0; + } else { + raw_pad.buttons[i].pressed = false; + raw_pad.buttons[i].value = 0.0; + } } - for (unsigned int i = 0; i < raw_pad.axesLength; i++) - raw_pad.axes[i] = gamepad->axes[i].value; + for (unsigned int i = 0; i < raw_pad.axesLength; i++) { + if (fabs(gamepad->axes[i].value) < kMinAxisResetValue) + pad_state_[index].is_axes_ever_reset[i] = true; + + if (pad_state_[index].is_axes_ever_reset[i]) + raw_pad.axes[i] = gamepad->axes[i].value; + else + raw_pad.axes[i] = 0.0; + } // Copy to the current state to the output buffer, using the mapping // function, if there is one available.
diff --git a/content/browser/gamepad/gamepad_platform_data_fetcher_win.h b/content/browser/gamepad/gamepad_platform_data_fetcher_win.h index 33dab0ca2..86ea629 100644 --- a/content/browser/gamepad/gamepad_platform_data_fetcher_win.h +++ b/content/browser/gamepad/gamepad_platform_data_fetcher_win.h
@@ -85,6 +85,9 @@ PadConnectionStatus status; GamepadStandardMappingFunction mapper; + bool is_axes_ever_reset[blink::WebGamepad::axesLengthCap]; + bool is_buttons_ever_reset[blink::WebGamepad::buttonsLengthCap]; + int xinput_index; // XInput-only HANDLE raw_input_handle; // RawInput-only fields. };
diff --git a/content/browser/gamepad/gamepad_provider_unittest.cc b/content/browser/gamepad/gamepad_provider_unittest.cc index c810a6ac..b75be3eb 100644 --- a/content/browser/gamepad/gamepad_provider_unittest.cc +++ b/content/browser/gamepad/gamepad_provider_unittest.cc
@@ -126,8 +126,8 @@ no_button_data.items[0].axesLength = 2; no_button_data.items[0].buttons[0].value = 0.f; no_button_data.items[0].buttons[0].pressed = false; - no_button_data.items[0].axes[0] = -1.f; - no_button_data.items[0].axes[1] = .5f; + no_button_data.items[0].axes[0] = 0.f; + no_button_data.items[0].axes[1] = .4f; WebGamepads button_down_data = no_button_data; button_down_data.items[0].buttons[0].value = 1.f;
diff --git a/content/browser/gpu/browser_gpu_memory_buffer_manager.cc b/content/browser/gpu/browser_gpu_memory_buffer_manager.cc index 189f0c5e..fa61b00a 100644 --- a/content/browser/gpu/browser_gpu_memory_buffer_manager.cc +++ b/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
@@ -146,11 +146,12 @@ gfx::BufferFormat::RGBA_8888, gfx::BufferFormat::RGBX_8888, gfx::BufferFormat::BGRA_8888, gfx::BufferFormat::BGRX_8888, gfx::BufferFormat::UYVY_422, gfx::BufferFormat::YUV_420_BIPLANAR}; + const gfx::BufferUsage kGPUReadWriteUsages[] = { + gfx::BufferUsage::GPU_READ, gfx::BufferUsage::SCANOUT}; for (auto& format : kGPUReadWriteFormats) { - if (IsNativeGpuMemoryBufferFactoryConfigurationSupported( - format, gfx::BufferUsage::SCANOUT)) { - configurations.insert( - std::make_pair(format, gfx::BufferUsage::SCANOUT)); + for (auto& usage : kGPUReadWriteUsages) { + if (IsNativeGpuMemoryBufferFactoryConfigurationSupported(format, usage)) + configurations.insert(std::make_pair(format, usage)); } } }
diff --git a/content/browser/gpu/compositor_util.cc b/content/browser/gpu/compositor_util.cc index c6aabfbe..1b77f8b9 100644 --- a/content/browser/gpu/compositor_util.cc +++ b/content/browser/gpu/compositor_util.cc
@@ -216,6 +216,13 @@ return command_line.HasSwitch(switches::kEnablePartialRaster); } +bool IsGpuMemoryBufferCompositorResourcesEnabled() { + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + return command_line.HasSwitch( + switches::kEnableGpuMemoryBufferCompositorResources); +} + bool IsGpuRasterizationEnabled() { const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
diff --git a/content/browser/gpu/compositor_util.h b/content/browser/gpu/compositor_util.h index 82cd778..1dc495a 100644 --- a/content/browser/gpu/compositor_util.h +++ b/content/browser/gpu/compositor_util.h
@@ -24,6 +24,9 @@ // Returns true if a partial raster is on (via flags). CONTENT_EXPORT bool IsPartialRasterEnabled(); +// Returns true if all compositor resources should use GPU memory buffers. +CONTENT_EXPORT bool IsGpuMemoryBufferCompositorResourcesEnabled(); + // Returns true if gpu rasterization is on (via flags) for the renderer. CONTENT_EXPORT bool IsGpuRasterizationEnabled();
diff --git a/content/browser/indexed_db/indexed_db_browsertest.cc b/content/browser/indexed_db/indexed_db_browsertest.cc index f4c949a4..0428d35 100644 --- a/content/browser/indexed_db/indexed_db_browsertest.cc +++ b/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -693,7 +693,7 @@ IN_PROC_BROWSER_TEST_P(IndexedDBBrowserTest, OperationOnCorruptedOpenDatabase) { ASSERT_TRUE(embedded_test_server()->Started() || - embedded_test_server()->InitializeAndWaitUntilReady()); + embedded_test_server()->Start()); const GURL& origin_url = embedded_test_server()->base_url(); embedded_test_server()->RegisterRequestHandler( base::Bind(&CorruptDBRequestHandler,
diff --git a/content/browser/loader/async_resource_handler_browsertest.cc b/content/browser/loader/async_resource_handler_browsertest.cc index 4276ce2b..08d253e 100644 --- a/content/browser/loader/async_resource_handler_browsertest.cc +++ b/content/browser/loader/async_resource_handler_browsertest.cc
@@ -65,8 +65,8 @@ }; IN_PROC_BROWSER_TEST_F(AsyncResourceHandlerBrowserTest, UploadProgress) { - net::test_server::EmbeddedTestServer* test_server = embedded_test_server(); - ASSERT_TRUE(test_server->InitializeAndWaitUntilReady()); + net::EmbeddedTestServer* test_server = embedded_test_server(); + ASSERT_TRUE(test_server->Start()); test_server->RegisterRequestHandler( base::Bind(&HandlePostAndRedirectURLs, kPostPath)); @@ -85,8 +85,8 @@ IN_PROC_BROWSER_TEST_F(AsyncResourceHandlerBrowserTest, UploadProgressRedirect) { - net::test_server::EmbeddedTestServer* test_server = embedded_test_server(); - ASSERT_TRUE(test_server->InitializeAndWaitUntilReady()); + net::EmbeddedTestServer* test_server = embedded_test_server(); + ASSERT_TRUE(test_server->Start()); test_server->RegisterRequestHandler( base::Bind(&HandlePostAndRedirectURLs, kRedirectPostPath));
diff --git a/content/browser/loader/cross_site_resource_handler_browsertest.cc b/content/browser/loader/cross_site_resource_handler_browsertest.cc index ba0f3cc..fabefab 100644 --- a/content/browser/loader/cross_site_resource_handler_browsertest.cc +++ b/content/browser/loader/cross_site_resource_handler_browsertest.cc
@@ -183,7 +183,7 @@ &CrossSiteResourceHandlerTest::InjectResourceDispatcherHostDelegate, base::Unretained(this))); host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); content::SetupCrossSiteRedirector(embedded_test_server()); }
diff --git a/content/browser/loader/resource_dispatcher_host_browsertest.cc b/content/browser/loader/resource_dispatcher_host_browsertest.cc index f82fe7c..954eab0 100644 --- a/content/browser/loader/resource_dispatcher_host_browsertest.cc +++ b/content/browser/loader/resource_dispatcher_host_browsertest.cc
@@ -99,7 +99,7 @@ // Test title for content created by javascript window.open(). // See http://crbug.com/5988 IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DynamicTitle1) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/dynamic1.html")); base::string16 title; @@ -112,7 +112,7 @@ // Test title for content created by javascript window.open(). // See http://crbug.com/5988 IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DynamicTitle2) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/dynamic2.html")); base::string16 title; @@ -177,7 +177,7 @@ // Test for bug #1091358. IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, SyncXMLHttpRequest) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); NavigateToURL( shell(), embedded_test_server()->GetURL("/sync_xmlhttprequest.html")); @@ -193,7 +193,7 @@ // If this flakes, use http://crbug.com/62776. IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, SyncXMLHttpRequest_Disallowed) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); NavigateToURL( shell(), embedded_test_server()->GetURL("/sync_xmlhttprequest_disallowed.html")); @@ -219,7 +219,7 @@ #endif IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, MAYBE_SyncXMLHttpRequest_DuringUnload) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); BrowserContext::GetDownloadManager( shell()->web_contents()->GetBrowserContext())->AddObserver(this); @@ -239,7 +239,7 @@ // Tests that onunload is run for cross-site requests. (Bug 1114994) IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DISABLED_CrossSiteOnunloadCookie) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url = embedded_test_server()->GetURL("/onunload_cookie.html"); CheckTitleTest(url, "set cookie on unload"); @@ -259,7 +259,7 @@ // without network loads (e.g., about:blank, data URLs). IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DISABLED_CrossSiteImmediateLoadOnunloadCookie) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url = embedded_test_server()->GetURL("/onunload_cookie.html"); CheckTitleTest(url, "set cookie on unload"); @@ -294,7 +294,7 @@ // If this flakes use http://crbug.com/80596. IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, CrossSiteNoUnloadOn204) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); // Start with a URL that sets a cookie in its unload handler. GURL url = embedded_test_server()->GetURL("/onunload_cookie.html"); @@ -364,7 +364,7 @@ // away from the link doctor page. (Bug 1235537) IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DISABLED_CrossSiteNavigationErrorPage) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/onunload_cookie.html")); CheckTitleTest(url, "set cookie on unload"); @@ -409,7 +409,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, CrossSiteNavigationErrorPage2) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/title2.html")); CheckTitleTest(url, "Title Of Awesomeness"); @@ -480,7 +480,7 @@ // Test that we update the cookie policy URLs correctly when transferring // navigations. IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, CookiePolicy) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); embedded_test_server()->RegisterRequestHandler( base::Bind(&HandleRedirectRequest, "/redirect?")); @@ -524,7 +524,7 @@ // when encountering a meta refresh tag. IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, PageTransitionClientRedirect) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); PageTransitionResourceDispatcherHostDelegate delegate( embedded_test_server()->GetURL("/title1.html"));
diff --git a/content/browser/manifest/manifest_browsertest.cc b/content/browser/manifest/manifest_browsertest.cc index d419442..92ee4e53 100644 --- a/content/browser/manifest/manifest_browsertest.cc +++ b/content/browser/manifest/manifest_browsertest.cc
@@ -47,11 +47,9 @@ friend MockWebContentsDelegate; ManifestBrowserTest() : console_error_count_(0), has_manifest_(false) { - cors_embedded_test_server_.reset(new net::test_server::EmbeddedTestServer); - base::FilePath test_data_dir; - CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir)); - cors_embedded_test_server_->ServeFilesFromDirectory( - test_data_dir.AppendASCII("content/test/data/")); + cors_embedded_test_server_.reset(new net::EmbeddedTestServer); + cors_embedded_test_server_->ServeFilesFromSourceDirectory( + "content/test/data"); } ~ManifestBrowserTest() override {} @@ -109,14 +107,14 @@ console_error_count_++; } - net::test_server::EmbeddedTestServer* cors_embedded_test_server() const { + net::EmbeddedTestServer* cors_embedded_test_server() const { return cors_embedded_test_server_.get(); } private: scoped_refptr<MessageLoopRunner> message_loop_runner_; scoped_ptr<MockWebContentsDelegate> mock_web_contents_delegate_; - scoped_ptr<net::test_server::EmbeddedTestServer> cors_embedded_test_server_; + scoped_ptr<net::EmbeddedTestServer> cors_embedded_test_server_; Manifest manifest_; int console_error_count_; bool has_manifest_; @@ -274,8 +272,8 @@ // rules and requesting the manifest should return an empty manifest (unless the // response contains CORS headers). IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, CORSManifest) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); - ASSERT_TRUE(cors_embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); + ASSERT_TRUE(cors_embedded_test_server()->Start()); ASSERT_NE(embedded_test_server()->port(), cors_embedded_test_server()->port()); @@ -314,8 +312,8 @@ // If a page's manifest lives in a different origin, it should be accessible if // it has valid access controls headers. IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, CORSManifestWithAcessControls) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); - ASSERT_TRUE(cors_embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); + ASSERT_TRUE(cors_embedded_test_server()->Start()); ASSERT_NE(embedded_test_server()->port(), cors_embedded_test_server()->port()); @@ -342,12 +340,11 @@ // If a page's manifest is in an insecure origin while the page is in a secure // origin, requesting the manifest should return the empty manifest. IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, MixedContentManifest) { - scoped_ptr<net::SpawnedTestServer> https_server(new net::SpawnedTestServer( - net::SpawnedTestServer::TYPE_HTTPS, - net::BaseTestServer::SSLOptions(net::BaseTestServer::SSLOptions::CERT_OK), - base::FilePath(FILE_PATH_LITERAL("content/test/data")))); + scoped_ptr<net::EmbeddedTestServer> https_server( + new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS)); + https_server->ServeFilesFromSourceDirectory("content/test/data"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); ASSERT_TRUE(https_server->Start()); GURL test_url = @@ -390,7 +387,7 @@ // If a page has a manifest and the page is navigated to a page without a // manifest, the page's manifest should be updated. IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, Navigation) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); { GURL test_url = embedded_test_server()->GetURL("/manifest/dummy-manifest.html"); @@ -427,7 +424,7 @@ // If a page has a manifest and the page is navigated using pushState (ie. same // page), it should keep its manifest state. IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, PushStateNavigation) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL test_url = embedded_test_server()->GetURL("/manifest/dummy-manifest.html"); @@ -456,7 +453,7 @@ // If a page has a manifest and is navigated using an anchor (ie. same page), it // should keep its manifest state. IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, AnchorNavigation) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL test_url = embedded_test_server()->GetURL("/manifest/dummy-manifest.html"); @@ -519,12 +516,12 @@ // This tests that when fetching a Manifest with 'use-credentials' set, the // cookies associated with it are passed along the request. IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, UseCredentialsSendCookies) { - scoped_ptr<net::test_server::EmbeddedTestServer> custom_embedded_test_server( - new net::test_server::EmbeddedTestServer()); + scoped_ptr<net::EmbeddedTestServer> custom_embedded_test_server( + new net::EmbeddedTestServer()); custom_embedded_test_server->RegisterRequestHandler( base::Bind(&CustomHandleRequestForCookies)); - ASSERT_TRUE(custom_embedded_test_server->InitializeAndWaitUntilReady()); + ASSERT_TRUE(custom_embedded_test_server->Start()); ASSERT_TRUE(SetCookie(shell()->web_contents()->GetBrowserContext(), custom_embedded_test_server->base_url(), @@ -578,12 +575,12 @@ // This tests that when fetching a Manifest without 'use-credentials' set, the // cookies associated with it are not passed along the request. IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, NoUseCredentialsNoCookies) { - scoped_ptr<net::test_server::EmbeddedTestServer> custom_embedded_test_server( - new net::test_server::EmbeddedTestServer()); + scoped_ptr<net::EmbeddedTestServer> custom_embedded_test_server( + new net::EmbeddedTestServer()); custom_embedded_test_server->RegisterRequestHandler( base::Bind(&CustomHandleRequestForNoCookies)); - ASSERT_TRUE(custom_embedded_test_server->InitializeAndWaitUntilReady()); + ASSERT_TRUE(custom_embedded_test_server->Start()); ASSERT_TRUE(SetCookie(shell()->web_contents()->GetBrowserContext(), custom_embedded_test_server->base_url(),
diff --git a/content/browser/media/capture/aura_window_capture_machine.cc b/content/browser/media/capture/aura_window_capture_machine.cc index 11150ea..4198adb 100644 --- a/content/browser/media/capture/aura_window_capture_machine.cc +++ b/content/browser/media/capture/aura_window_capture_machine.cc
@@ -107,7 +107,7 @@ if (!cursor_bitmap.isNull()) RenderCursorOnVideoFrame(target, cursor_bitmap, cursor_position); - release_callback->Run(0, false); + release_callback->Run(gpu::SyncToken(), false); // Only deliver the captured frame if the AuraWindowCaptureMachine has not // been stopped (i.e., the WeakPtr is still valid). @@ -116,8 +116,8 @@ } void RunSingleReleaseCallback(scoped_ptr<cc::SingleReleaseCallback> cb, - uint32 sync_point) { - cb->Run(sync_point, false); + const gpu::SyncToken& sync_token) { + cb->Run(sync_token, false); } } // namespace @@ -335,8 +335,9 @@ return false; video_frame = media::VideoFrame::WrapNativeTexture( media::PIXEL_FORMAT_ARGB, - gpu::MailboxHolder(texture_mailbox.mailbox(), texture_mailbox.target(), - texture_mailbox.sync_point()), + gpu::MailboxHolder(texture_mailbox.mailbox(), + texture_mailbox.sync_token(), + texture_mailbox.target()), base::Bind(&RunSingleReleaseCallback, base::Passed(&release_callback)), result->size(), gfx::Rect(result->size()), result->size(), base::TimeDelta()); @@ -389,17 +390,11 @@ gfx::Point cursor_position_in_frame = UpdateCursorState(region_in_frame); yuv_readback_pipeline_->ReadbackYUV( - texture_mailbox.mailbox(), - texture_mailbox.sync_point(), - video_frame.get(), - region_in_frame.origin(), - base::Bind(&CopyOutputFinishedForVideo, - weak_factory_.GetWeakPtr(), - start_time, - capture_frame_cb, - video_frame, - scaled_cursor_bitmap_, - cursor_position_in_frame, + texture_mailbox.mailbox(), texture_mailbox.sync_token(), + video_frame.get(), region_in_frame.origin(), + base::Bind(&CopyOutputFinishedForVideo, weak_factory_.GetWeakPtr(), + start_time, capture_frame_cb, video_frame, + scaled_cursor_bitmap_, cursor_position_in_frame, base::Passed(&release_callback))); return true; }
diff --git a/content/browser/media/media_browsertest.cc b/content/browser/media/media_browsertest.cc index f47c4a50..d0955cc7 100644 --- a/content/browser/media/media_browsertest.cc +++ b/content/browser/media/media_browsertest.cc
@@ -11,7 +11,7 @@ #include "content/public/test/content_browser_test_utils.h" #include "content/shell/browser/shell.h" #include "media/base/test_data_util.h" -#include "net/test/spawned_test_server/spawned_test_server.h" +#include "net/test/embedded_test_server/embedded_test_server.h" namespace content { @@ -26,14 +26,12 @@ bool http) { GURL gurl; std::string query = media::GetURLQueryString(query_params); - scoped_ptr<net::SpawnedTestServer> http_test_server; + scoped_ptr<net::EmbeddedTestServer> http_test_server; if (http) { - http_test_server.reset( - new net::SpawnedTestServer(net::SpawnedTestServer::TYPE_HTTP, - net::SpawnedTestServer::kLocalhost, - media::GetTestDataPath())); + http_test_server.reset(new net::EmbeddedTestServer); + http_test_server->ServeFilesFromSourceDirectory(media::GetTestDataPath()); CHECK(http_test_server->Start()); - gurl = http_test_server->GetURL("files/" + html_page + "?" + query); + gurl = http_test_server->GetURL("/" + html_page + "?" + query); } else { gurl = content::GetFileUrlWithQuery(media::GetTestDataFilePath(html_page), query);
diff --git a/content/browser/media/media_browsertest.h b/content/browser/media/media_browsertest.h index caf5d14..180cc2c 100644 --- a/content/browser/media/media_browsertest.h +++ b/content/browser/media/media_browsertest.h
@@ -15,8 +15,8 @@ class TitleWatcher; // Class used to automate running media related browser tests. The functions -// assume that media files are located under files/media/ folder known to -// the test http server. +// assume that media files are located under media/ folder known to the test +// http server. class MediaBrowserTest : public ContentBrowserTest { public: // Common test results.
diff --git a/content/browser/media/webrtc_audio_debug_recordings_browsertest.cc b/content/browser/media/webrtc_audio_debug_recordings_browsertest.cc index d8ff0985..cc450f1 100644 --- a/content/browser/media/webrtc_audio_debug_recordings_browsertest.cc +++ b/content/browser/media/webrtc_audio_debug_recordings_browsertest.cc
@@ -98,7 +98,7 @@ return; } - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); // We must navigate somewhere first so that the render process is created. NavigateToURL(shell(), GURL("")); @@ -164,7 +164,7 @@ return; } - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); // We must navigate somewhere first so that the render process is created. NavigateToURL(shell(), GURL("")); @@ -211,7 +211,7 @@ return; } - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); // We must navigate somewhere first so that the render process is created. NavigateToURL(shell(), GURL(""));
diff --git a/content/browser/media/webrtc_browsertest.cc b/content/browser/media/webrtc_browsertest.cc index a00e510..9f05713 100644 --- a/content/browser/media/webrtc_browsertest.cc +++ b/content/browser/media/webrtc_browsertest.cc
@@ -46,7 +46,7 @@ // Convenience function since most peerconnection-call.html tests just load // the page, kick off some javascript and wait for the title to change to OK. void MakeTypicalPeerConnectionCall(const std::string& javascript) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html")); NavigateToURL(shell(), url);
diff --git a/content/browser/media/webrtc_getusermedia_browsertest.cc b/content/browser/media/webrtc_getusermedia_browsertest.cc index b2100c4..426ec4f 100644 --- a/content/browser/media/webrtc_getusermedia_browsertest.cc +++ b/content/browser/media/webrtc_getusermedia_browsertest.cc
@@ -121,7 +121,7 @@ void RunGetUserMediaAndCollectMeasures(const int time_to_sample_secs, const std::string& measure_filter, const std::string& graph_name) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); NavigateToURL(shell(), url); @@ -179,7 +179,7 @@ const std::string& constraints1, const std::string& constraints2, const std::string& expected_result) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); NavigateToURL(shell(), url); @@ -249,7 +249,7 @@ #endif IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, MAYBE_GetVideoStreamAndStop) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); NavigateToURL(shell(), url); @@ -268,7 +268,7 @@ #endif IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, MAYBE_RenderSameTrackMediastreamAndStop) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); NavigateToURL(shell(), url); @@ -280,7 +280,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, RenderClonedMediastreamAndStop) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); NavigateToURL(shell(), url); @@ -293,7 +293,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, kRenderClonedTrackMediastreamAndStop) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); NavigateToURL(shell(), url); @@ -305,7 +305,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, kRenderDuplicatedMediastreamAndStop) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); NavigateToURL(shell(), url); @@ -317,7 +317,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, GetAudioAndVideoStreamAndStop) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); NavigateToURL(shell(), url); @@ -328,7 +328,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, GetAudioAndVideoStreamAndClone) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); NavigateToURL(shell(), url); @@ -341,7 +341,7 @@ // Flaky everywhere else: http://crbug.com/523152 IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, RenderVideoTrackInMultipleTagsAndPause) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); NavigateToURL(shell(), url); @@ -351,7 +351,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, GetUserMediaWithMandatorySourceID) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); std::vector<std::string> audio_ids; std::vector<std::string> video_ids; @@ -376,7 +376,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, GetUserMediaWithInvalidMandatorySourceID) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); std::vector<std::string> audio_ids; std::vector<std::string> video_ids; @@ -409,7 +409,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, GetUserMediaWithInvalidOptionalSourceID) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); std::vector<std::string> audio_ids; std::vector<std::string> video_ids; @@ -442,7 +442,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, TwoGetUserMediaAndStop) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); NavigateToURL(shell(), url); @@ -521,7 +521,7 @@ #endif IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, MAYBE_TwoGetUserMediaAndVerifyFrameRate) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); NavigateToURL(shell(), url); @@ -540,7 +540,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, GetUserMediaWithTooHighVideoConstraintsValues) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); @@ -563,7 +563,7 @@ // verifies getUserMedia can succeed after being given impossible constraints. IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, TwoGetUserMediaAndCheckCallbackAfterFailure) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); NavigateToURL(shell(), url); @@ -611,7 +611,7 @@ // This test calls getUserMedia and checks for aspect ratio behavior. IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, MAYBE_TestGetUserMediaAspectRatio4To3) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); @@ -633,7 +633,7 @@ // This test calls getUserMedia and checks for aspect ratio behavior. IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, MAYBE_TestGetUserMediaAspectRatio16To9) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); @@ -655,7 +655,7 @@ // This test calls getUserMedia and checks for aspect ratio behavior. IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, MAYBE_TestGetUserMediaAspectRatio1To1) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); @@ -671,7 +671,7 @@ // in the scope of the success callback. IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, AudioInIFrameAndCloseInSuccessCb) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); NavigateToURL(shell(), url); @@ -683,7 +683,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, VideoInIFrameAndCloseInSuccessCb) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); NavigateToURL(shell(), url); @@ -697,7 +697,7 @@ // in the scope of the failure callback. IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, VideoWithBadConstraintsInIFrameAndCloseInFailureCb) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); @@ -717,7 +717,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, InvalidSourceIdInIFrameAndCloseInFailureCb) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); @@ -765,7 +765,7 @@ // This test calls getUserMedia in sequence with different constraints. IN_PROC_BROWSER_TEST_P(WebRtcConstraintsBrowserTest, MAYBE_GetUserMediaConstraints) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
diff --git a/content/browser/media/webrtc_internals_browsertest.cc b/content/browser/media/webrtc_internals_browsertest.cc index a44fbe0..a0742b3 100644 --- a/content/browser/media/webrtc_internals_browsertest.cc +++ b/content/browser/media/webrtc_internals_browsertest.cc
@@ -681,7 +681,7 @@ IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, DISABLED_WithRealPeerConnectionCall) { // Start a peerconnection call in the first window. - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html")); NavigateToURL(shell(), url); ASSERT_TRUE(ExecuteJavascript("call({video:true});"));
diff --git a/content/browser/media/webrtc_webcam_browsertest.cc b/content/browser/media/webrtc_webcam_browsertest.cc index 5a7849c..59889b3 100644 --- a/content/browser/media/webrtc_webcam_browsertest.cc +++ b/content/browser/media/webrtc_webcam_browsertest.cc
@@ -71,7 +71,7 @@ // want here since the bot runs tests sequentially on the device. IN_PROC_BROWSER_TEST_F(WebRtcWebcamBrowserTest, MANUAL_CanAcquireVgaOnRealWebcam) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL( "/media/getusermedia-real-webcam.html")); NavigateToURL(shell(), url);
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc index 437c5e52..102a560 100644 --- a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc +++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
@@ -117,8 +117,8 @@ // size to the root window. Returns after the navigation to the url is // complete. void StartTestWithPage(const std::string& url) { - ASSERT_TRUE(test_server()->Start()); - GURL test_url(test_server()->GetURL(url)); + ASSERT_TRUE(embedded_test_server()->Start()); + GURL test_url(embedded_test_server()->GetURL(url)); NavigateToURL(shell(), test_url); aura::Window* content = shell()->web_contents()->GetContentNativeView(); content->GetHost()->SetBounds(gfx::Rect(800, 600)); @@ -163,7 +163,7 @@ // menu properly. IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, BasicSelection) { // Set the test page up. - ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html")); + ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html")); WebContents* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents()); RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>( @@ -202,7 +202,7 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, BasicInsertionFollowedByTapsOnHandle) { // Set the test page up. - ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html")); + ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html")); WebContents* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents()); RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>( @@ -256,7 +256,7 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, QuickMenuHiddenOnTouch) { // Set the test page up. - ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html")); + ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html")); WebContents* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents()); RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>( @@ -319,7 +319,7 @@ // Tests that the quick menu and touch handles are hidden during an scroll. IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, HiddenOnScroll) { // Set the test page up. - ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html")); + ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html")); WebContents* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents()); RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>( @@ -398,7 +398,7 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, HiddenAfterOverscroll) { // Set the page up. - ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html")); + ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html")); WebContents* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents()); RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc index b1a312d..50f3a5f7 100644 --- a/content/browser/renderer_host/media/video_capture_controller.cc +++ b/content/browser/renderer_host/media/video_capture_controller.cc
@@ -41,13 +41,13 @@ name, \ (height) ? ((width) * 100) / (height) : kInfiniteRatio); -class SyncPointClientImpl : public VideoFrame::SyncPointClient { +class SyncTokenClientImpl : public VideoFrame::SyncTokenClient { public: - explicit SyncPointClientImpl(GLHelper* gl_helper) : gl_helper_(gl_helper) {} - ~SyncPointClientImpl() override {} + explicit SyncTokenClientImpl(GLHelper* gl_helper) : gl_helper_(gl_helper) {} + ~SyncTokenClientImpl() override {} uint32 InsertSyncPoint() override { return gl_helper_->InsertSyncPoint(); } - void WaitSyncPoint(uint32 sync_point) override { - gl_helper_->WaitSyncPoint(sync_point); + void WaitSyncToken(const gpu::SyncToken& sync_token) override { + gl_helper_->WaitSyncToken(sync_token); } private: @@ -55,18 +55,18 @@ }; void ReturnVideoFrame(const scoped_refptr<VideoFrame>& video_frame, - uint32 sync_point) { + const gpu::SyncToken& sync_token) { DCHECK_CURRENTLY_ON(BrowserThread::UI); #if defined(OS_ANDROID) NOTREACHED(); #else GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper(); - // UpdateReleaseSyncPoint() creates a new sync_point using |gl_helper|, so - // wait the given |sync_point| using |gl_helper|. + // UpdateReleaseSyncToken() creates a new sync_token using |gl_helper|, so + // wait the given |sync_token| using |gl_helper|. if (gl_helper) { - gl_helper->WaitSyncPoint(sync_point); - SyncPointClientImpl client(gl_helper); - video_frame->UpdateReleaseSyncPoint(&client); + gl_helper->WaitSyncToken(sync_token); + SyncTokenClientImpl client(gl_helper); + video_frame->UpdateReleaseSyncToken(&client); } #endif } @@ -101,7 +101,7 @@ // Buffers that are currently known to this client. std::set<int> known_buffers; - // Buffers currently held by this client, and syncpoint callback to call when + // Buffers currently held by this client, and sync token callback to call when // they are returned from the client. typedef std::map<int, scoped_refptr<VideoFrame>> ActiveBufferMap; ActiveBufferMap active_buffers; @@ -267,7 +267,7 @@ VideoCaptureControllerID id, VideoCaptureControllerEventHandler* event_handler, int buffer_id, - uint32 sync_point, + const gpu::SyncToken& sync_token, double consumer_resource_utilization) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -306,12 +306,11 @@ buffer_pool_->RelinquishConsumerHold(buffer_id, 1); #if defined(OS_ANDROID) - DCHECK_EQ(0u, sync_point); + DCHECK(!sync_token.HasData()); #endif - if (sync_point) - BrowserThread::PostTask(BrowserThread::UI, - FROM_HERE, - base::Bind(&ReturnVideoFrame, frame, sync_point)); + if (sync_token.HasData()) + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&ReturnVideoFrame, frame, sync_token)); } const media::VideoCaptureFormat&
diff --git a/content/browser/renderer_host/media/video_capture_controller.h b/content/browser/renderer_host/media/video_capture_controller.h index f1e5852..b51bd25 100644 --- a/content/browser/renderer_host/media/video_capture_controller.h +++ b/content/browser/renderer_host/media/video_capture_controller.h
@@ -114,7 +114,7 @@ void ReturnBuffer(VideoCaptureControllerID id, VideoCaptureControllerEventHandler* event_handler, int buffer_id, - uint32 sync_point, + const gpu::SyncToken& sync_token, double consumer_resource_utilization); const media::VideoCaptureFormat& GetVideoCaptureFormat() const;
diff --git a/content/browser/renderer_host/media/video_capture_controller_unittest.cc b/content/browser/renderer_host/media/video_capture_controller_unittest.cc index a030323..1d8facee 100644 --- a/content/browser/renderer_host/media/video_capture_controller_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_controller_unittest.cc
@@ -86,16 +86,17 @@ EXPECT_EQ(frame->format(), media::PIXEL_FORMAT_I420); DoI420BufferReady(id, frame->coded_size()); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&VideoCaptureController::ReturnBuffer, - base::Unretained(controller_), id, this, - buffer_id, 0, resource_utilization_)); + FROM_HERE, + base::Bind(&VideoCaptureController::ReturnBuffer, + base::Unretained(controller_), id, this, buffer_id, + gpu::SyncToken(), resource_utilization_)); } else { EXPECT_EQ(frame->format(), media::PIXEL_FORMAT_ARGB); DoTextureBufferReady(id, frame->coded_size()); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(&VideoCaptureController::ReturnBuffer, base::Unretained(controller_), id, this, - buffer_id, frame->mailbox_holder(0).sync_point, + buffer_id, frame->mailbox_holder(0).sync_token, resource_utilization_)); } } @@ -260,9 +261,9 @@ << "Client count should return to zero after all clients are gone."; } -static void CacheSyncPoint(uint32* called_release_sync_point, - uint32 release_sync_point) { - *called_release_sync_point = release_sync_point; +static void CacheSyncToken(gpu::SyncToken* called_release_sync_token, + const gpu::SyncToken& release_sync_token) { + *called_release_sync_token = release_sync_token; } // This test will connect and disconnect several clients while simulating an @@ -524,8 +525,8 @@ device_->OnIncomingCapturedVideoFrame(buffer.Pass(), video_frame, base::TimeTicks()); } - std::vector<uint32> mailbox_syncpoints(mailbox_buffers); - std::vector<uint32> release_syncpoints(mailbox_buffers); + std::vector<gpu::SyncToken> mailbox_synctokens(mailbox_buffers); + std::vector<gpu::SyncToken> release_synctokens(mailbox_buffers); for (int i = 0; i < mailbox_buffers; ++i) { scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer = device_->ReserveOutputBuffer(capture_resolution, @@ -533,14 +534,14 @@ media::PIXEL_STORAGE_TEXTURE); ASSERT_TRUE(buffer.get()); #if !defined(OS_ANDROID) - mailbox_syncpoints[i] = - ImageTransportFactory::GetInstance()->GetGLHelper()->InsertSyncPoint(); + mailbox_synctokens[i] = gpu::SyncToken( + ImageTransportFactory::GetInstance()->GetGLHelper()->InsertSyncPoint()); #endif device_->OnIncomingCapturedVideoFrame( buffer.Pass(), - WrapMailboxBuffer(gpu::MailboxHolder(gpu::Mailbox::Generate(), 0, - mailbox_syncpoints[i]), - base::Bind(&CacheSyncPoint, &release_syncpoints[i]), + WrapMailboxBuffer(gpu::MailboxHolder(gpu::Mailbox::Generate(), + mailbox_synctokens[i], 0), + base::Bind(&CacheSyncToken, &release_synctokens[i]), capture_resolution), base::TimeTicks()); } @@ -564,12 +565,12 @@ EXPECT_CALL(*client_b_, DoBufferDestroyed(client_b_route_2)); #endif base::RunLoop().RunUntilIdle(); - for (size_t i = 0; i < mailbox_syncpoints.size(); ++i) { + for (size_t i = 0; i < mailbox_synctokens.size(); ++i) { // A new release sync point must be inserted when the video frame is // returned to the Browser process. // See: MockVideoCaptureControllerEventHandler::OnMailboxBufferReady() and // VideoCaptureController::ReturnBuffer() - ASSERT_NE(mailbox_syncpoints[i], release_syncpoints[i]); + ASSERT_NE(mailbox_synctokens[i], release_synctokens[i]); } Mock::VerifyAndClearExpectations(client_b_.get());
diff --git a/content/browser/renderer_host/media/video_capture_host.cc b/content/browser/renderer_host/media/video_capture_host.cc index d624125..f07dfbc 100644 --- a/content/browser/renderer_host/media/video_capture_host.cc +++ b/content/browser/renderer_host/media/video_capture_host.cc
@@ -270,7 +270,7 @@ void VideoCaptureHost::OnRendererFinishedWithBuffer( int device_id, int buffer_id, - uint32 sync_point, + const gpu::SyncToken& sync_token, double consumer_resource_utilization) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -279,10 +279,7 @@ if (it != entries_.end()) { const base::WeakPtr<VideoCaptureController>& controller = it->second; if (controller) { - controller->ReturnBuffer(controller_id, - this, - buffer_id, - sync_point, + controller->ReturnBuffer(controller_id, this, buffer_id, sync_token, consumer_resource_utilization); } }
diff --git a/content/browser/renderer_host/media/video_capture_host.h b/content/browser/renderer_host/media/video_capture_host.h index f270912..b7bb275 100644 --- a/content/browser/renderer_host/media/video_capture_host.h +++ b/content/browser/renderer_host/media/video_capture_host.h
@@ -130,7 +130,7 @@ // the controller. void OnRendererFinishedWithBuffer(int device_id, int buffer_id, - uint32 sync_point, + const gpu::SyncToken& sync_token, double consumer_resource_utilization); // IPC message: Get supported formats referenced by |capture_session_id|.
diff --git a/content/browser/renderer_host/media/video_capture_host_unittest.cc b/content/browser/renderer_host/media/video_capture_host_unittest.cc index 70c6112..a26a9c30 100644 --- a/content/browser/renderer_host/media/video_capture_host_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_host_unittest.cc
@@ -151,7 +151,8 @@ void ReturnReceivedDibs(int device_id) { int handle = GetReceivedDib(); while (handle) { - this->OnRendererFinishedWithBuffer(device_id, handle, 0, -1.0); + this->OnRendererFinishedWithBuffer(device_id, handle, gpu::SyncToken(), + -1.0); handle = GetReceivedDib(); } } @@ -231,7 +232,7 @@ OnBufferFilled(params.device_id); if (return_buffers_) { VideoCaptureHost::OnRendererFinishedWithBuffer( - params.device_id, params.buffer_id, 0, -1.0); + params.device_id, params.buffer_id, gpu::SyncToken(), -1.0); } }
diff --git a/content/browser/renderer_host/render_message_filter_browsertest.cc b/content/browser/renderer_host/render_message_filter_browsertest.cc index 78194fb..3f05b5f 100644 --- a/content/browser/renderer_host/render_message_filter_browsertest.cc +++ b/content/browser/renderer_host/render_message_filter_browsertest.cc
@@ -21,7 +21,6 @@ #include "ipc/ipc_security_test_util.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" -#include "net/test/spawned_test_server/spawned_test_server.h" #include "testing/gtest/include/gtest/gtest.h" namespace content { @@ -43,17 +42,16 @@ // interacting with secure cookies. IN_PROC_BROWSER_TEST_F(RenderMessageFilterBrowserTest, Cookies) { host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); SetupCrossSiteRedirector(embedded_test_server()); - net::SpawnedTestServer https_server( - net::SpawnedTestServer::TYPE_HTTPS, net::SpawnedTestServer::kLocalhost, - base::FilePath(FILE_PATH_LITERAL("content/test/data"))); + net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_server.ServeFilesFromSourceDirectory("content/test/data"); ASSERT_TRUE(https_server.Start()); // The server sends a HttpOnly cookie. The RenderMessageFilter should never // allow this to be sent to any renderer process. - GURL https_url = https_server.GetURL("set-cookie?notforjs=1;HttpOnly"); + GURL https_url = https_server.GetURL("/set-cookie?notforjs=1;HttpOnly"); GURL http_url = embedded_test_server()->GetURL("/frame_with_load_event.html"); Shell* shell2 = CreateBrowser(); @@ -112,7 +110,7 @@ } host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); SetupCrossSiteRedirector(embedded_test_server()); NavigateToURL(shell(), embedded_test_server()->GetURL("/frame_with_load_event.html"));
diff --git a/content/browser/renderer_host/render_process_host_browsertest.cc b/content/browser/renderer_host/render_process_host_browsertest.cc index 1d5ed553..96a5803 100644 --- a/content/browser/renderer_host/render_process_host_browsertest.cc +++ b/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -62,7 +62,7 @@ // http://crbug.com/87176. IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, ShutdownRequestFromActiveTabIgnored) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL test_url = embedded_test_server()->GetURL("/simple_page.html"); NavigateToURL(shell(), test_url); @@ -90,7 +90,7 @@ // Set max renderers to 1 to force running out of processes. content::RenderProcessHost::SetMaxRendererProcessCount(1); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL test_url = embedded_test_server()->GetURL("/simple_page.html"); NavigateToURL(shell(), test_url); @@ -160,7 +160,7 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, AllProcessExitedCallsBeforeAnyHostDestroyedCalls) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL test_url = embedded_test_server()->GetURL("/simple_page.html"); NavigateToURL(shell(), test_url);
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index dee22d35..892da51c 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -36,6 +36,7 @@ #include "base/trace_event/trace_event.h" #include "base/tracked_objects.h" #include "cc/base/switches.h" +#include "components/scheduler/common/scheduler_switches.h" #include "components/tracing/tracing_switches.h" #include "content/browser/appcache/appcache_dispatcher_host.h" #include "content/browser/appcache/chrome_appcache_service.h" @@ -1197,6 +1198,11 @@ if (IsForceGpuRasterizationEnabled()) command_line->AppendSwitch(switches::kForceGpuRasterization); + if (IsGpuMemoryBufferCompositorResourcesEnabled()) { + command_line->AppendSwitch( + switches::kEnableGpuMemoryBufferCompositorResources); + } + // Persistent buffers may come at a performance hit (not all platform specific // buffers support it), so only enable them if partial raster is enabled and // we are actually going to use them. @@ -1427,6 +1433,8 @@ cc::switches::kTopControlsHideThreshold, cc::switches::kTopControlsShowThreshold, + scheduler::switches::kEnableVirtualizedTime, + #if defined(ENABLE_PLUGINS) switches::kEnablePepperTesting, #endif
diff --git a/content/browser/renderer_host/render_view_host_browsertest.cc b/content/browser/renderer_host/render_view_host_browsertest.cc index 2fdaf0aa..feb4957 100644 --- a/content/browser/renderer_host/render_view_host_browsertest.cc +++ b/content/browser/renderer_host/render_view_host_browsertest.cc
@@ -62,7 +62,7 @@ }; IN_PROC_BROWSER_TEST_F(RenderViewHostTest, FrameNavigateSocketAddress) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); RenderViewHostTestWebContentsObserver observer(shell()->web_contents()); GURL test_url = embedded_test_server()->GetURL("/simple_page.html"); @@ -75,7 +75,7 @@ } IN_PROC_BROWSER_TEST_F(RenderViewHostTest, BaseURLParam) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); RenderViewHostTestWebContentsObserver observer(shell()->web_contents()); // Base URL is not set if it is the same as the URL. @@ -96,7 +96,7 @@ // This test ensures a RenderFrameHost object is created for the top level frame // in each RenderViewHost. IN_PROC_BROWSER_TEST_F(RenderViewHostTest, BasicRenderFrameHost) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL test_url = embedded_test_server()->GetURL("/simple_page.html"); NavigateToURL(shell(), test_url); @@ -117,7 +117,7 @@ } IN_PROC_BROWSER_TEST_F(RenderViewHostTest, IsFocusedElementEditable) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL test_url = embedded_test_server()->GetURL("/touch_selection.html"); NavigateToURL(shell(), test_url); @@ -129,7 +129,7 @@ } IN_PROC_BROWSER_TEST_F(RenderViewHostTest, ReleaseSessionOnCloseACK) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL test_url = embedded_test_server()->GetURL( "/access-session-storage.html"); NavigateToURL(shell(), test_url);
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 5f3afe1f9..9a7611b 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -224,7 +224,6 @@ waiting_for_drag_context_response_(false), enabled_bindings_(0), page_id_(-1), - nav_entry_id_(0), is_active_(!swapped_out), is_pending_deletion_(false), is_swapped_out_(swapped_out),
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h index ecdfc3cb..3c1ea4b8 100644 --- a/content/browser/renderer_host/render_view_host_impl.h +++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -326,11 +326,6 @@ // currently using it. int ref_count() { return frames_ref_count_; } - // TODO(avi): Move to RenderFrameHost once PageState is broken up into - // FrameStates. - int nav_entry_id() const { return nav_entry_id_; } - void set_nav_entry_id(int nav_entry_id) { nav_entry_id_ = nav_entry_id; } - // NOTE: Do not add functions that just send an IPC message that are called in // one or two places. Have the caller send the IPC message directly (unless // the caller places are in different platforms, in which case it's better @@ -439,11 +434,6 @@ // TODO(creis): Allocate this in WebContents/NavigationController instead. int32 page_id_; - // The unique ID of the latest NavigationEntry that this RenderViewHost is - // showing. TODO(avi): Move to RenderFrameHost once PageState is broken up - // into FrameStates. - int nav_entry_id_; - // Tracks whether this RenderViewHost is in an active state. False if the // main frame is pending swap out, pending deletion, or swapped out, because // it is not visible to the user in any of these cases.
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index cc7def858..0a9f05f 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -1551,7 +1551,7 @@ cc::CompositorFrameAck ack; if (frame->gl_frame_data) { ack.gl_frame_data = frame->gl_frame_data.Pass(); - ack.gl_frame_data->sync_point = 0; + ack.gl_frame_data->sync_token.Clear(); } else if (frame->delegated_frame_data) { cc::TransferableResource::ReturnResources( frame->delegated_frame_data->resource_list,
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index 9b5eb52..968c1bd 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -243,14 +243,14 @@ TRACE_EVENT0( "cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceFinished"); bitmap_pixels_lock.reset(); - uint32 sync_point = 0; + gpu::SyncToken sync_token; if (result) { GLHelper* gl_helper = GetPostReadbackGLHelper(); if (gl_helper) - sync_point = gl_helper->InsertSyncPoint(); + sync_token = gpu::SyncToken(gl_helper->InsertSyncPoint()); } - bool lost_resource = sync_point == 0; - release_callback->Run(sync_point, lost_resource); + const bool lost_resource = !sync_token.HasData(); + release_callback->Run(sync_token, lost_resource); UMA_HISTOGRAM_TIMES(kAsyncReadBackString, base::TimeTicks::Now() - start_time); ReadbackResponse response = result ? READBACK_SUCCESS : READBACK_FAILED; @@ -1988,19 +1988,11 @@ ignore_result(scoped_callback_runner.Release()); gl_helper->CropScaleReadbackAndCleanMailbox( - texture_mailbox.mailbox(), - texture_mailbox.sync_point(), - result->size(), - gfx::Rect(result->size()), - output_size_in_pixel, - pixels, - color_type, - base::Bind(&CopyFromCompositingSurfaceFinished, - callback, - base::Passed(&release_callback), - base::Passed(&bitmap), - start_time, - base::Passed(&bitmap_pixels_lock)), + texture_mailbox.mailbox(), texture_mailbox.sync_token(), result->size(), + gfx::Rect(result->size()), output_size_in_pixel, pixels, color_type, + base::Bind(&CopyFromCompositingSurfaceFinished, callback, + base::Passed(&release_callback), base::Passed(&bitmap), + start_time, base::Passed(&bitmap_pixels_lock)), GLHelper::SCALER_QUALITY_GOOD); }
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index 61a42bb..b8c6132 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -279,7 +279,7 @@ GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper(); GLuint texture = gl_helper->ConsumeMailboxToTexture( last_copy_request_->texture_mailbox().mailbox(), - last_copy_request_->texture_mailbox().sync_point()); + last_copy_request_->texture_mailbox().sync_token()); gl_helper->ResizeTexture(texture, window()->bounds().size()); gl_helper->DeleteTexture(texture); }
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc index 1358af2..dcf51ef6 100644 --- a/content/browser/security_exploit_browsertest.cc +++ b/content/browser/security_exploit_browsertest.cc
@@ -130,7 +130,7 @@ SecurityExploitBrowserTest() {} void SetUpCommandLine(base::CommandLine* command_line) override { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); // Add a host resolver rule to map all outgoing requests to the test server. // This allows us to use "real" hostnames in URLs, which we can use to
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc index 1619dd2..0b0cb59 100644 --- a/content/browser/service_worker/service_worker_browsertest.cc +++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -306,7 +306,7 @@ } void SetUpOnMainThread() override { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); StoragePartition* partition = BrowserContext::GetDefaultStoragePartition( shell()->web_contents()->GetBrowserContext()); wrapper_ = static_cast<ServiceWorkerContextWrapper*>( @@ -985,13 +985,10 @@ #endif IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, MAYBE_ResponseFromHTTPSServiceWorkerIsMarkedAsSecure) { - const char kPageUrl[] = "files/service_worker/fetch_event_blob.html"; - const char kWorkerUrl[] = "files/service_worker/fetch_event_blob.js"; - net::SpawnedTestServer https_server( - net::SpawnedTestServer::TYPE_HTTPS, - net::BaseTestServer::SSLOptions( - net::BaseTestServer::SSLOptions::CERT_OK), - base::FilePath(FILE_PATH_LITERAL("content/test/data/"))); + const char kPageUrl[] = "/service_worker/fetch_event_blob.html"; + const char kWorkerUrl[] = "/service_worker/fetch_event_blob.js"; + net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_server.ServeFilesFromSourceDirectory("content/test/data"); ASSERT_TRUE(https_server.Start()); scoped_refptr<WorkerActivatedObserver> observer =
diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc index ec97d014..503f27de 100644 --- a/content/browser/service_worker/service_worker_context_core.cc +++ b/content/browser/service_worker/service_worker_context_core.cc
@@ -23,6 +23,7 @@ #include "content/browser/service_worker/service_worker_register_job.h" #include "content/browser/service_worker/service_worker_registration.h" #include "content/browser/service_worker/service_worker_storage.h" +#include "content/common/service_worker/service_worker_utils.h" #include "content/public/browser/browser_thread.h" #include "ipc/ipc_message.h" #include "net/http/http_response_headers.h" @@ -668,6 +669,16 @@ AsWeakPtr())); } +void ServiceWorkerContextCore::CheckHasServiceWorker( + const GURL& url, + const GURL& other_url, + const ServiceWorkerContext::CheckHasServiceWorkerCallback callback) { + storage()->FindRegistrationForDocument( + url, base::Bind(&ServiceWorkerContextCore:: + DidFindRegistrationForCheckHasServiceWorker, + AsWeakPtr(), other_url, callback)); +} + void ServiceWorkerContextCore::OnRunningStateChanged( ServiceWorkerVersion* version) { if (!observer_list_) @@ -759,4 +770,42 @@ return wrapper_->process_manager(); } +void ServiceWorkerContextCore::DidFindRegistrationForCheckHasServiceWorker( + const GURL& other_url, + const ServiceWorkerContext::CheckHasServiceWorkerCallback callback, + ServiceWorkerStatusCode status, + const scoped_refptr<ServiceWorkerRegistration>& registration) { + if (status != SERVICE_WORKER_OK) { + callback.Run(false); + return; + } + + if (!ServiceWorkerUtils::ScopeMatches(registration->pattern(), other_url)) { + callback.Run(false); + return; + } + + if (registration->is_uninstalling() || registration->is_uninstalled()) { + callback.Run(false); + return; + } + + if (!registration->active_version() && !registration->waiting_version()) { + registration->RegisterRegistrationFinishedCallback( + base::Bind(&ServiceWorkerContextCore:: + OnRegistrationFinishedForCheckHasServiceWorker, + AsWeakPtr(), callback, registration)); + return; + } + + callback.Run(true); +} + +void ServiceWorkerContextCore::OnRegistrationFinishedForCheckHasServiceWorker( + const ServiceWorkerContext::CheckHasServiceWorkerCallback callback, + const scoped_refptr<ServiceWorkerRegistration>& registration) { + callback.Run(registration->active_version() || + registration->waiting_version()); +} + } // namespace content
diff --git a/content/browser/service_worker/service_worker_context_core.h b/content/browser/service_worker/service_worker_context_core.h index 6f44c73..f822e475 100644 --- a/content/browser/service_worker/service_worker_context_core.h +++ b/content/browser/service_worker/service_worker_context_core.h
@@ -20,6 +20,7 @@ #include "content/browser/service_worker/service_worker_registration_status.h" #include "content/browser/service_worker/service_worker_storage.h" #include "content/common/content_export.h" +#include "content/public/browser/service_worker_context.h" class GURL; @@ -262,6 +263,14 @@ void ClearAllServiceWorkersForTest(const base::Closure& callback); + // Determines if there is a ServiceWorker registration that matches |url|, and + // if |other_url| falls inside the scope of the same registration. See + // ServiceWorkerContext::CheckHasServiceWorker for more details. + void CheckHasServiceWorker( + const GURL& url, + const GURL& other_url, + const ServiceWorkerContext::CheckHasServiceWorkerCallback callback); + base::WeakPtr<ServiceWorkerContextCore> AsWeakPtr() { return weak_factory_.GetWeakPtr(); } @@ -295,6 +304,15 @@ const GURL& origin, const std::vector<ServiceWorkerRegistrationInfo>& registrations); + void DidFindRegistrationForCheckHasServiceWorker( + const GURL& other_url, + const ServiceWorkerContext::CheckHasServiceWorkerCallback callback, + ServiceWorkerStatusCode status, + const scoped_refptr<ServiceWorkerRegistration>& registration); + void OnRegistrationFinishedForCheckHasServiceWorker( + const ServiceWorkerContext::CheckHasServiceWorkerCallback callback, + const scoped_refptr<ServiceWorkerRegistration>& registration); + // It's safe to store a raw pointer instead of a scoped_refptr to |wrapper_| // because the Wrapper::Shutdown call that hops threads to destroy |this| uses // Bind() to hold a reference to |wrapper_| until |this| is fully destroyed.
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc index f6785c92..aaa37584 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.cc +++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -332,25 +332,13 @@ callback.Run(usage_infos); } -void ServiceWorkerContextWrapper::DidFindRegistrationForCheckHasServiceWorker( - const GURL& other_url, +void ServiceWorkerContextWrapper::DidCheckHasServiceWorker( const CheckHasServiceWorkerCallback& callback, - ServiceWorkerStatusCode status, - const scoped_refptr<ServiceWorkerRegistration>& registration) { + bool has_service_worker) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (status != SERVICE_WORKER_OK) { - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(callback, false)); - return; - } - - DCHECK(registration); - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(callback, registration->active_version() && - ServiceWorkerUtils::ScopeMatches( - registration->pattern(), other_url))); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(callback, has_service_worker)); } void ServiceWorkerContextWrapper::StopAllServiceWorkersForOrigin( @@ -439,11 +427,10 @@ base::Bind(callback, false)); return; } - context()->storage()->FindRegistrationForDocument( - net::SimplifyUrlForRequest(url), - base::Bind(&ServiceWorkerContextWrapper:: - DidFindRegistrationForCheckHasServiceWorker, - this, net::SimplifyUrlForRequest(other_url), callback)); + context()->CheckHasServiceWorker( + net::SimplifyUrlForRequest(url), net::SimplifyUrlForRequest(other_url), + base::Bind(&ServiceWorkerContextWrapper::DidCheckHasServiceWorker, this, + callback)); } void ServiceWorkerContextWrapper::ClearAllServiceWorkersForTest(
diff --git a/content/browser/service_worker/service_worker_context_wrapper.h b/content/browser/service_worker/service_worker_context_wrapper.h index a4d1e13b..37a8d24 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.h +++ b/content/browser/service_worker/service_worker_context_wrapper.h
@@ -185,11 +185,8 @@ const GetUsageInfoCallback& callback, const std::vector<ServiceWorkerRegistrationInfo>& registrations); - void DidFindRegistrationForCheckHasServiceWorker( - const GURL& other_url, - const CheckHasServiceWorkerCallback& callback, - ServiceWorkerStatusCode status, - const scoped_refptr<ServiceWorkerRegistration>& registration); + void DidCheckHasServiceWorker(const CheckHasServiceWorkerCallback& callback, + bool has_service_worker); void DidFindRegistrationForUpdate( ServiceWorkerStatusCode status,
diff --git a/content/browser/service_worker/service_worker_registration.cc b/content/browser/service_worker/service_worker_registration.cc index 039afa7..7517b51 100644 --- a/content/browser/service_worker/service_worker_registration.cc +++ b/content/browser/service_worker/service_worker_registration.cc
@@ -69,12 +69,21 @@ void ServiceWorkerRegistration::NotifyRegistrationFailed() { FOR_EACH_OBSERVER(Listener, listeners_, OnRegistrationFailed(this)); + NotifyRegistrationFinished(); } void ServiceWorkerRegistration::NotifyUpdateFound() { FOR_EACH_OBSERVER(Listener, listeners_, OnUpdateFound(this)); } +void ServiceWorkerRegistration::NotifyVersionAttributesChanged( + ChangedVersionAttributesMask mask) { + FOR_EACH_OBSERVER(Listener, listeners_, + OnVersionAttributesChanged(this, mask, GetInfo())); + if (mask.active_changed() || mask.waiting_changed()) + NotifyRegistrationFinished(); +} + ServiceWorkerRegistrationInfo ServiceWorkerRegistration::GetInfo() { DCHECK_CURRENTLY_ON(BrowserThread::IO); return ServiceWorkerRegistrationInfo( @@ -104,8 +113,7 @@ active_version_->AddListener(this); mask.add(ChangedVersionAttributesMask::ACTIVE_VERSION); - FOR_EACH_OBSERVER(Listener, listeners_, - OnVersionAttributesChanged(this, mask, GetInfo())); + NotifyVersionAttributesChanged(mask); } void ServiceWorkerRegistration::SetWaitingVersion( @@ -120,8 +128,7 @@ waiting_version_ = version; mask.add(ChangedVersionAttributesMask::WAITING_VERSION); - FOR_EACH_OBSERVER(Listener, listeners_, - OnVersionAttributesChanged(this, mask, GetInfo())); + NotifyVersionAttributesChanged(mask); } void ServiceWorkerRegistration::SetInstallingVersion( @@ -135,8 +142,7 @@ installing_version_ = version; mask.add(ChangedVersionAttributesMask::INSTALLING_VERSION); - FOR_EACH_OBSERVER(Listener, listeners_, - OnVersionAttributesChanged(this, mask, GetInfo())); + NotifyVersionAttributesChanged(mask); } void ServiceWorkerRegistration::UnsetVersion(ServiceWorkerVersion* version) { @@ -144,11 +150,8 @@ return; ChangedVersionAttributesMask mask; UnsetVersionInternal(version, &mask); - if (mask.changed()) { - ServiceWorkerRegistrationInfo info = GetInfo(); - FOR_EACH_OBSERVER(Listener, listeners_, - OnVersionAttributesChanged(this, mask, info)); - } + if (mask.changed()) + NotifyVersionAttributesChanged(mask); } void ServiceWorkerRegistration::UnsetVersionInternal( @@ -336,11 +339,26 @@ is_deleted_ = false; } else { is_uninstalled_ = true; - FOR_EACH_OBSERVER(Listener, listeners_, OnRegistrationFailed(this)); + NotifyRegistrationFailed(); } } } +void ServiceWorkerRegistration::NotifyRegistrationFinished() { + std::vector<base::Closure> callbacks; + callbacks.swap(registration_finished_callbacks_); + for (const auto& callback : callbacks) + callback.Run(); +} + +void ServiceWorkerRegistration::RegisterRegistrationFinishedCallback( + const base::Closure& callback) { + // This should only be called if the registration is in progress. + DCHECK(!active_version() && !waiting_version() && !is_uninstalled() && + !is_uninstalling()); + registration_finished_callbacks_.push_back(callback); +} + void ServiceWorkerRegistration::OnActivateEventFinished( ServiceWorkerVersion* activating_version, ServiceWorkerStatusCode status) { @@ -388,11 +406,8 @@ active_version_ = NULL; mask.add(ChangedVersionAttributesMask::ACTIVE_VERSION); } - if (mask.changed()) { - ServiceWorkerRegistrationInfo info = GetInfo(); - FOR_EACH_OBSERVER(Listener, listeners_, - OnVersionAttributesChanged(this, mask, info)); - } + if (mask.changed()) + NotifyVersionAttributesChanged(mask); FOR_EACH_OBSERVER( Listener, listeners_, OnRegistrationFinishedUninstalling(this));
diff --git a/content/browser/service_worker/service_worker_registration.h b/content/browser/service_worker/service_worker_registration.h index 4a37e55..8a8cbec 100644 --- a/content/browser/service_worker/service_worker_registration.h +++ b/content/browser/service_worker/service_worker_registration.h
@@ -90,6 +90,7 @@ void RemoveListener(Listener* listener); void NotifyRegistrationFailed(); void NotifyUpdateFound(); + void NotifyVersionAttributesChanged(ChangedVersionAttributesMask mask); ServiceWorkerRegistrationInfo GetInfo(); @@ -143,6 +144,9 @@ // registration from storage if there is no longer a stored version. void DeleteVersion(const scoped_refptr<ServiceWorkerVersion>& version); + void RegisterRegistrationFinishedCallback(const base::Closure& callback); + void NotifyRegistrationFinished(); + bool force_update_on_page_load() const { return force_update_on_page_load_; } void set_force_update_on_page_load(bool force_update_on_page_load) { force_update_on_page_load_ = force_update_on_page_load; @@ -190,6 +194,7 @@ scoped_refptr<ServiceWorkerVersion> installing_version_; base::ObserverList<Listener> listeners_; + std::vector<base::Closure> registration_finished_callbacks_; base::WeakPtr<ServiceWorkerContextCore> context_; DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegistration);
diff --git a/content/browser/session_history_browsertest.cc b/content/browser/session_history_browsertest.cc index f2d2e04..8a04f7e 100644 --- a/content/browser/session_history_browsertest.cc +++ b/content/browser/session_history_browsertest.cc
@@ -49,7 +49,7 @@ SessionHistoryTest() {} void SetUpOnMainThread() override { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); embedded_test_server()->RegisterRequestHandler( base::Bind(&HandleEchoTitleRequest, "/echotitle"));
diff --git a/content/browser/shared_worker/worker_browsertest.cc b/content/browser/shared_worker/worker_browsertest.cc index 0a9c34c..c88be69 100644 --- a/content/browser/shared_worker/worker_browsertest.cc +++ b/content/browser/shared_worker/worker_browsertest.cc
@@ -22,6 +22,8 @@ #include "content/shell/browser/shell_resource_dispatcher_host_delegate.h" #include "net/base/escape.h" #include "net/base/test_data_directory.h" +#include "net/ssl/ssl_server_config.h" +#include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/spawned_test_server/spawned_test_server.h" #include "url/gurl.h" @@ -141,8 +143,8 @@ // Make sure that auth dialog is displayed from worker context. // http://crbug.com/33344 IN_PROC_BROWSER_TEST_F(WorkerTest, WorkerHttpAuth) { - ASSERT_TRUE(test_server()->Start()); - GURL url = test_server()->GetURL("files/workers/worker_auth.html"); + ASSERT_TRUE(embedded_test_server()->Start()); + GURL url = embedded_test_server()->GetURL("/workers/worker_auth.html"); NavigateAndWaitForAuth(url); } @@ -158,24 +160,24 @@ if (!SupportsSharedWorker()) return; - ASSERT_TRUE(test_server()->Start()); - GURL url = test_server()->GetURL("files/workers/shared_worker_auth.html"); + ASSERT_TRUE(embedded_test_server()->Start()); + GURL url = embedded_test_server()->GetURL("/workers/shared_worker_auth.html"); NavigateAndWaitForAuth(url); } // Tests that TLS client auth prompts for normal workers. IN_PROC_BROWSER_TEST_F(WorkerTest, WorkerTlsClientAuth) { // Launch HTTPS server. - net::SpawnedTestServer::SSLOptions ssl_options; - ssl_options.request_client_certificate = true; - net::SpawnedTestServer https_server( - net::SpawnedTestServer::TYPE_HTTPS, ssl_options, - base::FilePath(FILE_PATH_LITERAL("content/test/data"))); + net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_server.ServeFilesFromSourceDirectory("content/test/data"); + net::SSLServerConfig ssl_config; + ssl_config.require_client_cert = true; + https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config); ASSERT_TRUE(https_server.Start()); RunTest("worker_tls_client_auth.html", - "url=" + - net::EscapeQueryParamValue(https_server.GetURL("").spec(), true)); + "url=" + net::EscapeQueryParamValue(https_server.GetURL("/").spec(), + true)); EXPECT_EQ(1, select_certificate_count()); } @@ -186,16 +188,16 @@ return; // Launch HTTPS server. - net::SpawnedTestServer::SSLOptions ssl_options; - ssl_options.request_client_certificate = true; - net::SpawnedTestServer https_server( - net::SpawnedTestServer::TYPE_HTTPS, ssl_options, - base::FilePath(FILE_PATH_LITERAL("content/test/data"))); + net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_server.ServeFilesFromSourceDirectory("content/test/data"); + net::SSLServerConfig ssl_config; + ssl_config.require_client_cert = true; + https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config); ASSERT_TRUE(https_server.Start()); RunTest("worker_tls_client_auth.html", - "shared=true&url=" + - net::EscapeQueryParamValue(https_server.GetURL("").spec(), true)); + "shared=true&url=" + net::EscapeQueryParamValue( + https_server.GetURL("/").spec(), true)); EXPECT_EQ(0, select_certificate_count()); }
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index 395a4a0..239d40e 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -313,7 +313,7 @@ void SitePerProcessBrowserTest::SetUpOnMainThread() { host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); SetupCrossSiteRedirector(embedded_test_server()); } @@ -1494,20 +1494,15 @@ // TODO(nasko): Disable this test until out-of-process iframes is ready and the // security checks are back in place. -// TODO(creis): Replace SpawnedTestServer with host_resolver to get test to run -// on Android (http://crbug.com/187570). IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DISABLED_CrossSiteIframeRedirectOnce) { - ASSERT_TRUE(test_server()->Start()); - net::SpawnedTestServer https_server( - net::SpawnedTestServer::TYPE_HTTPS, - net::SpawnedTestServer::kLocalhost, - base::FilePath(FILE_PATH_LITERAL("content/test/data"))); + net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_server.ServeFilesFromSourceDirectory("content/test/data"); ASSERT_TRUE(https_server.Start()); - GURL main_url(test_server()->GetURL("files/site_per_process_main.html")); - GURL http_url(test_server()->GetURL("files/title1.html")); - GURL https_url(https_server.GetURL("files/title1.html")); + GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); + GURL http_url(embedded_test_server()->GetURL("/title1.html")); + GURL https_url(https_server.GetURL("/title1.html")); NavigateToURL(shell(), main_url); @@ -1515,8 +1510,8 @@ { // Load cross-site client-redirect page into Iframe. // Should be blocked. - GURL client_redirect_https_url(https_server.GetURL( - "client-redirect?files/title1.html")); + GURL client_redirect_https_url( + https_server.GetURL("/client-redirect?/title1.html")); EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test", client_redirect_https_url)); // DidFailProvisionalLoad when navigating to client_redirect_https_url. @@ -1527,8 +1522,8 @@ { // Load cross-site server-redirect page into Iframe, // which redirects to same-site page. - GURL server_redirect_http_url(https_server.GetURL( - "server-redirect?" + http_url.spec())); + GURL server_redirect_http_url( + https_server.GetURL("/server-redirect?" + http_url.spec())); EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test", server_redirect_http_url)); EXPECT_EQ(observer.last_navigation_url(), http_url); @@ -1538,8 +1533,8 @@ { // Load cross-site server-redirect page into Iframe, // which redirects to cross-site page. - GURL server_redirect_http_url(https_server.GetURL( - "server-redirect?files/title1.html")); + GURL server_redirect_http_url( + https_server.GetURL("/server-redirect?/title1.html")); EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test", server_redirect_http_url)); // DidFailProvisionalLoad when navigating to https_url. @@ -1550,8 +1545,8 @@ { // Load same-site server-redirect page into Iframe, // which redirects to cross-site page. - GURL server_redirect_http_url(test_server()->GetURL( - "server-redirect?" + https_url.spec())); + GURL server_redirect_http_url( + embedded_test_server()->GetURL("/server-redirect?" + https_url.spec())); EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test", server_redirect_http_url)); @@ -1562,8 +1557,8 @@ { // Load same-site client-redirect page into Iframe, // which redirects to cross-site page. - GURL client_redirect_http_url(test_server()->GetURL( - "client-redirect?" + https_url.spec())); + GURL client_redirect_http_url( + embedded_test_server()->GetURL("/client-redirect?" + https_url.spec())); RedirectNotificationObserver load_observer2( NOTIFICATION_LOAD_STOP, @@ -1586,8 +1581,8 @@ { // Load same-site server-redirect page into Iframe, // which redirects to same-site page. - GURL server_redirect_http_url(test_server()->GetURL( - "server-redirect?files/title1.html")); + GURL server_redirect_http_url( + embedded_test_server()->GetURL("/server-redirect?/title1.html")); EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test", server_redirect_http_url)); EXPECT_EQ(observer.last_navigation_url(), http_url); @@ -1597,8 +1592,8 @@ { // Load same-site client-redirect page into Iframe, // which redirects to same-site page. - GURL client_redirect_http_url(test_server()->GetURL( - "client-redirect?" + http_url.spec())); + GURL client_redirect_http_url( + embedded_test_server()->GetURL("/client-redirect?" + http_url.spec())); RedirectNotificationObserver load_observer2( NOTIFICATION_LOAD_STOP, Source<NavigationController>( @@ -1620,20 +1615,15 @@ // TODO(nasko): Disable this test until out-of-process iframes is ready and the // security checks are back in place. -// TODO(creis): Replace SpawnedTestServer with host_resolver to get test to run -// on Android (http://crbug.com/187570). IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DISABLED_CrossSiteIframeRedirectTwice) { - ASSERT_TRUE(test_server()->Start()); - net::SpawnedTestServer https_server( - net::SpawnedTestServer::TYPE_HTTPS, - net::SpawnedTestServer::kLocalhost, - base::FilePath(FILE_PATH_LITERAL("content/test/data"))); + net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_server.ServeFilesFromSourceDirectory("content/test/data"); ASSERT_TRUE(https_server.Start()); - GURL main_url(test_server()->GetURL("files/site_per_process_main.html")); - GURL http_url(test_server()->GetURL("files/title1.html")); - GURL https_url(https_server.GetURL("files/title1.html")); + GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); + GURL http_url(embedded_test_server()->GetURL("/title1.html")); + GURL https_url(https_server.GetURL("/title1.html")); NavigateToURL(shell(), main_url); @@ -1641,10 +1631,10 @@ { // Load client-redirect page pointing to a cross-site client-redirect page, // which eventually redirects back to same-site page. - GURL client_redirect_https_url(https_server.GetURL( - "client-redirect?" + http_url.spec())); - GURL client_redirect_http_url(test_server()->GetURL( - "client-redirect?" + client_redirect_https_url.spec())); + GURL client_redirect_https_url( + https_server.GetURL("/client-redirect?" + http_url.spec())); + GURL client_redirect_http_url(embedded_test_server()->GetURL( + "/client-redirect?" + client_redirect_https_url.spec())); // We should wait until second client redirect get cancelled. RedirectNotificationObserver load_observer2( @@ -1664,10 +1654,10 @@ { // Load server-redirect page pointing to a cross-site server-redirect page, // which eventually redirect back to same-site page. - GURL server_redirect_https_url(https_server.GetURL( - "server-redirect?" + http_url.spec())); - GURL server_redirect_http_url(test_server()->GetURL( - "server-redirect?" + server_redirect_https_url.spec())); + GURL server_redirect_https_url( + https_server.GetURL("/server-redirect?" + http_url.spec())); + GURL server_redirect_http_url(embedded_test_server()->GetURL( + "/server-redirect?" + server_redirect_https_url.spec())); EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test", server_redirect_http_url)); EXPECT_EQ(observer.last_navigation_url(), http_url); @@ -1677,10 +1667,10 @@ { // Load server-redirect page pointing to a cross-site server-redirect page, // which eventually redirects back to cross-site page. - GURL server_redirect_https_url(https_server.GetURL( - "server-redirect?" + https_url.spec())); - GURL server_redirect_http_url(test_server()->GetURL( - "server-redirect?" + server_redirect_https_url.spec())); + GURL server_redirect_https_url( + https_server.GetURL("/server-redirect?" + https_url.spec())); + GURL server_redirect_http_url(embedded_test_server()->GetURL( + "/server-redirect?" + server_redirect_https_url.spec())); EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test", server_redirect_http_url)); @@ -1692,10 +1682,10 @@ { // Load server-redirect page pointing to a cross-site client-redirect page, // which eventually redirects back to same-site page. - GURL client_redirect_http_url(https_server.GetURL( - "client-redirect?" + http_url.spec())); - GURL server_redirect_http_url(test_server()->GetURL( - "server-redirect?" + client_redirect_http_url.spec())); + GURL client_redirect_http_url( + https_server.GetURL("/client-redirect?" + http_url.spec())); + GURL server_redirect_http_url(embedded_test_server()->GetURL( + "/server-redirect?" + client_redirect_http_url.spec())); EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test", server_redirect_http_url));
diff --git a/content/browser/web_contents/opened_by_dom_browsertest.cc b/content/browser/web_contents/opened_by_dom_browsertest.cc index efca34f..afc78511 100644 --- a/content/browser/web_contents/opened_by_dom_browsertest.cc +++ b/content/browser/web_contents/opened_by_dom_browsertest.cc
@@ -82,12 +82,12 @@ // Tests that window.close() does not work on a normal window that has navigated // a few times. IN_PROC_BROWSER_TEST_F(OpenedByDOMTest, NormalWindow) { - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(embedded_test_server()->Start()); // window.close is allowed if the window was opened by DOM OR the back/forward // list has only one element. Navigate a bit so the second condition is false. - GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1"); - GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2"); + GURL url1 = embedded_test_server()->GetURL("/site_isolation/blank.html?1"); + GURL url2 = embedded_test_server()->GetURL("/site_isolation/blank.html?2"); NavigateToURL(shell(), url1); NavigateToURL(shell(), url2); @@ -99,11 +99,11 @@ // Tests that window.close() works in a popup window that has navigated a few // times. IN_PROC_BROWSER_TEST_F(OpenedByDOMTest, Popup) { - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(embedded_test_server()->Start()); - GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1"); - GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2"); - GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3"); + GURL url1 = embedded_test_server()->GetURL("/site_isolation/blank.html?1"); + GURL url2 = embedded_test_server()->GetURL("/site_isolation/blank.html?2"); + GURL url3 = embedded_test_server()->GetURL("/site_isolation/blank.html?3"); NavigateToURL(shell(), url1); Shell* popup = OpenWindowFromJavaScript(shell(), url2); @@ -115,16 +115,16 @@ // times and swapped processes. IN_PROC_BROWSER_TEST_F(OpenedByDOMTest, CrossProcessPopup) { host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(embedded_test_server()->Start()); - GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1"); + GURL url1 = embedded_test_server()->GetURL("/site_isolation/blank.html?1"); - GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2"); + GURL url2 = embedded_test_server()->GetURL("/site_isolation/blank.html?2"); GURL::Replacements replace_host; replace_host.SetHostStr("foo.com"); url2 = url2.ReplaceComponents(replace_host); - GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3"); + GURL url3 = embedded_test_server()->GetURL("/site_isolation/blank.html?3"); url3 = url3.ReplaceComponents(replace_host); NavigateToURL(shell(), url1);
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index fdf40d3..ea91c32 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -3890,7 +3890,7 @@ return; NavigationEntryImpl* new_entry = controller_.GetEntryWithUniqueID( - rvhi->nav_entry_id()); + static_cast<RenderFrameHostImpl*>(rvhi->GetMainFrame())->nav_entry_id()); if (SiteIsolationPolicy::UseSubframeNavigationEntries()) { // TODO(creis): We can't properly update state for cross-process subframes @@ -4074,10 +4074,8 @@ NavigationEntryImpl* entry = controller_.GetEntryWithPageID( render_frame_host->GetSiteInstance(), page_id); - RenderViewHostImpl* rvhi = - static_cast<RenderViewHostImpl*>(render_frame_host->GetRenderViewHost()); NavigationEntryImpl* new_entry = controller_.GetEntryWithUniqueID( - rvhi->nav_entry_id()); + static_cast<RenderFrameHostImpl*>(render_frame_host)->nav_entry_id()); DCHECK_EQ(entry, new_entry); // We can handle title updates when we don't have an entry in
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc index aa975789..7a05171 100644 --- a/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -196,7 +196,7 @@ // Test that DidStopLoading includes the correct URL in the details. IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, MAYBE_DidStopLoadingDetails) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); LoadStopNotificationObserver load_observer( &shell()->web_contents()->GetController()); @@ -221,7 +221,7 @@ // pending entry is present. IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, MAYBE_DidStopLoadingDetailsWithPending) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url("data:text/html,<div>test</div>"); // Listen for the first load to stop. @@ -247,7 +247,7 @@ // See http://crbug.com/280512. IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, ClearNonVisiblePendingOnFail) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")); @@ -279,12 +279,10 @@ // WebContentsDelegate::GetSizeForNewRenderView(). IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, MAYBE_GetSizeForNewRenderView) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); // Create a new server with a different site. - net::SpawnedTestServer https_server( - net::SpawnedTestServer::TYPE_HTTPS, - net::SpawnedTestServer::kLocalhost, - base::FilePath(FILE_PATH_LITERAL("content/test/data"))); + net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_server.ServeFilesFromSourceDirectory("content/test/data"); ASSERT_TRUE(https_server.Start()); scoped_ptr<RenderViewSizeDelegate> delegate(new RenderViewSizeDelegate()); @@ -374,9 +372,9 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, OpenURLSubframe) { // Navigate to a page with frames and grab a subframe's FrameTreeNode ID. - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(embedded_test_server()->Start()); NavigateToURL(shell(), - test_server()->GetURL("files/frame_tree/top.html")); + embedded_test_server()->GetURL("/frame_tree/top.html")); WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents()); FrameTreeNode* root = wc->GetFrameTree()->root(); ASSERT_EQ(3UL, root->child_count()); @@ -384,7 +382,7 @@ EXPECT_NE(-1, frame_tree_node_id); // Navigate with the subframe's FrameTreeNode ID. - const GURL url(test_server()->GetURL("files/title1.html")); + const GURL url(embedded_test_server()->GetURL("/title1.html")); OpenURLParams params(url, Referrer(), frame_tree_node_id, CURRENT_TAB, ui::PAGE_TRANSITION_LINK, true); shell()->web_contents()->OpenURL(params); @@ -443,14 +441,14 @@ // Setup the server to allow serving separate sites, so we can perform // cross-process navigation. host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(embedded_test_server()->Start()); - foo_host_port = test_server()->host_port_pair(); + foo_host_port = embedded_test_server()->host_port_pair(); foo_host_port.set_host(kFooCom); - GURL initial_url(test_server()->GetURL("/title1.html")); + GURL initial_url(embedded_test_server()->GetURL("/title1.html")); - cross_site_url = test_server()->GetURL("/title2.html"); + cross_site_url = embedded_test_server()->GetURL("/title2.html"); replace_host.SetHostStr(kFooCom); cross_site_url = cross_site_url.ReplaceComponents(replace_host); @@ -471,7 +469,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, LoadingStateChangedForSameDocumentNavigation) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); scoped_ptr<LoadingStateChangedDelegate> delegate( new LoadingStateChangedDelegate()); shell()->web_contents()->SetDelegate(delegate.get()); @@ -496,7 +494,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, RenderViewCreatedForChildWindow) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")); @@ -550,7 +548,7 @@ }; IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, LoadProgress) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); scoped_ptr<LoadProgressDelegateAndObserver> delegate( new LoadProgressDelegateAndObserver(shell())); @@ -572,7 +570,7 @@ } IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, LoadProgressWithFrames) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); scoped_ptr<LoadProgressDelegateAndObserver> delegate( new LoadProgressDelegateAndObserver(shell())); @@ -599,7 +597,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, LoadProgressAfterInterruptedNav) { host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); // Start at a real page. NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")); @@ -663,7 +661,7 @@ #endif IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, MAYBE_FirstVisuallyNonEmptyPaint) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); scoped_ptr<FirstVisuallyNonEmptyPaintObserver> observer( new FirstVisuallyNonEmptyPaintObserver(shell())); @@ -692,7 +690,7 @@ } IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, ChangeDisplayMode) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); WebDisplayModeDelegate delegate(blink::WebDisplayModeMinimalUi); shell()->web_contents()->SetDelegate(&delegate); @@ -716,7 +714,7 @@ } IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NewNamedWindow) { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); GURL url = embedded_test_server()->GetURL("/click-noreferrer-links.html"); EXPECT_TRUE(NavigateToURL(shell(), url));
diff --git a/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/content/browser/web_contents/web_contents_view_aura_browsertest.cc index f03a68186..4140e35 100644 --- a/content/browser/web_contents/web_contents_view_aura_browsertest.cc +++ b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
@@ -36,6 +36,7 @@ #include "content/public/test/test_renderer_host.h" #include "content/public/test/test_utils.h" #include "content/shell/browser/shell.h" +#include "net/test/embedded_test_server/embedded_test_server.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" @@ -250,8 +251,12 @@ // size to the root window. Returns after the navigation to the url is // complete. void StartTestWithPage(const std::string& url) { - ASSERT_TRUE(test_server()->Start()); - GURL test_url(test_server()->GetURL(url)); + ASSERT_TRUE(embedded_test_server()->Start()); + GURL test_url; + if (url == "about:blank") + test_url = GURL(url); + else + test_url = GURL(embedded_test_server()->GetURL(url)); NavigateToURL(shell(), test_url); WebContentsImpl* web_contents = @@ -271,8 +276,7 @@ } void TestOverscrollNavigation(bool touch_handler) { - ASSERT_NO_FATAL_FAILURE( - StartTestWithPage("files/overscroll_navigation.html")); + ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html")); WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents()); NavigationController& controller = web_contents->GetController(); @@ -467,8 +471,7 @@ #endif IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_QuickOverscrollDirectionChange) { - ASSERT_NO_FATAL_FAILURE( - StartTestWithPage("files/overscroll_navigation.html")); + ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html")); WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents()); RenderFrameHost* main_frame = web_contents->GetMainFrame(); @@ -563,8 +566,7 @@ } #endif - ASSERT_NO_FATAL_FAILURE( - StartTestWithPage("files/overscroll_navigation.html")); + ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html")); WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents()); RenderFrameHost* main_frame = web_contents->GetMainFrame(); @@ -653,13 +655,10 @@ // RenderViewHost to be swapped out. IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_ScreenshotForSwappedOutRenderViews) { - ASSERT_NO_FATAL_FAILURE( - StartTestWithPage("files/overscroll_navigation.html")); + ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html")); // Create a new server with a different site. - net::SpawnedTestServer https_server( - net::SpawnedTestServer::TYPE_HTTPS, - net::SpawnedTestServer::kLocalhost, - base::FilePath(FILE_PATH_LITERAL("content/test/data"))); + net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_server.ServeFilesFromSourceDirectory("content/test/data"); ASSERT_TRUE(https_server.Start()); WebContentsImpl* web_contents = @@ -670,14 +669,13 @@ GURL url; int transition; } navigations[] = { - { https_server.GetURL("files/title1.html"), - ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR }, - { test_server()->GetURL("files/title2.html"), - ui::PAGE_TRANSITION_AUTO_BOOKMARK }, - { https_server.GetURL("files/title3.html"), - ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR }, - { GURL(), 0 } - }; + {https_server.GetURL("/title1.html"), + ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR}, + {embedded_test_server()->GetURL("/title2.html"), + ui::PAGE_TRANSITION_AUTO_BOOKMARK}, + {https_server.GetURL("/title3.html"), + ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR}, + {GURL(), 0}}; screenshot_manager()->Reset(); for (int i = 0; !navigations[i].url.is_empty(); ++i) { @@ -722,8 +720,7 @@ // Tests that navigations resulting from reloads, history.replaceState, // and history.pushState do not capture screenshots. IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ReplaceStateReloadPushState) { - ASSERT_NO_FATAL_FAILURE( - StartTestWithPage("files/overscroll_navigation.html")); + ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html")); WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents()); RenderFrameHost* main_frame = web_contents->GetMainFrame(); @@ -761,8 +758,7 @@ // better. IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, DISABLED_ContentWindowReparent) { - ASSERT_NO_FATAL_FAILURE( - StartTestWithPage("files/overscroll_navigation.html")); + ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html")); scoped_ptr<aura::Window> window(new aura::Window(NULL)); window->Init(ui::LAYER_NOT_DRAWN); @@ -785,8 +781,7 @@ } IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ContentWindowClose) { - ASSERT_NO_FATAL_FAILURE( - StartTestWithPage("files/overscroll_navigation.html")); + ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html")); WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents()); @@ -818,8 +813,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_RepeatedQuickOverscrollGestures) { - ASSERT_NO_FATAL_FAILURE( - StartTestWithPage("files/overscroll_navigation.html")); + ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html")); WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents()); @@ -873,7 +867,7 @@ // Verify that hiding a parent of the renderer will hide the content too. IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, HideContentOnParenHide) { - ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/title1.html")); + ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/title1.html")); WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents()); aura::Window* content = web_contents->GetNativeView()->parent(); @@ -887,8 +881,7 @@ // Ensure that SnapToPhysicalPixelBoundary() is called on WebContentsView parent // change. This is a regression test for http://crbug.com/388908. IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, WebContentsViewReparent) { - ASSERT_NO_FATAL_FAILURE( - StartTestWithPage("files/overscroll_navigation.html")); + ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html")); scoped_ptr<aura::Window> window(new aura::Window(NULL)); window->Init(ui::LAYER_NOT_DRAWN); @@ -918,8 +911,7 @@ // a non-scrollable area, except during gesture-nav. IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_OverscrollNavigationTouchThrottling) { - ASSERT_NO_FATAL_FAILURE( - StartTestWithPage("files/overscroll_navigation.html")); + ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html")); AddInputEventMessageFilter();
diff --git a/content/browser/webkit_browsertest.cc b/content/browser/webkit_browsertest.cc index 19e19c8..bd67587 100644 --- a/content/browser/webkit_browsertest.cc +++ b/content/browser/webkit_browsertest.cc
@@ -8,13 +8,14 @@ #include "content/public/test/content_browser_test_utils.h" #include "content/shell/browser/shell.h" #include "content/test/net/url_request_abort_on_end_job.h" +#include "net/test/embedded_test_server/embedded_test_server.h" namespace content { typedef ContentBrowserTest WebKitBrowserTest; const char kAsyncScriptThatAbortsOnEndPage[] = - "files/webkit/async_script_abort_on_end.html"; + "/webkit/async_script_abort_on_end.html"; // This is a browser test because it is hard to reproduce reliably in a // layout test without races. http://crbug.com/75604 deals with a request @@ -23,9 +24,9 @@ // if chrome does not crash. IN_PROC_BROWSER_TEST_F(WebKitBrowserTest, AbortOnEnd) { - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(embedded_test_server()->Start()); URLRequestAbortOnEndJob::AddUrlHandler(); - GURL url = test_server()->GetURL(kAsyncScriptThatAbortsOnEndPage); + GURL url = embedded_test_server()->GetURL(kAsyncScriptThatAbortsOnEndPage); NavigateToURL(shell(), url); @@ -43,12 +44,11 @@ // TODO(gavinp): remove this browser_test if we can get good LayoutTest // coverage of the same issue. -const char kXsltBadImportPage[] = - "files/webkit/xslt-bad-import.html"; +const char kXsltBadImportPage[] = "/webkit/xslt-bad-import.html"; IN_PROC_BROWSER_TEST_F(WebKitBrowserTest, XsltBadImport) { - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(embedded_test_server()->Start()); URLRequestAbortOnEndJob::AddUrlHandler(); - GURL url = test_server()->GetURL(kXsltBadImportPage); + GURL url = embedded_test_server()->GetURL(kXsltBadImportPage); NavigateToURL(shell(), url); @@ -65,11 +65,10 @@ // But both will exist when we use content_shell to run layout tests. We must // then add a mechanism to start content_shell without these, or else this // test is not very interesting. -const char kPrerenderNoCrashPage[] = - "files/prerender/prerender-no-crash.html"; +const char kPrerenderNoCrashPage[] = "/prerender/prerender-no-crash.html"; IN_PROC_BROWSER_TEST_F(WebKitBrowserTest, PrerenderNoCrash) { - ASSERT_TRUE(test_server()->Start()); - GURL url = test_server()->GetURL(kPrerenderNoCrashPage); + ASSERT_TRUE(embedded_test_server()->Start()); + GURL url = embedded_test_server()->GetURL(kPrerenderNoCrashPage); NavigateToURL(shell(), url);
diff --git a/content/browser/webui/web_ui_mojo_browsertest.cc b/content/browser/webui/web_ui_mojo_browsertest.cc index 5ceb632a..70b6c06 100644 --- a/content/browser/webui/web_ui_mojo_browsertest.cc +++ b/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -27,6 +27,7 @@ #include "content/shell/browser/shell.h" #include "content/test/data/web_ui_test_mojo_bindings.mojom.h" #include "mojo/test/test_utils.h" +#include "net/test/embedded_test_server/embedded_test_server.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" #include "third_party/mojo/src/mojo/public/js/constants.h" @@ -201,10 +202,10 @@ return; got_message = false; - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(embedded_test_server()->Start()); base::RunLoop run_loop; factory()->set_run_loop(&run_loop); - GURL test_url(test_server()->GetURL("files/web_ui_mojo.html?ping")); + GURL test_url(embedded_test_server()->GetURL("/web_ui_mojo.html?ping")); NavigateToURL(shell(), test_url); // RunLoop is quit when message received from page. run_loop.Run(); @@ -231,9 +232,9 @@ "content/public/test/test_mojo_service.mojom")) return; - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(embedded_test_server()->Start()); NavigateToURL(shell(), - test_server()->GetURL("files/web_ui_mojo_shell_test.html")); + embedded_test_server()->GetURL("/web_ui_mojo_shell_test.html")); DOMMessageQueue message_queue; std::string message;
diff --git a/content/child/resource_dispatcher.cc b/content/child/resource_dispatcher.cc index 92a0962..332b6376 100644 --- a/content/child/resource_dispatcher.cc +++ b/content/child/resource_dispatcher.cc
@@ -192,6 +192,7 @@ request_info->buffer.reset( new base::SharedMemory(shm_handle, true)); // read only + request_info->has_received_buffer = true; request_info->received_data_factory = make_scoped_refptr(new SharedMemoryReceivedDataFactory( message_sender_, request_id, request_info->buffer)); @@ -224,6 +225,11 @@ PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); bool send_ack = true; if (request_info && data_length > 0) { + // TODO(erikchen): Temporary debugging. http://crbug.com/550938. + CHECK(request_info->has_received_buffer); + CHECK(!request_info->has_destroyed_buffer); + CHECK(request_info->buffer.get()); + CHECK(base::SharedMemory::IsHandleValid(request_info->buffer->handle())); CHECK_GE(request_info->buffer_size, data_offset + data_length); @@ -342,6 +348,7 @@ return; request_info->completion_time = ConsumeIOTimestamp(); request_info->buffer.reset(); + request_info->has_destroyed_buffer = true; if (request_info->received_data_factory) request_info->received_data_factory->Stop(); request_info->received_data_factory = nullptr; @@ -504,7 +511,9 @@ frame_origin(frame_origin), response_url(request_url), download_to_file(download_to_file), - request_start(base::TimeTicks::Now()) { + request_start(base::TimeTicks::Now()), + has_received_buffer(false), + has_destroyed_buffer(false) { } ResourceDispatcher::PendingRequestInfo::~PendingRequestInfo() {
diff --git a/content/child/resource_dispatcher.h b/content/child/resource_dispatcher.h index 05500f5..b26a97a 100644 --- a/content/child/resource_dispatcher.h +++ b/content/child/resource_dispatcher.h
@@ -173,6 +173,10 @@ scoped_refptr<SharedMemoryReceivedDataFactory> received_data_factory; linked_ptr<SiteIsolationResponseMetaData> site_isolation_metadata; int buffer_size; + + // TODO(erikchen): Temporary debugging for http://crbug.com/550938. + bool has_received_buffer; + bool has_destroyed_buffer; }; typedef base::hash_map<int, PendingRequestInfo> PendingRequestList;
diff --git a/content/child/site_isolation_stats_gatherer_browsertest.cc b/content/child/site_isolation_stats_gatherer_browsertest.cc index ef22f38..68ccf31c 100644 --- a/content/child/site_isolation_stats_gatherer_browsertest.cc +++ b/content/child/site_isolation_stats_gatherer_browsertest.cc
@@ -13,7 +13,7 @@ #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" #include "content/shell/browser/shell.h" -#include "net/test/spawned_test_server/spawned_test_server.h" +#include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gmock/include/gmock/gmock.h" namespace content { @@ -28,13 +28,13 @@ ~SiteIsolationStatsGathererBrowserTest() override {} void SetUpCommandLine(base::CommandLine* command_line) override { - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(embedded_test_server()->Start()); // Add a host resolver rule to map all outgoing requests to the test server. // This allows us to use "real" hostnames in URLs, which we can use to // create arbitrary SiteInstances. command_line->AppendSwitchASCII( switches::kHostResolverRules, - "MAP * " + test_server()->host_port_pair().ToString() + + "MAP * " + embedded_test_server()->host_port_pair().ToString() + ",EXCLUDE localhost"); // Since we assume exploited renderer process, it can bypass the same origin @@ -112,26 +112,15 @@ DISALLOW_COPY_AND_ASSIGN(SiteIsolationStatsGathererBrowserTest); }; -// TODO(dsjang): we cannot run these tests on Android since SetUpCommandLine() -// is executed before the I/O thread is created on Android. After this bug -// (crbug.com/278425) is resolved, we can enable this test case on Android. -#if defined(OS_ANDROID) -#define MAYBE_CrossSiteDocumentBlockingForMimeType \ - DISABLED_CrossSiteDocumentBlockingForMimeType -#else -#define MAYBE_CrossSiteDocumentBlockingForMimeType \ - CrossSiteDocumentBlockingForMimeType -#endif - IN_PROC_BROWSER_TEST_F(SiteIsolationStatsGathererBrowserTest, - MAYBE_CrossSiteDocumentBlockingForMimeType) { + CrossSiteDocumentBlockingForMimeType) { // Load a page that issues illegal cross-site document requests to bar.com. // The page uses XHR to request HTML/XML/JSON documents from bar.com, and // inspects if any of them were successfully received. Currently, on illegal // access, the XHR requests should succeed, but the UMA histograms should // record that they would have been blocked. This test is only possible since // we run the browser without the same origin policy. - GURL foo("http://foo.com/files/cross_site_document_request.html"); + GURL foo("http://foo.com/cross_site_document_request.html"); NavigateToURL(shell(), foo); @@ -192,19 +181,8 @@ } } -// TODO(dsjang): we cannot run these tests on Android since SetUpCommandLine() -// is executed before the I/O thread is created on Android. After this bug -// (crbug.com/278425) is resolved, we can enable this test case on Android. -#if defined(OS_ANDROID) -#define MAYBE_CrossSiteDocumentBlockingForDifferentTargets \ - DISABLED_CrossSiteDocumentBlockingForDifferentTargets -#else -#define MAYBE_CrossSiteDocumentBlockingForDifferentTargets \ - CrossSiteDocumentBlockingForDifferentTargets -#endif - IN_PROC_BROWSER_TEST_F(SiteIsolationStatsGathererBrowserTest, - MAYBE_CrossSiteDocumentBlockingForDifferentTargets) { + CrossSiteDocumentBlockingForDifferentTargets) { // This webpage loads a cross-site HTML page in different targets such as // <img>,<link>,<embed>, etc. Since the requested document is blocked, and one // character string (' ') is returned instead, this tests that the renderer @@ -214,7 +192,7 @@ // TODO(nick): Split up these cases, and add positive assertions here about // what actually happens in these various resource-block cases. - GURL foo("http://foo.com/files/cross_site_document_request_target.html"); + GURL foo("http://foo.com/cross_site_document_request_target.html"); NavigateToURL(shell(), foo); }
diff --git a/content/common/cc_messages.h b/content/common/cc_messages.h index 80891cc..f31964b 100644 --- a/content/common/cc_messages.h +++ b/content/common/cc_messages.h
@@ -272,7 +272,7 @@ IPC_STRUCT_TRAITS_BEGIN(cc::ReturnedResource) IPC_STRUCT_TRAITS_MEMBER(id) - IPC_STRUCT_TRAITS_MEMBER(sync_point) + IPC_STRUCT_TRAITS_MEMBER(sync_token) IPC_STRUCT_TRAITS_MEMBER(count) IPC_STRUCT_TRAITS_MEMBER(lost) IPC_STRUCT_TRAITS_END() @@ -322,7 +322,7 @@ IPC_STRUCT_TRAITS_BEGIN(cc::GLFrameData) IPC_STRUCT_TRAITS_MEMBER(mailbox) - IPC_STRUCT_TRAITS_MEMBER(sync_point) + IPC_STRUCT_TRAITS_MEMBER(sync_token) IPC_STRUCT_TRAITS_MEMBER(size) IPC_STRUCT_TRAITS_MEMBER(sub_buffer_rect) IPC_STRUCT_TRAITS_END()
diff --git a/content/common/cc_messages_unittest.cc b/content/common/cc_messages_unittest.cc index 1a20504..58128b7 100644 --- a/content/common/cc_messages_unittest.cc +++ b/content/common/cc_messages_unittest.cc
@@ -212,7 +212,7 @@ b.mailbox_holder.mailbox.name[i]); } EXPECT_EQ(a.mailbox_holder.texture_target, b.mailbox_holder.texture_target); - EXPECT_EQ(a.mailbox_holder.sync_point, b.mailbox_holder.sync_point); + EXPECT_EQ(a.mailbox_holder.sync_token, b.mailbox_holder.sync_token); EXPECT_EQ(a.is_overlay_candidate, b.is_overlay_candidate); } }; @@ -619,8 +619,8 @@ TEST_F(CCMessagesTest, Resources) { IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL); gfx::Size arbitrary_size(757, 1281); - unsigned int arbitrary_uint1 = 71234838; - unsigned int arbitrary_uint2 = 53589793; + gpu::SyncToken arbitrary_token1(71234838); + gpu::SyncToken arbitrary_token2(53589793); GLbyte arbitrary_mailbox1[GL_MAILBOX_SIZE_CHROMIUM] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, @@ -639,7 +639,7 @@ arbitrary_resource1.size = gfx::Size(37189, 123123); arbitrary_resource1.mailbox_holder.mailbox.SetName(arbitrary_mailbox1); arbitrary_resource1.mailbox_holder.texture_target = GL_TEXTURE_2D; - arbitrary_resource1.mailbox_holder.sync_point = arbitrary_uint1; + arbitrary_resource1.mailbox_holder.sync_token = arbitrary_token1; arbitrary_resource1.is_overlay_candidate = true; TransferableResource arbitrary_resource2; @@ -649,7 +649,7 @@ arbitrary_resource2.size = gfx::Size(89123, 23789); arbitrary_resource2.mailbox_holder.mailbox.SetName(arbitrary_mailbox2); arbitrary_resource2.mailbox_holder.texture_target = GL_TEXTURE_EXTERNAL_OES; - arbitrary_resource2.mailbox_holder.sync_point = arbitrary_uint2; + arbitrary_resource2.mailbox_holder.sync_token = arbitrary_token2; arbitrary_resource2.is_overlay_candidate = false; scoped_ptr<RenderPass> renderpass_in = RenderPass::Create();
diff --git a/content/common/child_process_host_impl.cc b/content/common/child_process_host_impl.cc index c9cf76ba..707d644a 100644 --- a/content/common/child_process_host_impl.cc +++ b/content/common/child_process_host_impl.cc
@@ -25,6 +25,7 @@ #include "content/public/common/content_paths.h" #include "content/public/common/content_switches.h" #include "ipc/attachment_broker.h" +#include "ipc/attachment_broker_privileged.h" #include "ipc/ipc_channel.h" #include "ipc/ipc_logging.h" #include "ipc/message_filter.h" @@ -84,6 +85,19 @@ #if defined(OS_WIN) AddFilter(new FontCacheDispatcher()); #endif + +#if USE_ATTACHMENT_BROKER +#if defined(OS_MACOSX) && !defined(OS_IOS) + // On Mac, the privileged AttachmentBroker needs a reference to the Mach port + // Provider, which is only available in the chrome/ module. The attachment + // broker must already be created. + DCHECK(IPC::AttachmentBroker::GetGlobal()); +#else + // Construct the privileged attachment broker early in the life cycle of a + // child process. + IPC::AttachmentBrokerPrivileged::CreateBrokerIfNeeded(); +#endif // defined(OS_MACOSX) && !defined(OS_IOS) +#endif // USE_ATTACHMENT_BROKER } ChildProcessHostImpl::~ChildProcessHostImpl() {
diff --git a/content/common/frame_param_macros.h b/content/common/frame_param_macros.h index 32be0ad..a163747 100644 --- a/content/common/frame_param_macros.h +++ b/content/common/frame_param_macros.h
@@ -39,13 +39,6 @@ IPC_STRUCT_MEMBER(base::SharedMemoryHandle, shared_memory_handle) IPC_STRUCT_END() -IPC_STRUCT_BEGIN(FrameHostMsg_BuffersSwappedACK_Params) - IPC_STRUCT_MEMBER(int, gpu_host_id) - IPC_STRUCT_MEMBER(int, gpu_route_id) - IPC_STRUCT_MEMBER(gpu::Mailbox, mailbox) - IPC_STRUCT_MEMBER(uint32, sync_point) -IPC_STRUCT_END() - IPC_STRUCT_BEGIN(FrameHostMsg_CompositorFrameSwappedACK_Params) // Specifies which RenderWidget produced the CompositorFrame. IPC_STRUCT_MEMBER(int, producing_host_id)
diff --git a/content/common/gamepad_user_gesture.cc b/content/common/gamepad_user_gesture.cc index 649b5ca..54220d0 100644 --- a/content/common/gamepad_user_gesture.cc +++ b/content/common/gamepad_user_gesture.cc
@@ -4,27 +4,37 @@ #include "content/common/gamepad_user_gesture.h" +#include <math.h> + #include <algorithm> #include "third_party/WebKit/public/platform/WebGamepads.h" +namespace { +// A big enough deadzone to detect accidental presses. +const float kAxisMoveAmountThreshold = 0.5; +} + namespace content { bool GamepadsHaveUserGesture(const blink::WebGamepads& gamepads) { - for (unsigned i = 0; i < blink::WebGamepads::itemsLengthCap; i++) { + for (unsigned int i = 0; i < blink::WebGamepads::itemsLengthCap; i++) { const blink::WebGamepad& pad = gamepads.items[i]; - // If the device is physically connected, then check the primary 4 buttons + // If the device is physically connected, then check the buttons and axes // to see if there is currently an intentional user action. if (pad.connected) { - const unsigned kPrimaryInteractionButtons = 4; - unsigned buttons_to_check = std::min(pad.buttonsLength, - kPrimaryInteractionButtons); - for (unsigned button_index = 0; button_index < buttons_to_check; + for (unsigned int button_index = 0; button_index < pad.buttonsLength; button_index++) { if (pad.buttons[button_index].pressed) return true; } + + for (unsigned int axes_index = 0; axes_index < pad.axesLength; + axes_index++) { + if (fabs(pad.axes[axes_index]) > kAxisMoveAmountThreshold) + return true; + } } } return false;
diff --git a/content/common/gamepad_user_gesture.h b/content/common/gamepad_user_gesture.h index 6dbd2bf..899e366 100644 --- a/content/common/gamepad_user_gesture.h +++ b/content/common/gamepad_user_gesture.h
@@ -11,8 +11,8 @@ namespace content { -// Returns true if any of the gamepads have a button pressed that would be -// considerd a user gesture for interaction. +// Returns true if any of the gamepads have a button pressed or axis moved +// that would be considered a user gesture for interaction. bool GamepadsHaveUserGesture(const blink::WebGamepads& gamepads); } // namespace content
diff --git a/content/common/gpu/client/gl_helper.cc b/content/common/gpu/client/gl_helper.cc index e7f81af..88c64994 100644 --- a/content/common/gpu/client/gl_helper.cc +++ b/content/common/gpu/client/gl_helper.cc
@@ -133,8 +133,8 @@ ~CopyTextureToImpl() { CancelRequests(); } GLuint ConsumeMailboxToTexture(const gpu::Mailbox& mailbox, - uint32 sync_point) { - return helper_->ConsumeMailboxToTexture(mailbox, sync_point); + const gpu::SyncToken& sync_token) { + return helper_->ConsumeMailboxToTexture(mailbox, sync_token); } void CropScaleReadbackAndCleanTexture( @@ -273,7 +273,7 @@ ReadbackSwizzle swizzle); void ReadbackYUV(const gpu::Mailbox& mailbox, - uint32 sync_point, + const gpu::SyncToken& sync_token, const scoped_refptr<media::VideoFrame>& target, const gfx::Point& paste_location, const base::Callback<void(bool)>& callback) override; @@ -309,7 +309,7 @@ ReadbackSwizzle swizzle); void ReadbackYUV(const gpu::Mailbox& mailbox, - uint32 sync_point, + const gpu::SyncToken& sync_token, const scoped_refptr<media::VideoFrame>& target, const gfx::Point& paste_location, const base::Callback<void(bool)>& callback) override; @@ -815,7 +815,7 @@ void GLHelper::CropScaleReadbackAndCleanMailbox( const gpu::Mailbox& src_mailbox, - uint32 sync_point, + const gpu::SyncToken& sync_token, const gfx::Size& src_size, const gfx::Rect& src_subrect, const gfx::Size& dst_size, @@ -823,7 +823,7 @@ const SkColorType out_color_type, const base::Callback<void(bool)>& callback, GLHelper::ScalerQuality quality) { - GLuint mailbox_texture = ConsumeMailboxToTexture(src_mailbox, sync_point); + GLuint mailbox_texture = ConsumeMailboxToTexture(src_mailbox, sync_token); CropScaleReadbackAndCleanTexture(mailbox_texture, src_size, src_subrect, @@ -954,8 +954,8 @@ uint32 GLHelper::InsertSyncPoint() { return gl_->InsertSyncPointCHROMIUM(); } -void GLHelper::WaitSyncPoint(uint32 sync_point) { - gl_->WaitSyncPointCHROMIUM(sync_point); +void GLHelper::WaitSyncToken(const gpu::SyncToken& sync_token) { + gl_->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); } gpu::MailboxHolder GLHelper::ProduceMailboxHolderFromTexture( @@ -963,15 +963,16 @@ gpu::Mailbox mailbox; gl_->GenMailboxCHROMIUM(mailbox.name); gl_->ProduceTextureDirectCHROMIUM(texture_id, GL_TEXTURE_2D, mailbox.name); - return gpu::MailboxHolder(mailbox, GL_TEXTURE_2D, InsertSyncPoint()); + return gpu::MailboxHolder(mailbox, gpu::SyncToken(InsertSyncPoint()), + GL_TEXTURE_2D); } GLuint GLHelper::ConsumeMailboxToTexture(const gpu::Mailbox& mailbox, - uint32 sync_point) { + const gpu::SyncToken& sync_token) { if (mailbox.IsZero()) return 0; - if (sync_point) - WaitSyncPoint(sync_point); + if (sync_token.HasData()) + WaitSyncToken(sync_token); GLuint texture = gl_->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); return texture; @@ -1117,7 +1118,7 @@ void GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUV( const gpu::Mailbox& mailbox, - uint32 sync_point, + const gpu::SyncToken& sync_token, const scoped_refptr<media::VideoFrame>& target, const gfx::Point& paste_location, const base::Callback<void(bool)>& callback) { @@ -1125,7 +1126,7 @@ DCHECK(!(paste_location.y() & 1)); GLuint mailbox_texture = - copy_impl_->ConsumeMailboxToTexture(mailbox, sync_point); + copy_impl_->ConsumeMailboxToTexture(mailbox, sync_token); // Scale texture to right size. scaler_.Scale(mailbox_texture); @@ -1238,7 +1239,7 @@ void GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV( const gpu::Mailbox& mailbox, - uint32 sync_point, + const gpu::SyncToken& sync_token, const scoped_refptr<media::VideoFrame>& target, const gfx::Point& paste_location, const base::Callback<void(bool)>& callback) { @@ -1246,7 +1247,7 @@ DCHECK(!(paste_location.y() & 1)); GLuint mailbox_texture = - copy_impl_->ConsumeMailboxToTexture(mailbox, sync_point); + copy_impl_->ConsumeMailboxToTexture(mailbox, sync_token); GLuint texture; if (quality_ == GLHelper::SCALER_QUALITY_FAST) {
diff --git a/content/common/gpu/client/gl_helper.h b/content/common/gpu/client/gl_helper.h index 26ec217..828097d6 100644 --- a/content/common/gpu/client/gl_helper.h +++ b/content/common/gpu/client/gl_helper.h
@@ -188,7 +188,7 @@ // assumed to be GL_TEXTURE_2D. void CropScaleReadbackAndCleanMailbox( const gpu::Mailbox& src_mailbox, - uint32 sync_point, + const gpu::SyncToken& sync_token, const gfx::Size& src_size, const gfx::Rect& src_subrect, const gfx::Size& dst_size, @@ -246,8 +246,9 @@ // Insert a sync point into the GL command buffer. uint32 InsertSyncPoint(); - // Wait for the sync point before executing further GL commands. - void WaitSyncPoint(uint32 sync_point); + + // Wait for the sync token before executing further GL commands. + void WaitSyncToken(const gpu::SyncToken& sync_token); // Creates a mailbox holder that is attached to the given texture id, with a // sync point to wait on before using the mailbox. Returns a holder with an @@ -258,7 +259,7 @@ // Creates a texture and consumes a mailbox into it. Returns 0 on failure. // Note the mailbox is assumed to be GL_TEXTURE_2D. GLuint ConsumeMailboxToTexture(const gpu::Mailbox& mailbox, - uint32 sync_point); + const gpu::SyncToken& sync_token); // Resizes the texture's size to |size|. void ResizeTexture(GLuint texture, const gfx::Size& size); @@ -369,7 +370,7 @@ // the call to CreateReadbackPipelineYUV() must be fully contained within // |target->visible_rect()|. virtual void ReadbackYUV(const gpu::Mailbox& mailbox, - uint32 sync_point, + const gpu::SyncToken& sync_token, const scoped_refptr<media::VideoFrame>& target, const gfx::Point& paste_location, const base::Callback<void(bool)>& callback) = 0;
diff --git a/content/common/gpu/client/gl_helper_unittest.cc b/content/common/gpu/client/gl_helper_unittest.cc index 8278d76..e5382931 100644 --- a/content/common/gpu/client/gl_helper_unittest.cc +++ b/content/common/gpu/client/gl_helper_unittest.cc
@@ -1363,7 +1363,8 @@ context_->genMailboxCHROMIUM(mailbox.name); EXPECT_FALSE(mailbox.IsZero()); context_->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); - uint32 sync_point = context_->insertSyncPoint(); + gpu::SyncToken sync_token; + ASSERT_TRUE(context_->insertSyncPoint(sync_token.GetData())); std::string message = base::StringPrintf( "input size: %dx%d " @@ -1407,9 +1408,7 @@ base::TimeDelta::FromSeconds(0)); base::RunLoop run_loop; - yuv_reader->ReadbackYUV(mailbox, - sync_point, - output_frame.get(), + yuv_reader->ReadbackYUV(mailbox, sync_token, output_frame.get(), gfx::Point(xmargin, ymargin), base::Bind(&callcallback, run_loop.QuitClosure())); run_loop.Run();
diff --git a/content/common/gpu/client/gpu_context_tests.h b/content/common/gpu/client/gpu_context_tests.h index 5b8fb4970..814f59a0 100644 --- a/content/common/gpu/client/gpu_context_tests.h +++ b/content/common/gpu/client/gpu_context_tests.h
@@ -10,6 +10,7 @@ #include "base/run_loop.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/context_support.h" +#include "gpu/command_buffer/common/sync_token.h" namespace { @@ -43,7 +44,9 @@ if (!context_) return; - TestSignalSyncPoint(context_->insertSyncPoint()); + gpu::SyncToken sync_token; + ASSERT_TRUE(context_->insertSyncPoint(sync_token.GetData())); + TestSignalSyncPoint(static_cast<unsigned>(sync_token.release_count())); }; CONTEXT_TEST_F(SignalTest, InvalidSignalSyncPointTest) {
diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index cc04a7d..949ecf9 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h
@@ -63,7 +63,6 @@ IPC_ENUM_TRAITS_MAX_VALUE(gfx::SwapResult, gfx::SwapResult::SWAP_RESULT_LAST) IPC_ENUM_TRAITS_MAX_VALUE(gpu::MemoryAllocation::PriorityCutoff, gpu::MemoryAllocation::CUTOFF_LAST) -IPC_ENUM_TRAITS_MAX_VALUE(gpu::error::Error, gpu::error::kErrorLast) IPC_ENUM_TRAITS_MAX_VALUE(gpu::error::ContextLostReason, gpu::error::kContextLostReasonLast) IPC_ENUM_TRAITS_MAX_VALUE(media::JpegDecodeAccelerator::Error,
diff --git a/content/common/host_discardable_shared_memory_manager.cc b/content/common/host_discardable_shared_memory_manager.cc index e2b89cd..83c9a2b6 100644 --- a/content/common/host_discardable_shared_memory_manager.cc +++ b/content/common/host_discardable_shared_memory_manager.cc
@@ -124,10 +124,7 @@ base::Bind(&HostDiscardableSharedMemoryManager::OnMemoryPressure, base::Unretained(this)))), // Current thread might not have a task runner in tests. - enforce_memory_policy_task_runner_( - base::ThreadTaskRunnerHandle::IsSet() - ? base::ThreadTaskRunnerHandle::Get() - : nullptr), + enforce_memory_policy_task_runner_(base::ThreadTaskRunnerHandle::Get()), enforce_memory_policy_pending_(false), weak_ptr_factory_(this) { DCHECK_NE(memory_limit_, 0u);
diff --git a/content/common/host_discardable_shared_memory_manager_unittest.cc b/content/common/host_discardable_shared_memory_manager_unittest.cc index 3adbc72..12fb87b 100644 --- a/content/common/host_discardable_shared_memory_manager_unittest.cc +++ b/content/common/host_discardable_shared_memory_manager_unittest.cc
@@ -60,6 +60,8 @@ manager_.reset(new TestHostDiscardableSharedMemoryManager); } + // HostDiscardableSharedMemoryManager requires a message loop. + base::MessageLoop message_loop_; scoped_ptr<TestHostDiscardableSharedMemoryManager> manager_; }; @@ -241,7 +243,7 @@ manager_.reset(new HostDiscardableSharedMemoryManager); } - // This test requires a message loop. + // HostDiscardableSharedMemoryManager requires a message loop. base::MessageLoop message_loop_; scoped_ptr<HostDiscardableSharedMemoryManager> manager_; };
diff --git a/content/common/media/video_capture_messages.h b/content/common/media/video_capture_messages.h index 38cee119..3c89883 100644 --- a/content/common/media/video_capture_messages.h +++ b/content/common/media/video_capture_messages.h
@@ -119,7 +119,7 @@ IPC_MESSAGE_CONTROL4(VideoCaptureHostMsg_BufferReady, int /* device_id */, int /* buffer_id */, - uint32 /* syncpoint */, + gpu::SyncToken /* sync_token */, double /* consumer_resource_utilization */) // Get the formats supported by a device referenced by |capture_session_id|.
diff --git a/content/common/sandbox_win.cc b/content/common/sandbox_win.cc index d8689bc7..88f703c 100644 --- a/content/common/sandbox_win.cc +++ b/content/common/sandbox_win.cc
@@ -13,6 +13,7 @@ #include "base/hash.h" #include "base/logging.h" #include "base/memory/shared_memory.h" +#include "base/metrics/field_trial.h" #include "base/metrics/sparse_histogram.h" #include "base/path_service.h" #include "base/process/launch.h" @@ -540,6 +541,21 @@ } #endif +bool IsAppContainerEnabled() { + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return false; + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + const std::string appcontainer_group_name = + base::FieldTrialList::FindFullName("EnableAppContainer"); + if (command_line.HasSwitch(switches::kDisableAppContainer)) + return false; + if (command_line.HasSwitch(switches::kEnableAppContainer)) + return true; + return base::StartsWith(appcontainer_group_name, "Enabled", + base::CompareCase::INSENSITIVE_ASCII); +} + } // namespace void SetJobLevel(const base::CommandLine& cmd_line, @@ -566,13 +582,8 @@ } void AddAppContainerPolicy(sandbox::TargetPolicy* policy, const wchar_t* sid) { - if (base::win::GetVersion() >= base::win::VERSION_WIN8) { - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - if (command_line.HasSwitch(switches::kEnableAppContainer)) { - policy->SetLowBox(sid); - } - } + if (IsAppContainerEnabled()) + policy->SetLowBox(sid); } bool AddWin32kLockdownPolicy(sandbox::TargetPolicy* policy) {
diff --git a/content/common/view_messages.h b/content/common/view_messages.h index e1abbae..f7fe02a 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h
@@ -218,6 +218,7 @@ #if defined(OS_ANDROID) IPC_STRUCT_TRAITS_MEMBER(capture) #endif + IPC_STRUCT_TRAITS_MEMBER(requestor) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(content::RendererPreferences)
diff --git a/content/content.gyp b/content/content.gyp index bda908c..f1a2a97 100644 --- a/content/content.gyp +++ b/content/content.gyp
@@ -638,10 +638,14 @@ 'conditions': [ ['v8_use_external_startup_data==1', { 'dependencies': ['<(DEPTH)/v8/tools/gyp/v8.gyp:v8_external_snapshot'], - 'src_files': [ + 'renaming_sources': [ '<(PRODUCT_DIR)/natives_blob.bin', '<(PRODUCT_DIR)/snapshot_blob.bin', ], + 'renaming_destinations': [ + 'natives_blob_<(arch_suffix).bin', + 'snapshot_blob_<(arch_suffix).bin', + ], }], ['icu_use_data_file_flag==1', { 'dependencies': ['<(DEPTH)/third_party/icu/icu.gyp:icudata'], @@ -653,6 +657,7 @@ }, 'includes': [ '../build/android/copy_ex.gypi', + '../build/android/v8_external_startup_data_arch_suffix.gypi', ], }, ],
diff --git a/content/content_app.gypi b/content/content_app.gypi index 5afdd33..4de603bb 100644 --- a/content/content_app.gypi +++ b/content/content_app.gypi
@@ -62,12 +62,5 @@ 'content.gyp:sandbox_helper_win', ], }], - ['OS=="ios"', { - 'sources!': [ - 'app/content_main.cc', - 'app/mojo/mojo_init.cc', - 'app/mojo/mojo_init.h', - ], - }], ], }
diff --git a/content/content_browser.gypi b/content/content_browser.gypi index b000f21..bafd9f3 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi
@@ -1807,18 +1807,12 @@ # implementation, and re-include what is used. ['exclude', '\\.(cc|mm)$'], ['include', '_ios\\.(cc|mm)$'], - ['include', '^public/browser/browser_main_parts\\.cc$'], ['include', '^public/browser/content_browser_client\\.cc$'], - ['include', '^public/browser/favicon_status\\.cc$'], ['include', '^public/browser/navigation_details\\.cc$'], ['include', '^public/browser/notification_registrar\\.cc$'], ['include', '^public/browser/page_navigator\\.cc$'], ['include', '^public/browser/web_ui_controller\\.cc'], ['include', '^browser/browser_context\\.cc$'], - ['include', '^browser/browser_main_loop\\.cc$'], - ['include', '^browser/browser_main_runner\\.cc$'], - ['include', '^browser/browser_process_sub_thread\\.cc$'], - ['include', '^browser/browser_thread_impl\\.cc$'], ['include', '^browser/browser_url_handler_impl\\.cc$'], ['include', '^browser/cert_store_impl\\.cc$'], ['include', '^browser/download/download_create_info\\.cc$'], @@ -1836,6 +1830,7 @@ '../cc/cc.gyp:cc', '../cc/cc.gyp:cc_surfaces', '../components/mime_util/mime_util.gyp:mime_util', + '../components/scheduler/scheduler.gyp:scheduler_common', '../device/bluetooth/bluetooth.gyp:device_bluetooth', '../gin/gin.gyp:gin', '../net/net.gyp:http_server',
diff --git a/content/content_shell.gypi b/content/content_shell.gypi index 4a77d2b6..637b557 100644 --- a/content/content_shell.gypi +++ b/content/content_shell.gypi
@@ -941,13 +941,16 @@ }], ['v8_use_external_startup_data==1', { 'additional_input_paths': [ - '<(asset_location)/natives_blob.bin', - '<(asset_location)/snapshot_blob.bin', + '<(asset_location)/natives_blob_<(arch_suffix).bin', + '<(asset_location)/snapshot_blob_<(arch_suffix).bin', ], }], ], }, - 'includes': [ '../build/java_apk.gypi' ], + 'includes': [ + '../build/android/v8_external_startup_data_arch_suffix.gypi', + '../build/java_apk.gypi', + ], }, ], }], # OS=="android"
diff --git a/content/content_tests.gypi b/content/content_tests.gypi index 04ba14e..75789a5 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi
@@ -281,7 +281,6 @@ 'test/browser_test_utils_browsertest.cc', 'test/content_browser_test_test.cc', 'test/webui_resource_browsertest.cc', - ], 'content_browsertests_android_sources': [ 'browser/accessibility/android_granularity_movement_browsertest.cc', @@ -811,35 +810,6 @@ }, 'targets': [ { - # GN version: //content/test:layouttest_support - 'target_name': 'layouttest_support_content', - 'type': 'static_library', - 'conditions': [ - ['OS=="android"', { - 'dependencies': [ - 'test_support_content_jni_headers', - ], - }], - ['OS!="ios"', { - # layouttest_support_content is not supported nor required on iOS. - 'dependencies': [ - 'content.gyp:content_renderer', - 'test_support_content', - '../components/test_runner/test_runner.gyp:test_runner', - '../skia/skia.gyp:skia', - '../ui/accessibility/accessibility.gyp:ax_gen', - '../ui/base/ime/ui_base_ime.gyp:ui_base_ime', - '../v8/tools/gyp/v8.gyp:v8', - ], - 'include_dirs': [ - '..', - '<(SHARED_INTERMEDIATE_DIR)', - ], - 'sources': [ '<@(layouttest_support_content_sources)' ] - }], - ], - }, - { # GN version: //content/test:test_support 'target_name': 'test_support_content', 'type': 'static_library', @@ -865,7 +835,6 @@ '../ui/resources/ui_resources.gyp:ui_resources', '../url/url.gyp:url_lib', 'browser/speech/proto/speech_proto.gyp:speech_proto', - 'content.gyp:content_app_both', 'content.gyp:content_browser', 'content.gyp:content_common', ], @@ -894,16 +863,12 @@ # implementation, and re-include what is used. ['exclude', '\\.(cc|mm)$'], ['include', '_ios\\.(cc|mm)$'], - ['include', '^public/test/content_test_suite_base\\.cc$'], ['include', '^public/test/mock_notification_observer\\.cc$'], ['include', '^public/test/mock_resource_context\\.cc$'], - ['include', '^public/test/test_browser_thread\\.cc$'], - ['include', '^public/test/test_browser_thread_bundle\\.cc$'], ['include', '^public/test/test_content_client_initializer\\.cc$'], ['include', '^public/test/test_notification_tracker\\.cc$'], ['include', '^public/test/test_utils\\.cc$'], ['include', '^public/test/unittest_test_suite\\.cc$'], - ['include', '^test/content_test_suite\\.cc$'], ['include', '^test/test_content_browser_client\\.cc$'], ['include', '^test/test_content_client\\.cc$'], ], @@ -921,6 +886,7 @@ ], 'dependencies': [ 'content_test_mojo_bindings', + 'content.gyp:content_app_both', 'content.gyp:content_child', 'content.gyp:content_common', 'content.gyp:content_gpu', @@ -1029,226 +995,6 @@ }], ], }, - { - # GN version: //content/test:content_unittests - 'target_name': 'content_unittests', - 'type': '<(gtest_target_type)', - 'dependencies': [ - 'browser/background_sync/background_sync_proto.gyp:background_sync_proto', - 'browser/cache_storage/cache_storage_proto.gyp:cache_storage_proto', - 'browser/notifications/notification_proto.gyp:notification_proto', - 'browser/service_worker/service_worker_proto.gyp:service_worker_proto', - 'browser/speech/proto/speech_proto.gyp:speech_proto', - 'content.gyp:content_browser', - 'content.gyp:content_common', - 'content_common_mojo_bindings.gyp:content_common_mojo_bindings', - 'test_support_content', - '../base/base.gyp:test_support_base', - '../crypto/crypto.gyp:crypto', - '../device/battery/battery.gyp:device_battery', - '../device/battery/battery.gyp:device_battery_mojo_bindings', - '../mojo/mojo_base.gyp:mojo_environment_chromium', - '../net/net.gyp:net_extras', - '../net/net.gyp:net_test_support', - '../skia/skia.gyp:skia', - '../sql/sql.gyp:sql', - '../sql/sql.gyp:test_support_sql', - '../testing/gmock.gyp:gmock', - '../testing/gtest.gyp:gtest', - '../third_party/mojo/mojo_edk.gyp:mojo_common_test_support', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', - '../third_party/re2/re2.gyp:re2', - '../ui/accessibility/accessibility.gyp:accessibility', - '../ui/base/ui_base.gyp:ui_base', - '../ui/events/events.gyp:blink', - '../ui/gfx/gfx.gyp:gfx', - '../ui/gfx/gfx.gyp:gfx_geometry', - '../ui/gfx/ipc/gfx_ipc.gyp:gfx_ipc', - ], - 'include_dirs': [ - '..', - '<(SHARED_INTERMEDIATE_DIR)', # Needed by render_media_client_unittest.cc. - ], - 'sources': [ '<@(content_unittests_sources)' ], - 'conditions': [ - ['OS == "ios"', { - 'sources/': [ - # iOS only needs a small portion of content; exclude all the - # implementation, and re-include what is used. - ['exclude', '\\.(cc|mm)$'], - ['include', '_ios\\.(cc|mm)$'], - ['include', '^browser/notification_service_impl_unittest\\.cc$'], - ['include', '^browser/web_contents/navigation_entry_impl_unittest\\.cc$'], - ['include', '^test/run_all_unittests\\.cc$'], - ], - }, { # OS != "ios" - 'dependencies': [ - 'content.gyp:content_browser', - 'content.gyp:content_child', - 'content.gyp:content_gpu', - 'content.gyp:content_plugin', - 'content.gyp:content_renderer', - 'content.gyp:content_resources', - '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', - '../cc/cc.gyp:cc', - '../cc/cc.gyp:cc_surfaces', - '../cc/cc_tests.gyp:cc_test_support', - '../gin/gin.gyp:gin', - '../gpu/gpu.gyp:gpu', - '../gpu/gpu.gyp:gpu_unittest_utils', - '../ipc/ipc.gyp:test_support_ipc', - '../media/media.gyp:media_test_support', - '../media/media.gyp:shared_memory_support', - '../storage/storage_browser.gyp:storage', - '../storage/storage_common.gyp:storage_common', - '../third_party/WebKit/public/blink.gyp:blink', - '../third_party/icu/icu.gyp:icui18n', - '../third_party/icu/icu.gyp:icuuc', - '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase', - '../third_party/libjingle/libjingle.gyp:libjingle', - '../ui/gl/gl.gyp:gl', - '../ui/gl/gl.gyp:gl_test_support', - ], - }], - ['OS != "win"', { - 'sources': [ - 'browser/file_descriptor_info_impl_unittest.cc', - ], - }], - ['OS == "mac"', { - 'dependencies': [ - '../third_party/ocmock/ocmock.gyp:ocmock', - ], - }], - ['enable_plugins==1', { - 'sources': [ '<@(content_unittests_plugins_sources)' ], - }], - ['enable_webrtc==1', { - 'sources': [ '<@(content_unittests_webrtc_sources)' ], - 'dependencies': [ - '../third_party/libjingle/libjingle.gyp:libjingle_webrtc', - '../third_party/libjingle/libjingle.gyp:libpeerconnection', - '../third_party/webrtc/modules/modules.gyp:video_capture_module', - ] - }], - ['enable_webrtc==1 and enable_plugins==1', { - 'sources': [ '<@(content_unittests_plugin_webrtc_sources)' ], - }], - ['enable_webrtc==1 and (OS=="linux" or OS=="mac" or OS=="win")', { - 'sources': [ - 'browser/media/capture/desktop_capture_device_unittest.cc', - ], - 'dependencies': [ - '../third_party/webrtc/modules/modules.gyp:desktop_capture', - ], - }], - ['enable_webrtc==1 and chromeos==1', { - 'sources': [ - 'browser/media/capture/desktop_capture_device_aura_unittest.cc', - ], - }], - ['enable_web_speech==1', { - 'sources': [ '<@(content_unittests_speech_sources)' ], - }], - ['OS=="linux" and use_dbus==1', { - 'dependencies': [ - '../build/linux/system.gyp:dbus', - '../dbus/dbus.gyp:dbus_test_support', - ], - }], - ['OS=="win" and win_use_allocator_shim==1', { - 'dependencies': [ - '../base/allocator/allocator.gyp:allocator', - ], - }], - ['OS=="win"', { - 'dependencies': [ - '../third_party/iaccessible2/iaccessible2.gyp:iaccessible2', - ], - }], - ['OS=="mac"', { - # These flags are needed to run the test on Mac. - # Search for comments about "xcode_settings" in chrome_tests.gypi. - 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-ObjC']}, - }], - ['chromeos==1', { - 'dependencies': [ - '../chromeos/chromeos.gyp:chromeos', - ], - 'sources!': [ - 'browser/geolocation/wifi_data_provider_linux_unittest.cc', - ], - }], - ['use_aura==1', { - 'dependencies': [ - '../ui/aura/aura.gyp:aura', - '../ui/aura_extra/aura_extra.gyp:aura_extra', - '../ui/wm/wm.gyp:wm', - ] - }], - ['use_aura==1 or toolkit_views==1', { - 'dependencies': [ - '../ui/events/events.gyp:events_test_support', - ], - }], - ['use_aura!=1 and OS!="mac"', { - 'sources/': [ - ['exclude', '^browser/compositor/'], - ], - }], - ['OS == "android"', { - 'sources': [ '<@(content_unittests_android_sources)' ], - 'sources!': [ - 'browser/geolocation/network_location_provider_unittest.cc', - 'browser/geolocation/wifi_data_provider_common_unittest.cc', - 'browser/power_usage_monitor_impl_unittest.cc', - 'browser/renderer_host/begin_frame_observer_proxy_unittest.cc', - 'browser/webui/url_data_manager_backend_unittest.cc', - 'renderer/media/media_recorder_handler_unittest.cc', - 'renderer/media/video_track_recorder_unittest.cc', - ], - 'dependencies': [ - '../testing/android/native_test.gyp:native_test_native_code', - ], - 'dependencies!': [ - '../device/battery/battery.gyp:device_battery', - ], - }], - ['OS != "android" and OS != "ios"', { - 'dependencies': [ - '../third_party/libvpx_new/libvpx.gyp:libvpx_new', - ], - }], - ['use_aura!=1 and OS!="android"', { - 'sources!': [ - 'browser/renderer_host/input/tap_suppression_controller_unittest.cc', - ], - }], - ['use_dbus==0', { - 'sources!': [ - 'browser/geolocation/wifi_data_provider_linux_unittest.cc', - ], - }], - ['OS!="win" and OS!="mac"', { - 'sources!': [ - 'common/plugin_list_unittest.cc', - ], - }], - ['use_ozone==1', { - 'sources': [ '<@(content_unittests_ozone_sources)' ], - 'dependencies': [ - '../ui/ozone/ozone.gyp:ozone', - '../ui/ozone/ozone.gyp:ozone_base', - ], - }], - ['OS == "mac"', { - 'sources': [ '<@(content_unittests_mac_sources)' ], - 'dependencies': [ - '../third_party/boringssl/boringssl.gyp:boringssl', - ], - }], - ], - }, ], 'conditions': [ ['test_isolation_mode != "noop"', { @@ -1318,6 +1064,236 @@ ['OS!="ios"', { 'targets': [ { + # GN version: //content/test:layouttest_support + 'target_name': 'layouttest_support_content', + 'type': 'static_library', + 'dependencies': [ + 'content.gyp:content_renderer', + 'test_support_content', + '../components/test_runner/test_runner.gyp:test_runner', + '../skia/skia.gyp:skia', + '../ui/accessibility/accessibility.gyp:ax_gen', + '../ui/base/ime/ui_base_ime.gyp:ui_base_ime', + '../v8/tools/gyp/v8.gyp:v8', + ], + 'include_dirs': [ + '..', + '<(SHARED_INTERMEDIATE_DIR)', + ], + 'sources': [ '<@(layouttest_support_content_sources)' ], + 'conditions': [ + ['OS=="android"', { + 'dependencies': [ + 'test_support_content_jni_headers', + ], + }], + ], + }, + { + # GN version: //content/test:content_unittests + 'target_name': 'content_unittests', + 'type': '<(gtest_target_type)', + 'dependencies': [ + 'browser/background_sync/background_sync_proto.gyp:background_sync_proto', + 'browser/cache_storage/cache_storage_proto.gyp:cache_storage_proto', + 'browser/notifications/notification_proto.gyp:notification_proto', + 'browser/service_worker/service_worker_proto.gyp:service_worker_proto', + 'browser/speech/proto/speech_proto.gyp:speech_proto', + 'content.gyp:content_browser', + 'content.gyp:content_child', + 'content.gyp:content_common', + 'content.gyp:content_gpu', + 'content.gyp:content_plugin', + 'content.gyp:content_renderer', + 'content.gyp:content_resources', + 'content_common_mojo_bindings.gyp:content_common_mojo_bindings', + 'test_support_content', + '../base/base.gyp:test_support_base', + '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', + '../cc/cc.gyp:cc', + '../cc/cc.gyp:cc_surfaces', + '../cc/cc_tests.gyp:cc_test_support', + '../crypto/crypto.gyp:crypto', + '../device/battery/battery.gyp:device_battery', + '../device/battery/battery.gyp:device_battery_mojo_bindings', + '../gin/gin.gyp:gin', + '../gpu/gpu.gyp:gpu', + '../gpu/gpu.gyp:gpu_unittest_utils', + '../ipc/ipc.gyp:test_support_ipc', + '../media/media.gyp:media_test_support', + '../media/media.gyp:shared_memory_support', + '../mojo/mojo_base.gyp:mojo_environment_chromium', + '../net/net.gyp:net_extras', + '../net/net.gyp:net_test_support', + '../skia/skia.gyp:skia', + '../sql/sql.gyp:sql', + '../sql/sql.gyp:test_support_sql', + '../storage/storage_browser.gyp:storage', + '../storage/storage_common.gyp:storage_common', + '../testing/gmock.gyp:gmock', + '../testing/gtest.gyp:gtest', + '../third_party/icu/icu.gyp:icui18n', + '../third_party/icu/icu.gyp:icuuc', + '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase', + '../third_party/libjingle/libjingle.gyp:libjingle', + '../third_party/mojo/mojo_edk.gyp:mojo_common_test_support', + '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../third_party/re2/re2.gyp:re2', + '../third_party/WebKit/public/blink.gyp:blink', + '../ui/accessibility/accessibility.gyp:accessibility', + '../ui/base/ui_base.gyp:ui_base', + '../ui/events/events.gyp:blink', + '../ui/gfx/gfx.gyp:gfx', + '../ui/gfx/gfx.gyp:gfx_geometry', + '../ui/gfx/ipc/gfx_ipc.gyp:gfx_ipc', + '../ui/gl/gl.gyp:gl', + '../ui/gl/gl.gyp:gl_test_support', + ], + 'include_dirs': [ + '..', + '<(SHARED_INTERMEDIATE_DIR)', # Needed by render_media_client_unittest.cc. + ], + 'sources': [ '<@(content_unittests_sources)' ], + 'conditions': [ + ['OS != "win"', { + 'sources': [ + 'browser/file_descriptor_info_impl_unittest.cc', + ], + }], + ['OS == "mac"', { + 'dependencies': [ + '../third_party/ocmock/ocmock.gyp:ocmock', + ], + }], + ['enable_plugins==1', { + 'sources': [ '<@(content_unittests_plugins_sources)' ], + }], + ['enable_webrtc==1', { + 'sources': [ '<@(content_unittests_webrtc_sources)' ], + 'dependencies': [ + '../third_party/libjingle/libjingle.gyp:libjingle_webrtc', + '../third_party/libjingle/libjingle.gyp:libpeerconnection', + '../third_party/webrtc/modules/modules.gyp:video_capture_module', + ], + }], + ['enable_webrtc==1 and enable_plugins==1', { + 'sources': [ '<@(content_unittests_plugin_webrtc_sources)' ], + }], + ['enable_webrtc==1 and (OS=="linux" or OS=="mac" or OS=="win")', { + 'sources': [ + 'browser/media/capture/desktop_capture_device_unittest.cc', + ], + 'dependencies': [ + '../third_party/webrtc/modules/modules.gyp:desktop_capture', + ], + }], + ['enable_webrtc==1 and chromeos==1', { + 'sources': [ + 'browser/media/capture/desktop_capture_device_aura_unittest.cc', + ], + }], + ['enable_web_speech==1', { + 'sources': [ '<@(content_unittests_speech_sources)' ], + }], + ['OS=="linux" and use_dbus==1', { + 'dependencies': [ + '../build/linux/system.gyp:dbus', + '../dbus/dbus.gyp:dbus_test_support', + ], + }], + ['OS=="win" and win_use_allocator_shim==1', { + 'dependencies': [ + '../base/allocator/allocator.gyp:allocator', + ], + }], + ['OS=="win"', { + 'dependencies': [ + '../third_party/iaccessible2/iaccessible2.gyp:iaccessible2', + ], + }], + ['OS=="mac"', { + # These flags are needed to run the test on Mac. + # Search for comments about "xcode_settings" in chrome_tests.gypi. + 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-ObjC']}, + }], + ['chromeos==1', { + 'dependencies': [ + '../chromeos/chromeos.gyp:chromeos', + ], + 'sources!': [ + 'browser/geolocation/wifi_data_provider_linux_unittest.cc', + ], + }], + ['use_aura==1', { + 'dependencies': [ + '../ui/aura/aura.gyp:aura', + '../ui/aura_extra/aura_extra.gyp:aura_extra', + '../ui/wm/wm.gyp:wm', + ], + }], + ['use_aura==1 or toolkit_views==1', { + 'dependencies': [ + '../ui/events/events.gyp:events_test_support', + ], + }], + ['use_aura!=1 and OS!="mac"', { + 'sources/': [ + ['exclude', '^browser/compositor/'], + ], + }], + ['OS == "android"', { + 'sources': [ '<@(content_unittests_android_sources)' ], + 'sources!': [ + 'browser/geolocation/network_location_provider_unittest.cc', + 'browser/geolocation/wifi_data_provider_common_unittest.cc', + 'browser/power_usage_monitor_impl_unittest.cc', + 'browser/renderer_host/begin_frame_observer_proxy_unittest.cc', + 'browser/webui/url_data_manager_backend_unittest.cc', + 'renderer/media/media_recorder_handler_unittest.cc', + 'renderer/media/video_track_recorder_unittest.cc', + ], + 'dependencies': [ + '../testing/android/native_test.gyp:native_test_native_code', + ], + 'dependencies!': [ + '../device/battery/battery.gyp:device_battery', + ], + }, { # OS != "android" + 'dependencies': [ + '../third_party/libvpx_new/libvpx.gyp:libvpx_new', + ], + }], + ['use_aura!=1 and OS!="android"', { + 'sources!': [ + 'browser/renderer_host/input/tap_suppression_controller_unittest.cc', + ], + }], + ['use_dbus==0', { + 'sources!': [ + 'browser/geolocation/wifi_data_provider_linux_unittest.cc', + ], + }], + ['OS!="win" and OS!="mac"', { + 'sources!': [ + 'common/plugin_list_unittest.cc', + ], + }], + ['use_ozone==1', { + 'sources': [ '<@(content_unittests_ozone_sources)' ], + 'dependencies': [ + '../ui/ozone/ozone.gyp:ozone', + '../ui/ozone/ozone.gyp:ozone_base', + ], + }], + ['OS == "mac"', { + 'sources': [ '<@(content_unittests_mac_sources)' ], + 'dependencies': [ + '../third_party/boringssl/boringssl.gyp:boringssl', + ], + }], + ], + }, + { # GN version: //content/test:content_perftests 'target_name': 'content_perftests', 'type': '<(gtest_target_type)', @@ -1878,10 +1854,14 @@ ], 'variables': { 'dest_path': '<(asset_location)', - 'src_files': [ + 'renaming_sources': [ '<(PRODUCT_DIR)/natives_blob.bin', '<(PRODUCT_DIR)/snapshot_blob.bin', ], + 'renaming_destinations': [ + 'natives_blob_<(arch_suffix).bin', + 'snapshot_blob_<(arch_suffix).bin', + ], 'clear': 1, }, 'includes': ['../build/android/copy_ex.gypi'], @@ -1894,13 +1874,16 @@ ['v8_use_external_startup_data==1', { 'asset_location': '<(PRODUCT_DIR)/content_unittests_apk/assets', 'additional_input_paths': [ - '<(PRODUCT_DIR)/content_unittests_apk/assets/natives_blob.bin', - '<(PRODUCT_DIR)/content_unittests_apk/assets/snapshot_blob.bin', + '<(PRODUCT_DIR)/content_unittests_apk/assets/natives_blob_<(arch_suffix).bin', + '<(PRODUCT_DIR)/content_unittests_apk/assets/snapshot_blob_<(arch_suffix).bin', ], }], ], }, - 'includes': [ '../build/apk_test.gypi' ], + 'includes': [ + '../build/apk_test.gypi', + '../build/android/v8_external_startup_data_arch_suffix.gypi', + ], }, { 'target_name': 'content_shell_browsertests_java',
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentReadbackHandler.java b/content/public/android/java/src/org/chromium/content/browser/ContentReadbackHandler.java index 6bfae67..e549e83c 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentReadbackHandler.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentReadbackHandler.java
@@ -12,7 +12,6 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.content_public.browser.readback_types.ReadbackResponse; -import org.chromium.ui.base.WindowAndroid; /** * A class for reading back content. @@ -98,31 +97,6 @@ } /** - * Asynchronously, grab a bitmap of the current browser compositor root layer. - * - * @param windowAndroid The window that hosts the compositor. - * @param callback The callback to be executed after readback completes. - */ - public void getCompositorBitmapAsync( - WindowAndroid windowAndroid, final GetBitmapCallback callback) { - if (!readyForReadback()) { - ThreadUtils.postOnUiThread(new Runnable() { - @Override - public void run() { - callback.onFinishGetBitmap(null, ReadbackResponse.SURFACE_UNAVAILABLE); - } - }); - return; - } - ThreadUtils.assertOnUiThread(); - - int readbackId = mNextReadbackId++; - mGetBitmapRequests.put(readbackId, callback); - nativeGetCompositorBitmap(mNativeContentReadbackHandler, readbackId, - windowAndroid.getNativePointer()); - } - - /** * Implemented by the owner of this class to signal whether readback is possible or not. * @return Whether readback is possible or not. */ @@ -133,6 +107,4 @@ private native void nativeGetContentBitmap(long nativeContentReadbackHandler, int readbackId, float scale, Bitmap.Config config, float x, float y, float width, float height, Object contentViewCore); - private native void nativeGetCompositorBitmap(long nativeContentReadbackHandler, - int readbackId, long nativeWindowAndroid); }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java index dfbe5f2..f112dc48 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
@@ -8,6 +8,7 @@ import android.annotation.TargetApi; import android.app.Activity; import android.app.SearchManager; +import android.app.assist.AssistStructure.ViewNode; import android.content.ClipboardManager; import android.content.ContentResolver; import android.content.Context; @@ -111,14 +112,6 @@ // produce little visible difference. private static final float ZOOM_CONTROLS_EPSILON = 0.007f; - /** - * TODO(sgurun) remove these and use public API. crbug/512264 - */ - private static final int TEXT_STYLE_BOLD = 1 << 0; - private static final int TEXT_STYLE_ITALIC = 1 << 1; - private static final int TEXT_STYLE_UNDERLINE = 1 << 2; - private static final int TEXT_STYLE_STRIKE_THRU = 1 << 3; - private static final ZoomControlsDelegate NO_OP_ZOOM_CONTROLS_DELEGATE = new ZoomControlsDelegate() { @Override @@ -487,7 +480,6 @@ private ImeAdapter mImeAdapter; private ImeAdapter.AdapterInputConnectionFactory mAdapterInputConnectionFactory; private AdapterInputConnection mInputConnection; - private InputMethodManagerWrapper mInputMethodManagerWrapper; // Lazily created paste popup menu, triggered either via long press in an // editable region or from tapping the insertion handle. @@ -631,10 +623,7 @@ */ public ContentViewCore(Context context) { mContext = context; - mAdapterInputConnectionFactory = new AdapterInputConnectionFactory(); - mInputMethodManagerWrapper = new InputMethodManagerWrapper(mContext); - mRenderCoordinates = new RenderCoordinates(); mJoystickScrollProvider = new JoystickScrollProvider(this); float deviceScaleFactor = getContext().getResources().getDisplayMetrics().density; @@ -653,7 +642,8 @@ mEditable = Editable.Factory.getInstance().newEditable(""); Selection.setSelection(mEditable, 0); mContainerViewObservers = new ObserverList<ContainerViewObserver>(); - mCurrentConfig = getContext().getResources().getConfiguration(); + // Deep copy newConfig so that we can notice the difference. + mCurrentConfig = new Configuration(getContext().getResources().getConfiguration()); } /** @@ -737,17 +727,12 @@ } @VisibleForTesting - public void setInputMethodManagerWrapperForTest(InputMethodManagerWrapper immw) { - mInputMethodManagerWrapper = immw; - } - - @VisibleForTesting public AdapterInputConnection getInputConnectionForTest() { return mInputConnection; } private ImeAdapter createImeAdapter() { - return new ImeAdapter(mInputMethodManagerWrapper, + return new ImeAdapter(new InputMethodManagerWrapper(mContext), new ImeAdapter.ImeAdapterDelegate() { @Override public void onImeEvent() { @@ -1555,6 +1540,18 @@ * @see View#onCreateInputConnection(EditorInfo) */ public InputConnection onCreateInputConnection(EditorInfo outAttrs) { + // Android View framework will check whether the user can compose text by calling this + // function at view attachment. Especially in the case of hardware keyboard, connection can + // be made regardless of whether we have called showSoftInput(), and therefore we need + // to check the availability ourselves here. + // If we return null here, hardware keyboard will not be connected through input connection, + // but key events will go through View#dispatchKeyEvent(), and the user won't get any + // recommendation from text composition, which is what we expect. + if (!mImeAdapter.canCreateInputConnection()) { + mInputConnection = null; + return null; + } + if (!mImeAdapter.hasTextInputType()) { // Although onCheckIsTextEditor will return false in this case, the EditorInfo // is still used by the InputMethodService. Need to make sure the IME doesn't @@ -1594,21 +1591,17 @@ if (mCurrentConfig.keyboard != newConfig.keyboard || mCurrentConfig.keyboardHidden != newConfig.keyboardHidden || mCurrentConfig.hardKeyboardHidden != newConfig.hardKeyboardHidden) { - if (mNativeContentViewCore != 0) { - mImeAdapter.attach(nativeGetNativeImeAdapter(mNativeContentViewCore)); - } - mInputMethodManagerWrapper.restartInput(mContainerView); - // By default, we show soft keyboard on keyboard changes. This is useful - // when the user transitions from hardware keyboard to software keyboard. - mImeAdapter.showSoftKeyboard(); + mImeAdapter.onKeyboardConfigurationChanged(); } + // Deep copy newConfig so that we can notice the difference. + mCurrentConfig = new Configuration(newConfig); + mContainerViewInternals.super_onConfigurationChanged(newConfig); // To request layout has side effect, but it seems OK as it only happen in // onConfigurationChange and layout has to be changed in most case. mContainerView.requestLayout(); } finally { - mCurrentConfig = newConfig; TraceEvent.end("ContentViewCore.onConfigurationChanged"); } } @@ -1685,10 +1678,11 @@ } public void onFocusChanged(boolean gainFocus) { + mImeAdapter.onViewFocusChanged(gainFocus); + if (gainFocus) { restoreSelectionPopupsIfNecessary(); } else { - hideImeIfNeeded(); cancelRequestToScrollFocusedEditableNodeIntoView(); if (mPreserveSelectionOnNextLossOfFocus) { mPreserveSelectionOnNextLossOfFocus = false; @@ -2396,20 +2390,6 @@ nativeSetTextHandlesTemporarilyHidden(mNativeContentViewCore, hide); } - /** - * Hides the IME if the containerView is the active view for IME. - */ - public void hideImeIfNeeded() { - // Hide input method window from the current view synchronously - // because ImeAdapter does so asynchronouly with a delay, and - // by the time when ImeAdapter dismisses the input, the - // containerView may have lost focus. - if (mInputMethodManagerWrapper.isActive(mContainerView)) { - mInputMethodManagerWrapper.hideSoftInputFromWindow( - mContainerView.getWindowToken(), 0, null); - } - } - @SuppressWarnings("unused") @CalledByNative private void updateFrameInfo( @@ -3046,10 +3026,10 @@ node.width, node.height); viewNode.setChildCount(node.children.size()); if (node.hasStyle) { - int style = (node.bold ? TEXT_STYLE_BOLD : 0) - | (node.italic ? TEXT_STYLE_ITALIC : 0) - | (node.underline ? TEXT_STYLE_UNDERLINE : 0) - | (node.lineThrough ? TEXT_STYLE_STRIKE_THRU : 0); + int style = (node.bold ? ViewNode.TEXT_STYLE_BOLD : 0) + | (node.italic ? ViewNode.TEXT_STYLE_ITALIC : 0) + | (node.underline ? ViewNode.TEXT_STYLE_UNDERLINE : 0) + | (node.lineThrough ? ViewNode.TEXT_STYLE_STRIKE_THRU : 0); viewNode.setTextStyle(node.textSize, node.color, node.bgcolor, style); } for (int i = 0; i < node.children.size(); i++) {
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/AdapterInputConnection.java b/content/public/android/java/src/org/chromium/content/browser/input/AdapterInputConnection.java index 50bae1c4..13a48f8 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/AdapterInputConnection.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/AdapterInputConnection.java
@@ -530,10 +530,6 @@ return mImeAdapter.setComposingRegion(regionText, a, b); } - boolean isActive() { - return getInputMethodManagerWrapper().isActive(mInternalView); - } - private InputMethodManagerWrapper getInputMethodManagerWrapper() { return mImeAdapter.getInputMethodManagerWrapper(); }
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java index b0a56df3..c53070ae 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java
@@ -91,12 +91,10 @@ private InputMethodManagerWrapper mInputMethodManagerWrapper; private AdapterInputConnection mInputConnection; private final ImeAdapterDelegate mViewEmbedder; + private int mTextInputType = TextInputType.NONE; private int mTextInputFlags; - @VisibleForTesting - boolean mIsShowWithoutHideOutstanding = false; - /** * @param wrapper InputMethodManagerWrapper that should receive all the call directed to * InputMethodManager. @@ -123,7 +121,7 @@ * @param immw InputMethodManagerWrapper that should be used to call InputMethodManager. */ @VisibleForTesting - public void setInputMethodManagerWrapper(InputMethodManagerWrapper immw) { + public void setInputMethodManagerWrapperForTest(InputMethodManagerWrapper immw) { mInputMethodManagerWrapper = immw; } @@ -210,7 +208,7 @@ if (textInputType != TextInputType.NONE) { if (showIfNeeded) showSoftKeyboard(); } else { - hideSoftKeyboard(); + hideKeyboard(); } } @@ -234,8 +232,7 @@ * Show soft keyboard only if it is the current keyboard configuration. */ public void showSoftKeyboard() { - Log.d(TAG, "showKeyboard"); - mIsShowWithoutHideOutstanding = true; + Log.d(TAG, "showSoftKeyboard"); mInputMethodManagerWrapper.showSoftInput( mViewEmbedder.getAttachedView(), 0, mViewEmbedder.getNewShowKeyboardReceiver()); if (mViewEmbedder.getAttachedView().getResources().getConfiguration().keyboard @@ -244,14 +241,56 @@ } } - private void hideSoftKeyboard() { - Log.d(TAG, "hideSoftKeyboard"); - mIsShowWithoutHideOutstanding = false; + /** + * Hide soft keyboard. + */ + public void hideKeyboard() { + Log.d(TAG, "hideKeyboard"); View view = mViewEmbedder.getAttachedView(); if (mInputMethodManagerWrapper.isActive(view)) { - mInputMethodManagerWrapper.hideSoftInputFromWindow(view.getWindowToken(), 0, - mViewEmbedder.getNewShowKeyboardReceiver()); + // NOTE: we should not set ResultReceiver here. Otherwise, IMM will own ContentViewCore + // and ImeAdapter even after input method goes away and result gets received. + mInputMethodManagerWrapper.hideSoftInputFromWindow(view.getWindowToken(), 0, null); } + if (mTextInputType == TextInputType.NONE && mInputConnection != null) { + mInputConnection.restartInput(); + } + } + + /** + * Call this when keyboard configuration has changed. + */ + public void onKeyboardConfigurationChanged() { + Log.d(TAG, "onKeyboardConfigurationChanged: mTextInputType [%d]", mTextInputType); + if (mTextInputType != TextInputType.NONE) { + mInputMethodManagerWrapper.restartInput(mViewEmbedder.getAttachedView()); + // By default, we show soft keyboard on keyboard changes. This is useful + // when the user switches from hardware keyboard to software keyboard. + // TODO(changwan): check if we can skip this for hardware keyboard configurations. + showSoftKeyboard(); + } + } + + /** + * Call this when view's focus has changed. + * @param gainFocus True if we're gaining focus. + */ + public void onViewFocusChanged(boolean gainFocus) { + Log.d(TAG, "onViewFocusChanged: gainFocus [%b]", gainFocus); + if (!gainFocus) hideKeyboard(); + } + + /** + * @return Whether input can be shown on the current focus (e.g. on an input box + * or on a contenteditable). + */ + public boolean canCreateInputConnection() { + return mTextInputType != TextInputType.NONE; + } + + @VisibleForTesting + public void setInputTypeForTest(int textInputType) { + mTextInputType = textInputType; } private static boolean isTextInputType(int type) { @@ -400,7 +439,7 @@ @CalledByNative private void focusedNodeChanged(boolean isEditable) { - Log.d(TAG, "focusedNodeChanged"); + Log.d(TAG, "focusedNodeChanged: isEditable [%b]", isEditable); if (mTextInputType != TextInputType.NONE && mInputConnection != null && isEditable) { mInputConnection.restartInput(); }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreFocusTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreFocusTest.java index 5ae6b38..f2178a0 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreFocusTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreFocusTest.java
@@ -56,10 +56,10 @@ // view loses its focus final ContentViewCore contentViewCore = getContentViewCore(); final View view = contentViewCore.getContainerView(); - final TestInputMethodManagerWrapper immw = new TestInputMethodManagerWrapper(getActivity()); assertTrue(view.requestFocus()); - contentViewCore.setInputMethodManagerWrapperForTest(immw); + final TestInputMethodManagerWrapper immw = new TestInputMethodManagerWrapper(getActivity()); + contentViewCore.getImeAdapterForTest().setInputMethodManagerWrapperForTest(immw); immw.showSoftInput(view, 0, null); assertFalse(immw.isHidden());
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreInputConnectionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreInputConnectionTest.java index 5243610..d8d9f31 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreInputConnectionTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreInputConnectionTest.java
@@ -12,6 +12,7 @@ import org.chromium.content.browser.input.InputMethodManagerWrapper; import org.chromium.content.browser.test.util.TestInputMethodManagerWrapper; import org.chromium.content_shell_apk.ContentShellTestBase; +import org.chromium.ui.base.ime.TextInputType; /** * Tests that when InputConnection is recreated, the text is still retained. @@ -37,7 +38,7 @@ mContentViewCore = new ContentViewCore(getActivity()); mInputMethodManagerWrapper = new TestInputMethodManagerWrapper(mContentViewCore); mImeAdapter = new TestImeAdapter(mInputMethodManagerWrapper); - mImeAdapter.setInputMethodManagerWrapper(new TestInputMethodManagerWrapper( + mImeAdapter.setInputMethodManagerWrapperForTest(new TestInputMethodManagerWrapper( mContentViewCore)); mContentViewCore.setImeAdapterForTest(mImeAdapter); mContentViewCore.createContentViewAndroidDelegate(); @@ -53,6 +54,7 @@ public void testRecreateInputConnection() throws Exception { EditorInfo info = new EditorInfo(); + mImeAdapter.setInputTypeForTest(TextInputType.TEXT); mContentViewCore.onCreateInputConnection(info); AdapterInputConnection adapter = mContentViewCore.getAdapterInputConnectionForTest(); adapter.updateState("Is this text restored?", 0, 0, 0, 0, true);
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/PopupZoomerTest.java b/content/public/android/javatests/src/org/chromium/content/browser/PopupZoomerTest.java index 8ecc52e..ff3bbeb 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/PopupZoomerTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/PopupZoomerTest.java
@@ -14,6 +14,9 @@ import android.view.View; import org.chromium.base.test.util.Feature; +import org.chromium.content.browser.input.ImeAdapter; +import org.chromium.content.browser.input.TestImeAdapterDelegate; +import org.chromium.content.browser.test.util.TestInputMethodManagerWrapper; import org.chromium.content_shell_apk.ContentShellTestBase; /** @@ -78,6 +81,9 @@ mPopupZoomer = createPopupZoomerForTest(getInstrumentation().getTargetContext()); mContentViewCore = new ContentViewCore(getActivity()); mContentViewCore.setPopupZoomerForTest(mPopupZoomer); + mContentViewCore.setImeAdapterForTest(new ImeAdapter( + new TestInputMethodManagerWrapper(mContentViewCore), + new TestImeAdapterDelegate())); } @SmallTest
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/AdapterInputConnectionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/AdapterInputConnectionTest.java index cfeebd9..0694de03 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/input/AdapterInputConnectionTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/input/AdapterInputConnectionTest.java
@@ -36,8 +36,7 @@ launchContentShellWithUrl("about:blank"); assertTrue("Page failed to load", waitForActiveShellToBeDoneLoading()); mWrapper = new TestInputMethodManagerWrapper(getActivity()); - ImeAdapterDelegate delegate = new TestImeAdapterDelegate(); - mImeAdapter = new TestImeAdapter(mWrapper, delegate); + mImeAdapter = new TestImeAdapter(mWrapper, new TestImeAdapterDelegate()); mEditable = Editable.Factory.getInstance().newEditable(""); mConnection = new AdapterInputConnection( getContentViewCore().getContainerView(), mImeAdapter, mEditable, new EditorInfo()); @@ -158,29 +157,6 @@ } } - private static class TestImeAdapterDelegate implements ImeAdapterDelegate { - @Override - public void onImeEvent() {} - - @Override - public void onKeyboardBoundsUnchanged() {} - - @Override - public boolean performContextMenuAction(int id) { - return false; - } - - @Override - public View getAttachedView() { - return null; - } - - @Override - public ResultReceiver getNewShowKeyboardReceiver() { - return null; - } - } - private static void assertCorrectState(String text, int selectionStart, int selectionEnd, int compositionStart, int compositionEnd, ImeState actual) { assertEquals("Text did not match", text, actual.text);
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java index 46b28024..0e3fb0b 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
@@ -8,6 +8,7 @@ import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; +import android.content.res.Configuration; import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.SmallTest; import android.text.Editable; @@ -34,6 +35,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; /** @@ -73,7 +76,7 @@ mWebContents = getWebContents(); mInputMethodManagerWrapper = new TestInputMethodManagerWrapper(mContentViewCore); - getImeAdapter().setInputMethodManagerWrapper(mInputMethodManagerWrapper); + getImeAdapter().setInputMethodManagerWrapperForTest(mInputMethodManagerWrapper); assertEquals(0, mInputMethodManagerWrapper.getShowSoftInputCounter()); mConnectionFactory = new TestAdapterInputConnectionFactory(); mContentViewCore.setAdapterInputConnectionFactory(mConnectionFactory); @@ -122,7 +125,6 @@ performGo(mCallbackContainer); - waitAndVerifyStatesAndCalls(1, "", 0, 0, -1, -1); assertWaitForKeyboardStatus(false); } @@ -163,48 +165,41 @@ DOMUtils.clickNode(this, mContentViewCore, "input_radio"); assertWaitForKeyboardStatus(false); - waitAndVerifyStatesAndCalls(1, "", 0, 0, -1, -1); DOMUtils.clickNode(this, mContentViewCore, "input_text"); assertWaitForKeyboardStatus(true); - // The initial values will not be correct here because we call showSoftInput() - // before updating selection range. - assertEquals(0, mInputMethodManagerWrapper.getEditorInfo().initialSelStart); - assertEquals(0, mInputMethodManagerWrapper.getEditorInfo().initialSelEnd); - - // The values will immediately be updated. - waitAndVerifyStatesAndCalls(2, "hello", 5, 5, -1, -1); + assertEquals(5, mInputMethodManagerWrapper.getEditorInfo().initialSelStart); + assertEquals(5, mInputMethodManagerWrapper.getEditorInfo().initialSelEnd); } @SmallTest @Feature({"TextInput"}) public void testShowAndHideSoftInput() throws Exception { focusElement("input_radio", false); - waitAndVerifyStatesAndCalls(0, "", 0, 0, -1, -1); - // hideSoftKeyboard(). - waitForKeyboardStates(0, 1, 0, new Integer[] {}); + // hideSoftKeyboard(), restartInput() + waitForKeyboardStates(0, 1, 1, new Integer[] {}); // showSoftInput(), restartInput() focusElement("input_number1"); - waitForKeyboardStates(1, 1, 1, new Integer[] {TextInputType.NUMBER}); + waitForKeyboardStates(1, 1, 2, new Integer[] {TextInputType.NUMBER}); focusElement("input_number2"); // Hide should never be called here. Otherwise we will see a flicker. Restarted to // reset internal states to handle the new input form. - waitForKeyboardStates(2, 1, 2, new Integer[] {TextInputType.NUMBER, TextInputType.NUMBER}); + waitForKeyboardStates(2, 1, 3, new Integer[] {TextInputType.NUMBER, TextInputType.NUMBER}); focusElement("input_text"); // showSoftInput() on input_text. restartInput() on input_number1 due to focus change, // and restartInput() on input_text later. // TODO(changwan): reduce unnecessary restart input. - waitForKeyboardStates(3, 1, 4, new Integer[] {TextInputType.NUMBER, TextInputType.NUMBER, + waitForKeyboardStates(3, 1, 5, new Integer[] {TextInputType.NUMBER, TextInputType.NUMBER, TextInputType.NUMBER, TextInputType.TEXT}); focusElement("input_radio", false); - // hideSoftInput(). - waitForKeyboardStates(3, 2, 4, new Integer[] {TextInputType.NUMBER, TextInputType.NUMBER, + // hideSoftInput(), restartInput() + waitForKeyboardStates(3, 2, 6, new Integer[] {TextInputType.NUMBER, TextInputType.NUMBER, TextInputType.NUMBER, TextInputType.TEXT}); } @@ -227,11 +222,21 @@ } private String getKeyboardStates() { - int showCount = mInputMethodManagerWrapper.getShowSoftInputCounter(); - int hideCount = mInputMethodManagerWrapper.getHideSoftInputCounter(); - int restartCount = mInputMethodManagerWrapper.getRestartInputCounter(); - Integer[] history = mConnectionFactory.getTextInputTypeHistory(); - return stringifyKeyboardStates(showCount, hideCount, restartCount, history); + try { + return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() { + @Override + public String call() throws Exception { + int showCount = mInputMethodManagerWrapper.getShowSoftInputCounter(); + int hideCount = mInputMethodManagerWrapper.getHideSoftInputCounter(); + int restartCount = mInputMethodManagerWrapper.getRestartInputCounter(); + Integer[] history = mConnectionFactory.getTextInputTypeHistory(); + return stringifyKeyboardStates(showCount, hideCount, restartCount, history); + } + }); + } catch (ExecutionException e) { + e.printStackTrace(); + return null; + } } private String stringifyKeyboardStates(int show, int hide, int restart, Integer[] history) { @@ -332,6 +337,58 @@ })); } + private void attachPhysicalKeyboard() { + Configuration hardKeyboardConfig = + new Configuration(mContentViewCore.getContext().getResources().getConfiguration()); + hardKeyboardConfig.keyboard = Configuration.KEYBOARD_QWERTY; + hardKeyboardConfig.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES; + hardKeyboardConfig.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; + onConfigurationChanged(hardKeyboardConfig); + } + + private void detachPhysicalKeyboard() { + Configuration softKeyboardConfig = + new Configuration(mContentViewCore.getContext().getResources().getConfiguration()); + softKeyboardConfig.keyboard = Configuration.KEYBOARD_NOKEYS; + softKeyboardConfig.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; + softKeyboardConfig.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES; + onConfigurationChanged(softKeyboardConfig); + } + + private void onConfigurationChanged(final Configuration config) { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + mContentViewCore.onConfigurationChanged(config); + } + }); + } + + @SmallTest + @Feature({"TextInput"}) + public void testPhysicalKeyboard_AttachDetach() throws Exception { + attachPhysicalKeyboard(); + // We still call showSoftKeyboard, which will be ignored by physical keyboard. + waitForKeyboardStates(1, 0, 1, new Integer[] {TextInputType.TEXT}); + setComposingText("a", 1); + waitForKeyboardStates(1, 0, 1, new Integer[] {TextInputType.TEXT}); + detachPhysicalKeyboard(); + // Now we really show soft keyboard. We also call restartInput when configuration changes. + waitForKeyboardStates(2, 0, 2, new Integer[] {TextInputType.TEXT, TextInputType.TEXT}); + + // Reload the page, then the focus will be lost. + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + getActivity().getActiveShell().loadUrl(DATA_URL); + } + }); + + detachPhysicalKeyboard(); + // We should not show soft keyboard here because focus has been lost. + waitForKeyboardStates(2, 1, 2, new Integer[] {TextInputType.TEXT, TextInputType.TEXT}); + } + @SmallTest @Feature({"TextInput"}) public void testSelectActionBarClearedOnTappingInput() throws Exception { @@ -432,7 +489,6 @@ waitAndVerifyStatesAndCalls(1, "hello", 0, 5, -1, -1); unselect(); - waitAndVerifyStatesAndCalls(2, "", 0, 0, -1, -1); assertWaitForKeyboardStatus(false); }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/TestImeAdapterDelegate.java b/content/public/android/javatests/src/org/chromium/content/browser/input/TestImeAdapterDelegate.java new file mode 100644 index 0000000..f59a101 --- /dev/null +++ b/content/public/android/javatests/src/org/chromium/content/browser/input/TestImeAdapterDelegate.java
@@ -0,0 +1,36 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.content.browser.input; + +import android.os.ResultReceiver; +import android.view.View; + +import org.chromium.content.browser.input.ImeAdapter.ImeAdapterDelegate; + +/** + * An empty ImeAdapterDelegate used for testing. + */ +public class TestImeAdapterDelegate implements ImeAdapterDelegate { + @Override + public void onImeEvent() {} + + @Override + public void onKeyboardBoundsUnchanged() {} + + @Override + public boolean performContextMenuAction(int id) { + return false; + } + + @Override + public View getAttachedView() { + return null; + } + + @Override + public ResultReceiver getNewShowKeyboardReceiver() { + return null; + } +} \ No newline at end of file
diff --git a/content/public/browser/service_worker_context.h b/content/public/browser/service_worker_context.h index 843704d..bac9ab6 100644 --- a/content/public/browser/service_worker_context.h +++ b/content/public/browser/service_worker_context.h
@@ -70,9 +70,9 @@ virtual void DeleteForOrigin(const GURL& origin_url, const ResultCallback& callback) = 0; - // Returns true if an active Service Worker registration exists that matches - // |url|, and if |other_url| falls inside the scope of the same registration. - // Note this still returns true even if there is a Service Worker registration + // Returns true if a Service Worker registration exists that matches |url|, + // and if |other_url| falls inside the scope of the same registration. Note + // this still returns true even if there is a Service Worker registration // which has a longer match for |other_url|. // This function can be called from any thread, but the callback will always // be called on the UI thread.
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index 74ac83c..44acc091 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc
@@ -343,6 +343,10 @@ // Enables TRACE for GL calls in the renderer. const char kEnableGpuClientTracing[] = "enable-gpu-client-tracing"; +// Specify that all compositor resources should be backed by GPU memory buffers. +const char kEnableGpuMemoryBufferCompositorResources[] = + "enable-gpu-memory-buffer-compositor-resources"; + // Enable GpuMemoryBuffer backed VideoFrames. const char kEnableGpuMemoryBufferVideoFrames[] = "enable-gpu-memory-buffer-video-frames"; @@ -592,8 +596,9 @@ // Disables the sandbox for all process types that are normally sandboxed. const char kNoSandbox[] = "no-sandbox"; -// Enables appcontainer/lowbox for renderer on Win8+ platforms. +// Enable or disable appcontainer/lowbox for renderer on Win8+ platforms. const char kEnableAppContainer[] = "enable-appcontainer"; +const char kDisableAppContainer[] = "disable-appcontainer"; // Number of worker threads used to rasterize content. const char kNumRasterThreads[] = "num-raster-threads";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index 66b4cc5..079cab7d 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h
@@ -107,6 +107,7 @@ CONTENT_EXPORT extern const char kEnableFeatures[]; CONTENT_EXPORT extern const char kEnableWebBluetooth[]; extern const char kEnableGpuClientTracing[]; +CONTENT_EXPORT extern const char kEnableGpuMemoryBufferCompositorResources[]; CONTENT_EXPORT extern const char kEnableGpuMemoryBufferVideoFrames[]; CONTENT_EXPORT extern const char kEnableGpuRasterization[]; CONTENT_EXPORT extern const char kGpuRasterizationMSAASampleCount[]; @@ -178,6 +179,7 @@ CONTENT_EXPORT extern const char kNoReferrers[]; CONTENT_EXPORT extern const char kNoSandbox[]; CONTENT_EXPORT extern const char kEnableAppContainer[]; +CONTENT_EXPORT extern const char kDisableAppContainer[]; CONTENT_EXPORT extern const char kNumRasterThreads[]; CONTENT_EXPORT extern const char kOverridePluginPowerSaverForTesting[]; CONTENT_EXPORT extern const char kOverscrollHistoryNavigation[];
diff --git a/content/public/common/file_chooser_params.h b/content/public/common/file_chooser_params.h index ad612ab..cb9d934 100644 --- a/content/public/common/file_chooser_params.h +++ b/content/public/common/file_chooser_params.h
@@ -10,6 +10,7 @@ #include "base/files/file_path.h" #include "base/strings/string16.h" #include "content/common/content_export.h" +#include "url/gurl.h" namespace content { @@ -54,6 +55,11 @@ // If true, the data should be obtained using the device's camera/mic/etc. bool capture; #endif + + // If non-empty, represents the URL of the requestor if the request was + // initiated by a document. Note that this value should be considered + // untrustworthy since it is specified by the sandbox and not validated. + GURL requestor; }; } // namespace content
diff --git a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestInputMethodManagerWrapper.java b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestInputMethodManagerWrapper.java index 20ad2219..b604f87 100644 --- a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestInputMethodManagerWrapper.java +++ b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestInputMethodManagerWrapper.java
@@ -10,6 +10,7 @@ import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; +import org.chromium.base.Log; import org.chromium.content.browser.ContentViewCore; import org.chromium.content.browser.input.InputMethodManagerWrapper; @@ -17,6 +18,8 @@ * Overrides InputMethodManagerWrapper for testing purposes. */ public class TestInputMethodManagerWrapper extends InputMethodManagerWrapper { + private static final String TAG = "cr_Ime"; + /** * A simple class to set start and end in int type. */ @@ -75,12 +78,14 @@ public TestInputMethodManagerWrapper(ContentViewCore contentViewCore) { super(null); + Log.d(TAG, "TestInputMethodManagerWrapper constructor"); mContentViewCore = contentViewCore; } @Override public void restartInput(View view) { mRestartInputCounter++; + Log.d(TAG, "restartInput: count [%d]", mRestartInputCounter); mEditorInfo = new EditorInfo(); mInputConnection = mContentViewCore.onCreateInputConnection(mEditorInfo); } @@ -89,6 +94,7 @@ public void showSoftInput(View view, int flags, ResultReceiver resultReceiver) { mIsShowWithoutHideOutstanding = true; mShowSoftInputCounter++; + Log.d(TAG, "showSoftInput: count [%d]", mShowSoftInputCounter); if (mInputConnection != null) return; mEditorInfo = new EditorInfo(); mInputConnection = mContentViewCore.onCreateInputConnection(mEditorInfo); @@ -96,8 +102,9 @@ @Override public boolean isActive(View view) { - if (mInputConnection == null) return false; - return true; + boolean result = mInputConnection != null; + Log.d(TAG, "isActive: returns [%b]", result); + return result; } @Override @@ -105,6 +112,7 @@ ResultReceiver resultReceiver) { mIsShowWithoutHideOutstanding = false; mHideSoftInputCounter++; + Log.d(TAG, "hideSoftInputFromWindow: count [%d]", mHideSoftInputCounter); boolean retVal = mInputConnection == null; mInputConnection = null; return retVal; @@ -113,6 +121,7 @@ @Override public void updateSelection(View view, int selStart, int selEnd, int candidatesStart, int candidatesEnd) { + Log.d(TAG, "updateSelection"); mUpdateSelectionCounter++; mSelection.set(selStart, selEnd); mComposition.set(candidatesStart, candidatesEnd); @@ -123,6 +132,7 @@ } public int getShowSoftInputCounter() { + Log.d(TAG, "getShowSoftInputCounter: %d", mShowSoftInputCounter); return mShowSoftInputCounter; } @@ -135,6 +145,7 @@ } public void resetCounters() { + Log.d(TAG, "resetCounters"); mRestartInputCounter = 0; mShowSoftInputCounter = 0; mHideSoftInputCounter = 0;
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 0848458..73d0b77 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -809,8 +809,7 @@ runner->Run(); } -void SetupCrossSiteRedirector( - net::test_server::EmbeddedTestServer* embedded_test_server) { +void SetupCrossSiteRedirector(net::EmbeddedTestServer* embedded_test_server) { embedded_test_server->RegisterRequestHandler( base::Bind(&CrossSiteRedirectResponseHandler, embedded_test_server->base_url()));
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h index 31841937..f18d4e9 100644 --- a/content/public/test/browser_test_utils.h +++ b/content/public/test/browser_test_utils.h
@@ -37,6 +37,9 @@ namespace test_server { class EmbeddedTestServer; } +// TODO(svaldez): Remove typedef once EmbeddedTestServer has been migrated +// out of net::test_server. +using test_server::EmbeddedTestServer; } // A collections of functions designed for use with content_browsertests and @@ -248,8 +251,7 @@ // "/cross-site/hostname/rest/of/path" to redirect the request to // "<scheme>://hostname:<port>/rest/of/path", where <scheme> and <port> // are the values for the instance of EmbeddedTestServer. -void SetupCrossSiteRedirector( - net::test_server::EmbeddedTestServer* embedded_test_server); +void SetupCrossSiteRedirector(net::EmbeddedTestServer* embedded_test_server); // Waits for an interstitial page to attach to given web contents. void WaitForInterstitialAttach(content::WebContents* web_contents);
diff --git a/content/renderer/browser_render_view_browsertest.cc b/content/renderer/browser_render_view_browsertest.cc index 123b238..9d878a9 100644 --- a/content/renderer/browser_render_view_browsertest.cc +++ b/content/renderer/browser_render_view_browsertest.cc
@@ -194,10 +194,10 @@ }; IN_PROC_BROWSER_TEST_F(RenderViewBrowserTest, ConfirmCacheInformationPlumbed) { - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(embedded_test_server()->Start()); // Load URL with "nocache" set, to create stale cache. - GURL test_url(test_server()->GetURL("files/nocache.html")); + GURL test_url(embedded_test_server()->GetURL("/nocache.html")); NavigateToURLAndWaitForTitle(test_url, "Nocache Test Page", 1); // Reload same URL after forcing an error from the the network layer;
diff --git a/content/renderer/child_frame_compositing_helper.h b/content/renderer/child_frame_compositing_helper.h index ffd34be3..d674503d 100644 --- a/content/renderer/child_frame_compositing_helper.h +++ b/content/renderer/child_frame_compositing_helper.h
@@ -44,7 +44,6 @@ } struct FrameHostMsg_CompositorFrameSwappedACK_Params; -struct FrameHostMsg_BuffersSwappedACK_Params; struct FrameHostMsg_ReclaimCompositorResources_Params; namespace content {
diff --git a/content/renderer/gpu/compositor_dependencies.h b/content/renderer/gpu/compositor_dependencies.h index 6647fa123..fd46a11 100644 --- a/content/renderer/gpu/compositor_dependencies.h +++ b/content/renderer/gpu/compositor_dependencies.h
@@ -40,6 +40,7 @@ virtual bool IsDistanceFieldTextEnabled() = 0; virtual bool IsZeroCopyEnabled() = 0; virtual bool IsPartialRasterEnabled() = 0; + virtual bool IsGpuMemoryBufferCompositorResourcesEnabled() = 0; virtual bool IsElasticOverscrollEnabled() = 0; virtual std::vector<unsigned> GetImageTextureTargets() = 0; virtual scoped_refptr<base::SingleThreadTaskRunner>
diff --git a/content/renderer/gpu/mailbox_output_surface.cc b/content/renderer/gpu/mailbox_output_surface.cc index a536f99..127f7e8 100644 --- a/content/renderer/gpu/mailbox_output_surface.cc +++ b/content/renderer/gpu/mailbox_output_surface.cc
@@ -68,8 +68,8 @@ TransferableFrame& texture = returned_textures_.front(); if (texture.size == surface_size_) { current_backing_ = texture; - if (current_backing_.sync_point) - gl->WaitSyncPointCHROMIUM(current_backing_.sync_point); + if (current_backing_.sync_token.HasData()) + gl->WaitSyncTokenCHROMIUM(current_backing_.sync_token.GetConstData()); returned_textures_.pop(); break; } @@ -173,7 +173,7 @@ } } DCHECK(it != pending_textures_.end()); - it->sync_point = ack.gl_frame_data->sync_point; + it->sync_token = ack.gl_frame_data->sync_token; if (!is_backbuffer_discarded_) { returned_textures_.push(*it); @@ -206,8 +206,8 @@ frame->gl_frame_data->mailbox = current_backing_.mailbox; context_provider_->ContextGL()->Flush(); - frame->gl_frame_data->sync_point = - context_provider_->ContextGL()->InsertSyncPointCHROMIUM(); + frame->gl_frame_data->sync_token = + gpu::SyncToken(context_provider_->ContextGL()->InsertSyncPointCHROMIUM()); CompositorOutputSurface::SwapBuffers(frame); pending_textures_.push_back(current_backing_); @@ -219,4 +219,12 @@ return pending_textures_.size() - 1; } +MailboxOutputSurface::TransferableFrame::TransferableFrame() : texture_id(0) {} + +MailboxOutputSurface::TransferableFrame::TransferableFrame( + uint32 texture_id, + const gpu::Mailbox& mailbox, + const gfx::Size size) + : texture_id(texture_id), mailbox(mailbox), size(size) {} + } // namespace content
diff --git a/content/renderer/gpu/mailbox_output_surface.h b/content/renderer/gpu/mailbox_output_surface.h index fc789c48..a812934d 100644 --- a/content/renderer/gpu/mailbox_output_surface.h +++ b/content/renderer/gpu/mailbox_output_surface.h
@@ -52,17 +52,15 @@ size_t GetNumAcksPending(); struct TransferableFrame { - TransferableFrame() : texture_id(0), sync_point(0) {} - + TransferableFrame(); TransferableFrame(uint32 texture_id, const gpu::Mailbox& mailbox, - const gfx::Size size) - : texture_id(texture_id), mailbox(mailbox), size(size), sync_point(0) {} + const gfx::Size size); uint32 texture_id; gpu::Mailbox mailbox; + gpu::SyncToken sync_token; gfx::Size size; - uint32 sync_point; }; TransferableFrame current_backing_;
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index e5f6e5d6..f7ac509 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -300,6 +300,8 @@ settings.use_partial_raster = compositor_deps_->IsPartialRasterEnabled(); settings.enable_elastic_overscroll = compositor_deps_->IsElasticOverscrollEnabled(); + settings.renderer_settings.use_gpu_memory_buffer_resources = + compositor_deps_->IsGpuMemoryBufferCompositorResourcesEnabled(); settings.use_image_texture_targets = compositor_deps_->GetImageTextureTargets(); settings.image_decode_tasks_enabled =
diff --git a/content/renderer/media/android/webmediaplayer_android.cc b/content/renderer/media/android/webmediaplayer_android.cc index 4e6db86..e732515 100644 --- a/content/renderer/media/android/webmediaplayer_android.cc +++ b/content/renderer/media/android/webmediaplayer_android.cc
@@ -87,9 +87,9 @@ void OnReleaseTexture( const scoped_refptr<content::StreamTextureFactory>& factories, uint32 texture_id, - uint32 release_sync_point) { + const gpu::SyncToken& sync_token) { GLES2Interface* gl = factories->ContextGL(); - gl->WaitSyncPointCHROMIUM(release_sync_point); + gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); gl->DeleteTextures(1, &texture_id); // Flush to ensure that the stream texture gets deleted in a timely fashion. gl->ShallowFlushCHROMIUM(); @@ -130,17 +130,20 @@ return true; } -class SyncPointClientImpl : public media::VideoFrame::SyncPointClient { +class SyncTokenClientImpl : public media::VideoFrame::SyncTokenClient { public: - explicit SyncPointClientImpl( + explicit SyncTokenClientImpl( blink::WebGraphicsContext3D* web_graphics_context) : web_graphics_context_(web_graphics_context) {} - ~SyncPointClientImpl() override {} + ~SyncTokenClientImpl() override {} uint32 InsertSyncPoint() override { - return web_graphics_context_->insertSyncPoint(); + gpu::SyncToken sync_token; + if (!web_graphics_context_->insertSyncPoint(sync_token.GetData())) + return 0; + return static_cast<uint32>(sync_token.release_count()); } - void WaitSyncPoint(uint32 sync_point) override { - web_graphics_context_->waitSyncPoint(sync_point); + void WaitSyncToken(const gpu::SyncToken& sync_token) override { + web_graphics_context_->waitSyncToken(sync_token.GetConstData()); } private: @@ -684,7 +687,7 @@ mailbox_holder.texture_target == GL_TEXTURE_EXTERNAL_OES) || (is_remote_ && mailbox_holder.texture_target == GL_TEXTURE_2D)); - web_graphics_context->waitSyncPoint(mailbox_holder.sync_point); + web_graphics_context->waitSyncToken(mailbox_holder.sync_token.GetConstData()); // Ensure the target of texture is set before copyTextureCHROMIUM, otherwise // an invalid texture target may be used for copy texture. @@ -703,8 +706,8 @@ web_graphics_context->deleteTexture(src_texture); web_graphics_context->flush(); - SyncPointClientImpl client(web_graphics_context); - video_frame->UpdateReleaseSyncPoint(&client); + SyncTokenClientImpl client(web_graphics_context); + video_frame->UpdateReleaseSyncToken(&client); return true; } @@ -1228,12 +1231,12 @@ gl->GenMailboxCHROMIUM(texture_mailbox.name); gl->ProduceTextureCHROMIUM(texture_target, texture_mailbox.name); gl->Flush(); - GLuint texture_mailbox_sync_point = gl->InsertSyncPointCHROMIUM(); + gpu::SyncToken texture_mailbox_sync_token(gl->InsertSyncPointCHROMIUM()); scoped_refptr<VideoFrame> new_frame = VideoFrame::WrapNativeTexture( media::PIXEL_FORMAT_ARGB, - gpu::MailboxHolder(texture_mailbox, texture_target, - texture_mailbox_sync_point), + gpu::MailboxHolder(texture_mailbox, texture_mailbox_sync_token, + texture_target), media::BindToCurrentLoop(base::Bind(&OnReleaseTexture, stream_texture_factory_, remote_playback_texture_id)), @@ -1266,12 +1269,12 @@ GLuint texture_id_ref = gl->CreateAndConsumeTextureCHROMIUM( texture_target, texture_mailbox_.name); gl->Flush(); - GLuint texture_mailbox_sync_point = gl->InsertSyncPointCHROMIUM(); + gpu::SyncToken texture_mailbox_sync_token(gl->InsertSyncPointCHROMIUM()); scoped_refptr<VideoFrame> new_frame = VideoFrame::WrapNativeTexture( media::PIXEL_FORMAT_ARGB, - gpu::MailboxHolder(texture_mailbox_, texture_target, - texture_mailbox_sync_point), + gpu::MailboxHolder(texture_mailbox_, texture_mailbox_sync_token, + texture_target), media::BindToCurrentLoop(base::Bind( &OnReleaseTexture, stream_texture_factory_, texture_id_ref)), natural_size_, gfx::Rect(natural_size_), natural_size_,
diff --git a/content/renderer/media/media_stream_audio_processor.cc b/content/renderer/media/media_stream_audio_processor.cc index ed94baa3..18f7bed 100644 --- a/content/renderer/media/media_stream_audio_processor.cc +++ b/content/renderer/media/media_stream_audio_processor.cc
@@ -470,10 +470,10 @@ // Experimental options provided at creation. webrtc::Config config; - if (goog_experimental_aec) - config.Set<webrtc::ExtendedFilter>(new webrtc::ExtendedFilter(true)); - if (goog_experimental_ns) - config.Set<webrtc::ExperimentalNs>(new webrtc::ExperimentalNs(true)); + config.Set<webrtc::ExtendedFilter>( + new webrtc::ExtendedFilter(goog_experimental_aec)); + config.Set<webrtc::ExperimentalNs>( + new webrtc::ExperimentalNs(goog_experimental_ns)); if (IsDelayAgnosticAecEnabled()) config.Set<webrtc::DelayAgnostic>(new webrtc::DelayAgnostic(true)); if (goog_beamforming) {
diff --git a/content/renderer/media/media_stream_audio_processor_options.cc b/content/renderer/media/media_stream_audio_processor_options.cc index 911f196..778676e 100644 --- a/content/renderer/media/media_stream_audio_processor_options.cc +++ b/content/renderer/media/media_stream_audio_processor_options.cc
@@ -64,7 +64,7 @@ { MediaAudioConstraints::kGoogNoiseSuppression, true }, { MediaAudioConstraints::kGoogHighpassFilter, true }, { MediaAudioConstraints::kGoogTypingNoiseDetection, true }, - { MediaAudioConstraints::kGoogExperimentalNoiseSuppression, false }, + { MediaAudioConstraints::kGoogExperimentalNoiseSuppression, true }, // Beamforming will only be enabled if we are also provided with a // multi-microphone geometry. { MediaAudioConstraints::kGoogBeamforming, true },
diff --git a/content/renderer/media/renderer_gpu_video_accelerator_factories.cc b/content/renderer/media/renderer_gpu_video_accelerator_factories.cc index 5cd32b8..62e90878 100644 --- a/content/renderer/media/renderer_gpu_video_accelerator_factories.cc +++ b/content/renderer/media/renderer_gpu_video_accelerator_factories.cc
@@ -164,16 +164,17 @@ DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); } -void RendererGpuVideoAcceleratorFactories::WaitSyncPoint(uint32 sync_point) { +void RendererGpuVideoAcceleratorFactories::WaitSyncToken( + const gpu::SyncToken& sync_token) { DCHECK(task_runner_->BelongsToCurrentThread()); if (CheckContextLost()) return; cc::ContextProvider::ScopedContextLock lock(context_provider_); gpu::gles2::GLES2Interface* gles2 = lock.ContextGL(); - gles2->WaitSyncPointCHROMIUM(sync_point); + gles2->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); - // Callers expect the WaitSyncPoint to affect the next IPCs. Make sure to + // Callers expect the WaitSyncToken to affect the next IPCs. Make sure to // flush the command buffers to ensure that. gles2->ShallowFlushCHROMIUM(); }
diff --git a/content/renderer/media/renderer_gpu_video_accelerator_factories.h b/content/renderer/media/renderer_gpu_video_accelerator_factories.h index 5efad49..dea8c20 100644 --- a/content/renderer/media/renderer_gpu_video_accelerator_factories.h +++ b/content/renderer/media/renderer_gpu_video_accelerator_factories.h
@@ -66,7 +66,7 @@ std::vector<gpu::Mailbox>* texture_mailboxes, uint32 texture_target) override; void DeleteTexture(uint32 texture_id) override; - void WaitSyncPoint(uint32 sync_point) override; + void WaitSyncToken(const gpu::SyncToken& sync_token) override; scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer( const gfx::Size& size,
diff --git a/content/renderer/media/rtc_video_decoder.cc b/content/renderer/media/rtc_video_decoder.cc index c9a403a..a9d1af5 100644 --- a/content/renderer/media/rtc_video_decoder.cc +++ b/content/renderer/media/rtc_video_decoder.cc
@@ -419,7 +419,8 @@ // correct format is used and everyone down the line understands it. scoped_refptr<media::VideoFrame> frame(media::VideoFrame::WrapNativeTexture( media::PIXEL_FORMAT_ARGB, - gpu::MailboxHolder(pb.texture_mailbox(), decoder_texture_target_, 0), + gpu::MailboxHolder(pb.texture_mailbox(), gpu::SyncToken(), + decoder_texture_target_), media::BindToCurrentLoop(base::Bind( &RTCVideoDecoder::ReleaseMailbox, weak_factory_.GetWeakPtr(), factories_, picture.picture_buffer_id(), pb.texture_id())), @@ -624,9 +625,9 @@ media::GpuVideoAcceleratorFactories* factories, int64 picture_buffer_id, uint32 texture_id, - uint32 release_sync_point) { + const gpu::SyncToken& release_sync_token) { DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread()); - factories->WaitSyncPoint(release_sync_point); + factories->WaitSyncToken(release_sync_token); if (decoder) { decoder->ReusePictureBuffer(picture_buffer_id);
diff --git a/content/renderer/media/rtc_video_decoder.h b/content/renderer/media/rtc_video_decoder.h index bf04df8..813aabe 100644 --- a/content/renderer/media/rtc_video_decoder.h +++ b/content/renderer/media/rtc_video_decoder.h
@@ -33,6 +33,10 @@ class GpuVideoAcceleratorFactories; } +namespace gpu { +struct SyncToken; +} + namespace content { // This class uses hardware accelerated video decoder to decode video for @@ -146,7 +150,7 @@ media::GpuVideoAcceleratorFactories* factories, int64 picture_buffer_id, uint32 texture_id, - uint32 release_sync_point); + const gpu::SyncToken& release_sync_token); // Tells VDA that a picture buffer can be recycled. void ReusePictureBuffer(int64 picture_buffer_id);
diff --git a/content/renderer/media/video_capture_impl.cc b/content/renderer/media/video_capture_impl.cc index 8036ca1..174344d 100644 --- a/content/renderer/media/video_capture_impl.cc +++ b/content/renderer/media/video_capture_impl.cc
@@ -27,12 +27,13 @@ // This is called on an unknown thread when the VideoFrame destructor executes. // As of this writing, this callback mechanism is the only interface in -// VideoFrame to provide the final value for |release_sync_point|. +// VideoFrame to provide the final value for |release_sync_token|. // VideoCaptureImpl::DidFinishConsumingFrame() will read the value saved here, // and pass it back to the IO thread to pass back to the host via the // BufferReady IPC. -void SaveReleaseSyncPoint(uint32* storage, uint32 release_sync_point) { - *storage = release_sync_point; +void SaveReleaseSyncToken(gpu::SyncToken* sync_token_storage, + const gpu::SyncToken& release_sync_token) { + *sync_token_storage = release_sync_token; } } // namespace @@ -315,7 +316,8 @@ const gpu::MailboxHolder& mailbox_holder) { DCHECK(io_task_runner_->BelongsToCurrentThread()); if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) { - Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id, 0, -1.0)); + Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id, + gpu::SyncToken(), -1.0)); return; } if (first_frame_timestamp_.is_null()) @@ -328,8 +330,8 @@ (timestamp - first_frame_timestamp_).ToInternalValue()); scoped_refptr<media::VideoFrame> frame; - base::Callback<void(uint32, double)> buffer_finished_callback; - uint32* release_sync_point_storage = new uint32(0); + BufferFinishedCallback buffer_finished_callback; + scoped_ptr<gpu::SyncToken> release_sync_token(new gpu::SyncToken); if (storage_type == media::VideoFrame::STORAGE_GPU_MEMORY_BUFFERS) { DCHECK_EQ(media::PIXEL_FORMAT_I420, pixel_format); const auto& iter = client_buffer2s_.find(buffer_id); @@ -378,12 +380,9 @@ DCHECK(mailbox_holder.mailbox.Verify()); DCHECK_EQ(media::PIXEL_FORMAT_ARGB, pixel_format); frame = media::VideoFrame::WrapNativeTexture( - pixel_format, - mailbox_holder, - base::Bind(&SaveReleaseSyncPoint, release_sync_point_storage), - coded_size, - gfx::Rect(coded_size), - coded_size, + pixel_format, mailbox_holder, + base::Bind(&SaveReleaseSyncToken, release_sync_token.get()), + coded_size, gfx::Rect(coded_size), coded_size, timestamp - first_frame_timestamp_); } buffer_finished_callback = media::BindToCurrentLoop( @@ -394,7 +393,7 @@ timestamp); frame->AddDestructionObserver( base::Bind(&VideoCaptureImpl::DidFinishConsumingFrame, frame->metadata(), - release_sync_point_storage, buffer_finished_callback)); + base::Passed(&release_sync_token), buffer_finished_callback)); frame->metadata()->MergeInternalValuesFrom(metadata); @@ -405,20 +404,20 @@ void VideoCaptureImpl::OnClientBufferFinished( int buffer_id, const scoped_refptr<ClientBuffer>& /* ignored_buffer */, - uint32 release_sync_point, + const gpu::SyncToken& release_sync_token, double consumer_resource_utilization) { DCHECK(io_task_runner_->BelongsToCurrentThread()); Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id, - release_sync_point, + release_sync_token, consumer_resource_utilization)); } void VideoCaptureImpl::OnClientBufferFinished2( int buffer_id, const scoped_refptr<ClientBuffer2>& gpu_memory_buffer /* ignored_buffer */, - uint32 release_sync_point, + const gpu::SyncToken& release_sync_token, double consumer_resource_utilization) { OnClientBufferFinished(buffer_id, scoped_refptr<ClientBuffer>(), - release_sync_point, consumer_resource_utilization); + release_sync_token, consumer_resource_utilization); } void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) { @@ -554,24 +553,17 @@ // static void VideoCaptureImpl::DidFinishConsumingFrame( const media::VideoFrameMetadata* metadata, - uint32* release_sync_point_storage, - const base::Callback<void(uint32, double)>& callback_to_io_thread) { + scoped_ptr<gpu::SyncToken> release_sync_token, + const BufferFinishedCallback& callback_to_io_thread) { // Note: This function may be called on any thread by the VideoFrame // destructor. |metadata| is still valid for read-access at this point. - - uint32 release_sync_point = 0u; - if (release_sync_point_storage) { - release_sync_point = *release_sync_point_storage; - delete release_sync_point_storage; - } - double consumer_resource_utilization = -1.0; if (!metadata->GetDouble(media::VideoFrameMetadata::RESOURCE_UTILIZATION, &consumer_resource_utilization)) { consumer_resource_utilization = -1.0; } - callback_to_io_thread.Run(release_sync_point, consumer_resource_utilization); + callback_to_io_thread.Run(*release_sync_token, consumer_resource_utilization); } } // namespace content
diff --git a/content/renderer/media/video_capture_impl.h b/content/renderer/media/video_capture_impl.h index 8918b6f4..05631176 100644 --- a/content/renderer/media/video_capture_impl.h +++ b/content/renderer/media/video_capture_impl.h
@@ -104,6 +104,10 @@ }; typedef std::map<int, ClientInfo> ClientInfoMap; + typedef base::Callback<void(const gpu::SyncToken& sync_token, + double consumer_resource_utilization)> + BufferFinishedCallback; + // VideoCaptureMessageFilter::Delegate interface. void OnBufferCreated(base::SharedMemoryHandle handle, int length, @@ -130,16 +134,14 @@ // Sends an IPC message to browser process when all clients are done with the // buffer. - void OnClientBufferFinished( - int buffer_id, - const scoped_refptr<ClientBuffer>& buffer, - uint32 release_sync_point, - double consumer_resource_utilization); - void OnClientBufferFinished2( - int buffer_id, - const scoped_refptr<ClientBuffer2>& buffer, - uint32 release_sync_point, - double consumer_resource_utilization); + void OnClientBufferFinished(int buffer_id, + const scoped_refptr<ClientBuffer>& buffer, + const gpu::SyncToken& release_sync_token, + double consumer_resource_utilization); + void OnClientBufferFinished2(int buffer_id, + const scoped_refptr<ClientBuffer2>& buffer, + const gpu::SyncToken& release_sync_token, + double consumer_resource_utilization); void StopDevice(); void RestartCapture(); @@ -155,9 +157,9 @@ // RESOURCE_UTILIZATION value from the |metadata| and then runs the given // callback, to trampoline back to the IO thread with the values. static void DidFinishConsumingFrame( - const media::VideoFrameMetadata* metadata, - uint32* release_sync_point_storage, // Takes ownership. - const base::Callback<void(uint32, double)>& callback_to_io_thread); + const media::VideoFrameMetadata* metadata, + scoped_ptr<gpu::SyncToken> release_sync_token, + const BufferFinishedCallback& callback_to_io_thread); const scoped_refptr<VideoCaptureMessageFilter> message_filter_; int device_id_;
diff --git a/content/renderer/media/video_capture_impl_unittest.cc b/content/renderer/media/video_capture_impl_unittest.cc index 795b1e6e6..261aa5b 100644 --- a/content/renderer/media/video_capture_impl_unittest.cc +++ b/content/renderer/media/video_capture_impl_unittest.cc
@@ -47,8 +47,9 @@ static const BufferReceivedTestArg kBufferFormats[] = { BufferReceivedTestArg(media::PIXEL_FORMAT_I420), - BufferReceivedTestArg(media::PIXEL_FORMAT_ARGB, - gpu::MailboxHolder(gpu::Mailbox::Generate(), 0, 0))}; + BufferReceivedTestArg( + media::PIXEL_FORMAT_ARGB, + gpu::MailboxHolder(gpu::Mailbox::Generate(), gpu::SyncToken(), 0))}; class VideoCaptureImplTest : public ::testing::TestWithParam<BufferReceivedTestArg> { @@ -98,7 +99,7 @@ void DeviceReceiveEmptyBuffer(int device_id, int buffer_id, - uint32 sync_point, + const gpu::SyncToken& release_sync_token, double consumer_resource_utilization) { received_buffer_count_++; }
diff --git a/content/renderer/media/video_capture_message_filter.cc b/content/renderer/media/video_capture_message_filter.cc index 9b4c81c..a75e3694 100644 --- a/content/renderer/media/video_capture_message_filter.cc +++ b/content/renderer/media/video_capture_message_filter.cc
@@ -113,7 +113,7 @@ base::SharedMemory::CloseHandle(handle); Send(new VideoCaptureHostMsg_BufferReady( - device_id, buffer_id, 0 /* release_sync_point */, + device_id, buffer_id, gpu::SyncToken() /* release_sync_token */, -1.0 /* consumer_resource_utilization */)); return; } @@ -131,7 +131,7 @@ DLOG(WARNING) << "OnBufferCreated: Got video GMB buffer for a " "non-existent or removed video capture."; Send(new VideoCaptureHostMsg_BufferReady( - device_id, buffer_id, 0 /* release_sync_point */, + device_id, buffer_id, gpu::SyncToken() /* release_sync_token */, -1.0 /* consumer_resource_utilization */)); return; } @@ -148,8 +148,8 @@ // Send the buffer back to Host in case it's waiting for all buffers // to be returned. - Send(new VideoCaptureHostMsg_BufferReady( - params.device_id, params.buffer_id, 0, -1.0)); + Send(new VideoCaptureHostMsg_BufferReady(params.device_id, params.buffer_id, + gpu::SyncToken(), -1.0)); return; }
diff --git a/content/renderer/media/video_capture_message_filter_unittest.cc b/content/renderer/media/video_capture_message_filter_unittest.cc index 6738545f..c36f3d3 100644 --- a/content/renderer/media/video_capture_message_filter_unittest.cc +++ b/content/renderer/media/video_capture_message_filter_unittest.cc
@@ -136,7 +136,8 @@ params_m.pixel_format = media::PIXEL_FORMAT_ARGB; params_m.storage_type = media::VideoFrame::STORAGE_OPAQUE; params_m.coded_size = gfx::Size(345, 256); - params_m.mailbox_holder = gpu::MailboxHolder(gpu::Mailbox::Generate(), 0, 44); + params_m.mailbox_holder = + gpu::MailboxHolder(gpu::Mailbox::Generate(), gpu::SyncToken(), 44); gpu::MailboxHolder received_mailbox_holder; EXPECT_CALL(delegate, OnBufferReceived(params_m.buffer_id, params_m.timestamp,
diff --git a/content/renderer/pepper/pepper_compositor_host.cc b/content/renderer/pepper/pepper_compositor_host.cc index e8343ee3..31d9b6d 100644 --- a/content/renderer/pepper/pepper_compositor_host.cc +++ b/content/renderer/pepper/pepper_compositor_host.cc
@@ -189,19 +189,19 @@ int32_t id, scoped_ptr<base::SharedMemory> shared_memory, scoped_ptr<cc::SharedBitmap> bitmap, - uint32_t sync_point, + const gpu::SyncToken& sync_token, bool is_lost) { bitmap.reset(); shared_memory.reset(); - ResourceReleased(id, sync_point, is_lost); + ResourceReleased(id, sync_token, is_lost); } void PepperCompositorHost::ResourceReleased(int32_t id, - uint32_t sync_point, + const gpu::SyncToken& sync_token, bool is_lost) { host()->SendUnsolicitedReply( pp_resource(), - PpapiPluginMsg_Compositor_ReleaseResource(id, sync_point, is_lost)); + PpapiPluginMsg_Compositor_ReleaseResource(id, sync_token, is_lost)); } void PepperCompositorHost::SendCommitLayersReplyIfNecessary() { @@ -271,8 +271,8 @@ if (!old_layer || new_layer->common.resource_id != old_layer->common.resource_id) { cc::TextureMailbox mailbox(new_layer->texture->mailbox, - new_layer->texture->target, - new_layer->texture->sync_point); + new_layer->texture->sync_token, + new_layer->texture->target); texture_layer->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create( base::Bind(&PepperCompositorHost::ResourceReleased,
diff --git a/content/renderer/pepper/pepper_compositor_host.h b/content/renderer/pepper/pepper_compositor_host.h index cd17aef4..a954ffb 100644 --- a/content/renderer/pepper/pepper_compositor_host.h +++ b/content/renderer/pepper/pepper_compositor_host.h
@@ -21,6 +21,10 @@ class SharedBitmap; } // namespace cc +namespace gpu { +struct SyncToken; +} // namespace gpu + namespace content { class PepperPluginInstanceImpl; @@ -47,10 +51,10 @@ void ImageReleased(int32_t id, scoped_ptr<base::SharedMemory> shared_memory, scoped_ptr<cc::SharedBitmap> bitmap, - uint32_t sync_point, + const gpu::SyncToken& sync_token, bool is_lost); void ResourceReleased(int32_t id, - uint32_t sync_point, + const gpu::SyncToken& sync_token, bool is_lost); void SendCommitLayersReplyIfNecessary(); void UpdateLayer(const scoped_refptr<cc::Layer>& layer,
diff --git a/content/renderer/pepper/pepper_file_chooser_host.cc b/content/renderer/pepper/pepper_file_chooser_host.cc index 27179b5..7c19403 100644 --- a/content/renderer/pepper/pepper_file_chooser_host.cc +++ b/content/renderer/pepper/pepper_file_chooser_host.cc
@@ -149,6 +149,7 @@ params.acceptTypes = mime_types; params.directory = false; params.needLocalPath = true; + params.requestor = renderer_ppapi_host_->GetDocumentURL(pp_instance()); handler_ = new CompletionHandler(AsWeakPtr()); RenderViewImpl* render_view = static_cast<RenderViewImpl*>(
diff --git a/content/renderer/pepper/pepper_graphics_2d_host.cc b/content/renderer/pepper/pepper_graphics_2d_host.cc index 02a984b0..efa3bc1 100644 --- a/content/renderer/pepper/pepper_graphics_2d_host.cc +++ b/content/renderer/pepper/pepper_graphics_2d_host.cc
@@ -371,15 +371,10 @@ paint.setXfermodeMode(SkXfermode::kSrc_Mode); } - SkPoint origin; - origin.set(SkIntToScalar(plugin_rect.x()), SkIntToScalar(plugin_rect.y())); - - SkPoint pixel_origin = origin; - + SkPoint pixel_origin(PointToSkPoint(plugin_rect.origin())); if (scale_ != 1.0f && scale_ > 0.0f) { canvas->scale(scale_, scale_); - pixel_origin.set(pixel_origin.x() * (1.0f / scale_), - pixel_origin.y() * (1.0f / scale_)); + pixel_origin.scale(1.0f / scale_); } canvas->drawBitmap(image, pixel_origin.x(), pixel_origin.y(), &paint); } @@ -549,7 +544,7 @@ void PepperGraphics2DHost::ReleaseCallback(scoped_ptr<cc::SharedBitmap> bitmap, const gfx::Size& bitmap_size, - uint32 sync_point, + const gpu::SyncToken& sync_token, bool lost_resource) { cached_bitmap_.reset(); // Only keep around a cached bitmap if the plugin is currently drawing (has
diff --git a/content/renderer/pepper/pepper_graphics_2d_host.h b/content/renderer/pepper/pepper_graphics_2d_host.h index 3d592ae..35b632b 100644 --- a/content/renderer/pepper/pepper_graphics_2d_host.h +++ b/content/renderer/pepper/pepper_graphics_2d_host.h
@@ -28,6 +28,10 @@ class Rect; } +namespace gpu { +struct SyncToken; +} + namespace ppapi { struct ViewData; } @@ -159,7 +163,7 @@ void ReleaseCallback(scoped_ptr<cc::SharedBitmap> bitmap, const gfx::Size& bitmap_size, - uint32 sync_point, + const gpu::SyncToken& sync_token, bool lost_resource); RendererPpapiHost* renderer_ppapi_host_;
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc index 9bef853..a4e73c5 100644 --- a/content/renderer/pepper/pepper_plugin_instance_impl.cc +++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -773,7 +773,7 @@ DCHECK(!mailbox.IsZero()); DCHECK_NE(sync_point, 0u); texture_layer_->SetTextureMailboxWithoutReleaseCallback( - cc::TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point)); + cc::TextureMailbox(mailbox, gpu::SyncToken(sync_point), GL_TEXTURE_2D)); texture_layer_->SetNeedsDisplay(); } @@ -2005,7 +2005,8 @@ cc_blink::WebLayerImpl::LayerSettings(), NULL); opaque = bound_graphics_3d_->IsOpaque(); texture_layer_->SetTextureMailboxWithoutReleaseCallback( - cc::TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point)); + cc::TextureMailbox(mailbox, gpu::SyncToken(sync_point), + GL_TEXTURE_2D)); } else { DCHECK(bound_graphics_2d_platform_); texture_layer_ = cc::TextureLayer::CreateForMailbox(
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.cc b/content/renderer/pepper/ppb_graphics_3d_impl.cc index 33087c0..783f800 100644 --- a/content/renderer/pepper/ppb_graphics_3d_impl.cc +++ b/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -229,9 +229,12 @@ if (!plugin_instance) return false; - const WebPreferences& prefs = - static_cast<RenderViewImpl*>(plugin_instance->GetRenderView()) - ->webkit_preferences(); + RenderView* render_view = plugin_instance->GetRenderView(); + if (!render_view) + return false; + + const WebPreferences& prefs = render_view->GetWebkitPreferences(); + // 3D access might be disabled or blacklisted. if (!prefs.pepper_3d_enabled) return false;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 92b5bb0..a2a25086 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -705,6 +705,8 @@ is_zero_copy_enabled_ = command_line.HasSwitch(switches::kEnableZeroCopy); is_partial_raster_enabled_ = command_line.HasSwitch(switches::kEnablePartialRaster); + is_gpu_memory_buffer_compositor_resources_enabled_ = command_line.HasSwitch( + switches::kEnableGpuMemoryBufferCompositorResources); #if defined(OS_MACOSX) && !defined(OS_IOS) is_elastic_overscroll_enabled_ = base::mac::IsOSLionOrLater(); @@ -1503,6 +1505,10 @@ return is_partial_raster_enabled_; } +bool RenderThreadImpl::IsGpuMemoryBufferCompositorResourcesEnabled() { + return is_gpu_memory_buffer_compositor_resources_enabled_; +} + bool RenderThreadImpl::IsElasticOverscrollEnabled() { return is_elastic_overscroll_enabled_; }
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index 236da9f..f7eef237 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h
@@ -194,6 +194,7 @@ bool IsDistanceFieldTextEnabled() override; bool IsZeroCopyEnabled() override; bool IsPartialRasterEnabled() override; + bool IsGpuMemoryBufferCompositorResourcesEnabled() override; bool IsElasticOverscrollEnabled() override; std::vector<unsigned> GetImageTextureTargets() override; scoped_refptr<base::SingleThreadTaskRunner> @@ -634,6 +635,7 @@ bool is_distance_field_text_enabled_; bool is_zero_copy_enabled_; bool is_one_copy_enabled_; + bool is_gpu_memory_buffer_compositor_resources_enabled_; bool is_partial_raster_enabled_; bool is_elastic_overscroll_enabled_; std::vector<unsigned> use_image_texture_targets_;
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 26acfca8..075472f3 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -1769,6 +1769,7 @@ #if defined(OS_ANDROID) ipc_params.capture = params.useMediaCapture; #endif + ipc_params.requestor = params.requestor; return ScheduleFileChooser(ipc_params, chooser_completion); }
diff --git a/content/renderer/resource_fetcher_browsertest.cc b/content/renderer/resource_fetcher_browsertest.cc index 0d76e2de..b677fbe 100644 --- a/content/renderer/resource_fetcher_browsertest.cc +++ b/content/renderer/resource_fetcher_browsertest.cc
@@ -20,6 +20,7 @@ #include "content/public/test/content_browser_test_utils.h" #include "content/public/test/test_utils.h" #include "content/shell/browser/shell.h" +#include "net/test/embedded_test_server/embedded_test_server.h" #include "third_party/WebKit/public/platform/WebURLResponse.h" #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebView.h" @@ -180,7 +181,6 @@ ASSERT_TRUE(delegate->completed()); EXPECT_EQ(delegate->response().httpStatusCode(), 404); - EXPECT_TRUE(delegate->data().find("Not Found.") != std::string::npos); } void ResourceFetcherDidFailOnRenderer() { @@ -295,8 +295,8 @@ // Need to spin up the renderer. NavigateToURL(shell(), GURL(url::kAboutBlankURL)); - ASSERT_TRUE(test_server()->Start()); - GURL url(test_server()->GetURL("files/simple_page.html")); + ASSERT_TRUE(embedded_test_server()->Start()); + GURL url(embedded_test_server()->GetURL("/simple_page.html")); PostTaskToInProcessRendererAndWait( base::Bind(&ResourceFetcherTests::ResourceFetcherDownloadOnRenderer, @@ -308,8 +308,8 @@ NavigateToURL(shell(), GURL(url::kAboutBlankURL)); // Test 404 response. - ASSERT_TRUE(test_server()->Start()); - GURL url = test_server()->GetURL("files/thisfiledoesntexist.html"); + ASSERT_TRUE(embedded_test_server()->Start()); + GURL url = embedded_test_server()->GetURL("/thisfiledoesntexist.html"); PostTaskToInProcessRendererAndWait( base::Bind(&ResourceFetcherTests::ResourceFetcher404OnRenderer, @@ -332,8 +332,8 @@ // Grab a page that takes at least 1 sec to respond, but set the fetcher to // timeout in 0 sec. - ASSERT_TRUE(test_server()->Start()); - GURL url(test_server()->GetURL("slow?1")); + ASSERT_TRUE(embedded_test_server()->Start()); + GURL url(embedded_test_server()->GetURL("/slow?1")); PostTaskToInProcessRendererAndWait( base::Bind(&ResourceFetcherTests::ResourceFetcherTimeoutOnRenderer, @@ -346,8 +346,8 @@ // Grab a page that takes at least 1 sec to respond, but set the fetcher to // timeout in 0 sec. - ASSERT_TRUE(test_server()->Start()); - GURL url(test_server()->GetURL("slow?1")); + ASSERT_TRUE(embedded_test_server()->Start()); + GURL url(embedded_test_server()->GetURL("/slow?1")); PostTaskToInProcessRendererAndWait( base::Bind( @@ -363,8 +363,8 @@ NavigateToURL(shell(), GURL(url::kAboutBlankURL)); // Grab a page that echos the POST body. - ASSERT_TRUE(test_server()->Start()); - GURL url(test_server()->GetURL("echo")); + ASSERT_TRUE(embedded_test_server()->Start()); + GURL url(embedded_test_server()->GetURL("/echo")); PostTaskToInProcessRendererAndWait( base::Bind( @@ -378,8 +378,8 @@ NavigateToURL(shell(), GURL(url::kAboutBlankURL)); // Grab a page that echos the POST body. - ASSERT_TRUE(test_server()->Start()); - GURL url(test_server()->GetURL("echoheader?header")); + ASSERT_TRUE(embedded_test_server()->Start()); + GURL url(embedded_test_server()->GetURL("/echoheader?header")); PostTaskToInProcessRendererAndWait( base::Bind(
diff --git a/content/shell/android/BUILD.gn b/content/shell/android/BUILD.gn index 4fd3e85..94e0d9f 100644 --- a/content/shell/android/BUILD.gn +++ b/content/shell/android/BUILD.gn
@@ -102,10 +102,8 @@ deps += [ "//third_party/icu:icudata" ] } if (v8_use_external_startup_data) { - sources += [ - "$root_out_dir/natives_blob.bin", - "$root_out_dir/snapshot_blob.bin", - ] + renaming_sources = v8_external_startup_data_renaming_sources + renaming_destinations = v8_external_startup_data_renaming_destinations deps += [ "//v8" ] } }
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 3b0dd922..83d36b3a 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -494,10 +494,8 @@ dest = _content_unittests_apk_assets_dir if (v8_use_external_startup_data) { - sources = [ - "$root_out_dir/natives_blob.bin", - "$root_out_dir/snapshot_blob.bin", - ] + renaming_sources = v8_external_startup_data_renaming_sources + renaming_destinations = v8_external_startup_data_renaming_destinations deps = [ "//v8", ]
diff --git a/content/test/browser_test_utils_browsertest.cc b/content/test/browser_test_utils_browsertest.cc index 15f65ae..423f097 100644 --- a/content/test/browser_test_utils_browsertest.cc +++ b/content/test/browser_test_utils_browsertest.cc
@@ -55,7 +55,7 @@ VerifyCrossSiteRedirectURL) { // Map all hosts to localhost and setup the EmbeddedTestServer for redirects. host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); SetupCrossSiteRedirector(embedded_test_server()); // Navigate to http://localhost:<port>/cross-site/foo.com/title2.html and
diff --git a/content/test/data/cross_site_document_request.html b/content/test/data/cross_site_document_request.html index 5edea9d2..accead2 100644 --- a/content/test/data/cross_site_document_request.html +++ b/content/test/data/cross_site_document_request.html
@@ -14,7 +14,7 @@ one of the blacklisted content types.</p> <script> -var pathPrefix = "http://bar.com/files/site_isolation/"; +var pathPrefix = "http://bar.com/site_isolation/"; // To be called from the browsertest via ExecuteScriptAndExtractBool(). function sendRequest(resourceUrl) {
diff --git a/content/test/data/cross_site_document_request_target.html b/content/test/data/cross_site_document_request_target.html index e00db77..b2ccfde 100644 --- a/content/test/data/cross_site_document_request_target.html +++ b/content/test/data/cross_site_document_request_target.html
@@ -3,11 +3,11 @@ <!-- favicon --> <link rel="icon" type="image/png" - href="http://bar.com/files/site_isolation/valid.html"> + href="http://bar.com/site_isolation/valid.html"> <!-- css --> -<link rel="stylesheet" type="text/css" href="http://bar.com/files/site_isolation/valid.html"> +<link rel="stylesheet" type="text/css" href="http://bar.com/site_isolation/valid.html"> <!-- script --> -<script language="javascript" src="http://bar.com/files/site_isolation/valid.html"></script> +<script language="javascript" src="http://bar.com/site_isolation/valid.html"></script> </head> <body> @@ -16,25 +16,25 @@ should be loaded on a domain other than bar.com to be different from the requested resource here.</p> -image:<img src="http://bar.com/files/site_isolation/valid.html"></img><br/> +image:<img src="http://bar.com/site_isolation/valid.html"></img><br/> font: <style media="screen" type="text/css"> @font-face { font-family: "myfont"; - src: url("http://bar.com/files/site_isolation/valid.html") format('woff'); + src: url("http://bar.com/site_isolation/valid.html") format('woff'); } </style><br/> <!-- The renderer creates an iframe for a file with .html extension, so this shouldn't be blocked --> -embed:<embed src="http://bar.com/files/site_isolation/valid.html"></embed><br/> +embed:<embed src="http://bar.com/site_isolation/valid.html"></embed><br/> <!-- The renderer creates an iframe for a file with .html extension, so this shouldn't be blocked --> object:<object width="400" height="400" -data="http://bar.com/files/site_isolation/valid.html"></object><br/> +data="http://bar.com/site_isolation/valid.html"></object><br/> </body> </html>
diff --git a/content/test/data/cross_site_iframe_factory.html b/content/test/data/cross_site_iframe_factory.html index 5084f4c6..e4e808b0 100644 --- a/content/test/data/cross_site_iframe_factory.html +++ b/content/test/data/cross_site_iframe_factory.html
@@ -21,7 +21,7 @@ void SetUpOnMainThread() override { host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server()->Start()); } You can play around with the arguments by loading this page via file://, but
diff --git a/content/test/fake_compositor_dependencies.cc b/content/test/fake_compositor_dependencies.cc index 3cd5043c..63a24d2 100644 --- a/content/test/fake_compositor_dependencies.cc +++ b/content/test/fake_compositor_dependencies.cc
@@ -46,6 +46,10 @@ return false; } +bool FakeCompositorDependencies::IsGpuMemoryBufferCompositorResourcesEnabled() { + return false; +} + bool FakeCompositorDependencies::IsElasticOverscrollEnabled() { return false; }
diff --git a/content/test/fake_compositor_dependencies.h b/content/test/fake_compositor_dependencies.h index 09e517c5..8b9cf12 100644 --- a/content/test/fake_compositor_dependencies.h +++ b/content/test/fake_compositor_dependencies.h
@@ -26,6 +26,7 @@ bool IsDistanceFieldTextEnabled() override; bool IsZeroCopyEnabled() override; bool IsPartialRasterEnabled() override; + bool IsGpuMemoryBufferCompositorResourcesEnabled() override; bool IsElasticOverscrollEnabled() override; std::vector<unsigned> GetImageTextureTargets() override; scoped_refptr<base::SingleThreadTaskRunner>
diff --git a/content/test/ppapi/ppapi_test.h b/content/test/ppapi/ppapi_test.h index 92d5f8b..1f0aad1 100644 --- a/content/test/ppapi/ppapi_test.h +++ b/content/test/ppapi/ppapi_test.h
@@ -11,7 +11,6 @@ #include "base/compiler_specific.h" #include "content/public/test/content_browser_test.h" #include "content/public/test/javascript_test_observer.h" -#include "net/test/spawned_test_server/spawned_test_server.h" #include "url/gurl.h" // This file provides test classes for writing Pepper tests for
diff --git a/content/test/test_blink_web_unit_test_support.cc b/content/test/test_blink_web_unit_test_support.cc index be23db8..d6e2b90 100644 --- a/content/test/test_blink_web_unit_test_support.cc +++ b/content/test/test_blink_web_unit_test_support.cc
@@ -21,7 +21,6 @@ #include "content/test/weburl_loader_mock_factory.h" #include "media/base/media.h" #include "net/cookies/cookie_monster.h" -#include "net/test/spawned_test_server/spawned_test_server.h" #include "storage/browser/database/vfs_backend.h" #include "third_party/WebKit/public/platform/WebData.h" #include "third_party/WebKit/public/platform/WebFileSystem.h"
diff --git a/content/test/web_layer_tree_view_impl_for_testing.cc b/content/test/web_layer_tree_view_impl_for_testing.cc index 8b07ba2..a70aa24 100644 --- a/content/test/web_layer_tree_view_impl_for_testing.cc +++ b/content/test/web_layer_tree_view_impl_for_testing.cc
@@ -8,7 +8,10 @@ #include "base/strings/string_number_conversions.h" #include "base/synchronization/lock.h" #include "base/thread_task_runner_handle.h" +#include "cc/animation/animation_host.h" +#include "cc/animation/animation_timeline.h" #include "cc/base/switches.h" +#include "cc/blink/web_compositor_animation_timeline_impl.h" #include "cc/blink/web_layer_impl.h" #include "cc/input/input_handler.h" #include "cc/layers/layer.h" @@ -58,6 +61,26 @@ layer_tree_host_->SetRootLayer(scoped_refptr<cc::Layer>()); } +void WebLayerTreeViewImplForTesting::attachCompositorAnimationTimeline( + blink::WebCompositorAnimationTimeline* compositor_timeline) { + DCHECK(compositor_timeline); + DCHECK(layer_tree_host_->animation_host()); + layer_tree_host_->animation_host()->AddAnimationTimeline( + static_cast<const cc_blink::WebCompositorAnimationTimelineImpl*>( + compositor_timeline) + ->animation_timeline()); +} + +void WebLayerTreeViewImplForTesting::detachCompositorAnimationTimeline( + blink::WebCompositorAnimationTimeline* compositor_timeline) { + DCHECK(compositor_timeline); + DCHECK(layer_tree_host_->animation_host()); + layer_tree_host_->animation_host()->RemoveAnimationTimeline( + static_cast<const cc_blink::WebCompositorAnimationTimelineImpl*>( + compositor_timeline) + ->animation_timeline()); +} + void WebLayerTreeViewImplForTesting::setViewportSize( const WebSize& unused_deprecated, const WebSize& device_viewport_size) {
diff --git a/content/test/web_layer_tree_view_impl_for_testing.h b/content/test/web_layer_tree_view_impl_for_testing.h index 56dbdb1..b2d82f4 100644 --- a/content/test/web_layer_tree_view_impl_for_testing.h +++ b/content/test/web_layer_tree_view_impl_for_testing.h
@@ -15,7 +15,10 @@ class LayerTreeHost; } -namespace blink { class WebLayer; } +namespace blink { +class WebCompositorAnimationTimeline; +class WebLayer; +} namespace content { @@ -33,6 +36,10 @@ // blink::WebLayerTreeView implementation. void setRootLayer(const blink::WebLayer& layer) override; void clearRootLayer() override; + void attachCompositorAnimationTimeline( + blink::WebCompositorAnimationTimeline*) override; + void detachCompositorAnimationTimeline( + blink::WebCompositorAnimationTimeline*) override; virtual void setViewportSize(const blink::WebSize& unused_deprecated, const blink::WebSize& device_viewport_size); void setViewportSize(const blink::WebSize& device_viewport_size) override;
diff --git a/device/bluetooth/BUILD.gn b/device/bluetooth/BUILD.gn index 25dfc44b..5edb17c 100644 --- a/device/bluetooth/BUILD.gn +++ b/device/bluetooth/BUILD.gn
@@ -161,6 +161,95 @@ if (is_win) { libs = [ "setupapi.lib" ] } + + # This block will also build for Linux once we write the linux + # implementation of BluezDbusManager. + if (is_chromeos) { + defines += [ "DEVICE_BLUETOOTH_IMPLEMENTATION" ] + sources += [ + "dbus/bluetooth_adapter_client.cc", + "dbus/bluetooth_adapter_client.h", + "dbus/bluetooth_agent_manager_client.cc", + "dbus/bluetooth_agent_manager_client.h", + "dbus/bluetooth_agent_service_provider.cc", + "dbus/bluetooth_agent_service_provider.h", + "dbus/bluetooth_dbus_client_bundle.cc", + "dbus/bluetooth_dbus_client_bundle.h", + "dbus/bluetooth_device_client.cc", + "dbus/bluetooth_device_client.h", + "dbus/bluetooth_gatt_characteristic_client.cc", + "dbus/bluetooth_gatt_characteristic_client.h", + "dbus/bluetooth_gatt_characteristic_service_provider.cc", + "dbus/bluetooth_gatt_characteristic_service_provider.h", + "dbus/bluetooth_gatt_descriptor_client.cc", + "dbus/bluetooth_gatt_descriptor_client.h", + "dbus/bluetooth_gatt_descriptor_service_provider.cc", + "dbus/bluetooth_gatt_descriptor_service_provider.h", + "dbus/bluetooth_gatt_manager_client.cc", + "dbus/bluetooth_gatt_manager_client.h", + "dbus/bluetooth_gatt_service_client.cc", + "dbus/bluetooth_gatt_service_client.h", + "dbus/bluetooth_gatt_service_service_provider.cc", + "dbus/bluetooth_gatt_service_service_provider.h", + "dbus/bluetooth_input_client.cc", + "dbus/bluetooth_input_client.h", + "dbus/bluetooth_le_advertisement_service_provider.cc", + "dbus/bluetooth_le_advertisement_service_provider.h", + "dbus/bluetooth_le_advertising_manager_client.cc", + "dbus/bluetooth_le_advertising_manager_client.h", + "dbus/bluetooth_media_client.cc", + "dbus/bluetooth_media_client.h", + "dbus/bluetooth_media_endpoint_service_provider.cc", + "dbus/bluetooth_media_endpoint_service_provider.h", + "dbus/bluetooth_media_transport_client.cc", + "dbus/bluetooth_media_transport_client.h", + "dbus/bluetooth_profile_manager_client.cc", + "dbus/bluetooth_profile_manager_client.h", + "dbus/bluetooth_profile_service_provider.cc", + "dbus/bluetooth_profile_service_provider.h", + "dbus/bluez_dbus_client.h", + "dbus/bluez_dbus_manager.cc", + "dbus/bluez_dbus_manager.h", + "dbus/fake_bluetooth_adapter_client.cc", + "dbus/fake_bluetooth_adapter_client.h", + "dbus/fake_bluetooth_agent_manager_client.cc", + "dbus/fake_bluetooth_agent_manager_client.h", + "dbus/fake_bluetooth_agent_service_provider.cc", + "dbus/fake_bluetooth_agent_service_provider.h", + "dbus/fake_bluetooth_device_client.cc", + "dbus/fake_bluetooth_device_client.h", + "dbus/fake_bluetooth_gatt_characteristic_client.cc", + "dbus/fake_bluetooth_gatt_characteristic_client.h", + "dbus/fake_bluetooth_gatt_characteristic_service_provider.cc", + "dbus/fake_bluetooth_gatt_characteristic_service_provider.h", + "dbus/fake_bluetooth_gatt_descriptor_client.cc", + "dbus/fake_bluetooth_gatt_descriptor_client.h", + "dbus/fake_bluetooth_gatt_descriptor_service_provider.cc", + "dbus/fake_bluetooth_gatt_descriptor_service_provider.h", + "dbus/fake_bluetooth_gatt_manager_client.cc", + "dbus/fake_bluetooth_gatt_manager_client.h", + "dbus/fake_bluetooth_gatt_service_client.cc", + "dbus/fake_bluetooth_gatt_service_client.h", + "dbus/fake_bluetooth_gatt_service_service_provider.cc", + "dbus/fake_bluetooth_gatt_service_service_provider.h", + "dbus/fake_bluetooth_input_client.cc", + "dbus/fake_bluetooth_input_client.h", + "dbus/fake_bluetooth_le_advertisement_service_provider.cc", + "dbus/fake_bluetooth_le_advertisement_service_provider.h", + "dbus/fake_bluetooth_le_advertising_manager_client.cc", + "dbus/fake_bluetooth_le_advertising_manager_client.h", + "dbus/fake_bluetooth_media_client.cc", + "dbus/fake_bluetooth_media_client.h", + "dbus/fake_bluetooth_media_endpoint_service_provider.cc", + "dbus/fake_bluetooth_media_endpoint_service_provider.h", + "dbus/fake_bluetooth_media_transport_client.cc", + "dbus/fake_bluetooth_media_transport_client.h", + "dbus/fake_bluetooth_profile_manager_client.cc", + "dbus/fake_bluetooth_profile_manager_client.h", + "dbus/fake_bluetooth_profile_service_provider.cc", + "dbus/fake_bluetooth_profile_service_provider.h", + ] + } } static_library("mocks") {
diff --git a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothDevice.java b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothDevice.java index 68ccee7d..6e20600 100644 --- a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothDevice.java +++ b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothDevice.java
@@ -15,6 +15,7 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; +import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -34,6 +35,8 @@ private HashSet<String> mUuidsFromScan; Wrappers.BluetoothGattWrapper mBluetoothGatt; private final BluetoothGattCallbackImpl mBluetoothGattCallbackImpl; + final HashMap<Wrappers.BluetoothGattCharacteristicWrapper, + ChromeBluetoothRemoteGattCharacteristic> mWrapperToChromeCharacteristicsMap; private ChromeBluetoothDevice( long nativeBluetoothDeviceAndroid, Wrappers.BluetoothDeviceWrapper deviceWrapper) { @@ -41,6 +44,9 @@ mDevice = deviceWrapper; mUuidsFromScan = new HashSet<String>(); mBluetoothGattCallbackImpl = new BluetoothGattCallbackImpl(); + mWrapperToChromeCharacteristicsMap = + new HashMap<Wrappers.BluetoothGattCharacteristicWrapper, + ChromeBluetoothRemoteGattCharacteristic>(); Log.v(TAG, "ChromeBluetoothDevice created."); } @@ -172,6 +178,36 @@ } }); } + + @Override + public void onCharacteristicRead( + final Wrappers.BluetoothGattCharacteristicWrapper characteristic, + final int status) { + ThreadUtils.runOnUiThread(new Runnable() { + @Override + public void run() { + ChromeBluetoothRemoteGattCharacteristic + chromeBluetoothRemoteGattCharacteristic = + mWrapperToChromeCharacteristicsMap.get(characteristic); + chromeBluetoothRemoteGattCharacteristic.onCharacteristicRead(status); + } + }); + } + + @Override + public void onCharacteristicWrite( + final Wrappers.BluetoothGattCharacteristicWrapper characteristic, + final int status) { + ThreadUtils.runOnUiThread(new Runnable() { + @Override + public void run() { + ChromeBluetoothRemoteGattCharacteristic + chromeBluetoothRemoteGattCharacteristic = + mWrapperToChromeCharacteristicsMap.get(characteristic); + chromeBluetoothRemoteGattCharacteristic.onCharacteristicWrite(status); + } + }); + } } // --------------------------------------------------------------------------------------------- @@ -182,9 +218,7 @@ long nativeBluetoothDeviceAndroid, int status, boolean connected); // Binds to BluetoothDeviceAndroid::CreateGattRemoteService. - // 'Object' type must be used for |bluetoothGattServiceWrapper| because inner class - // Wrappers.BluetoothGattServiceWrapper reference is not handled by jni_generator.py JavaToJni. - // http://crbug.com/505554 + // TODO(http://crbug.com/505554): Replace 'Object' with specific type when JNI fixed. private native void nativeCreateGattRemoteService(long nativeBluetoothDeviceAndroid, String instanceId, Object bluetoothGattServiceWrapper);
diff --git a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothRemoteGattCharacteristic.java b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothRemoteGattCharacteristic.java index 814602fe..845026d 100644 --- a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothRemoteGattCharacteristic.java +++ b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothRemoteGattCharacteristic.java
@@ -19,24 +19,63 @@ final class ChromeBluetoothRemoteGattCharacteristic { private static final String TAG = "Bluetooth"; + private long mNativeBluetoothRemoteGattCharacteristicAndroid; final Wrappers.BluetoothGattCharacteristicWrapper mCharacteristic; + final ChromeBluetoothDevice mChromeBluetoothDevice; private ChromeBluetoothRemoteGattCharacteristic( - Wrappers.BluetoothGattCharacteristicWrapper characteristicWrapper) { + long nativeBluetoothRemoteGattCharacteristicAndroid, + Wrappers.BluetoothGattCharacteristicWrapper characteristicWrapper, + ChromeBluetoothDevice chromeBluetoothDevice) { + mNativeBluetoothRemoteGattCharacteristicAndroid = + nativeBluetoothRemoteGattCharacteristicAndroid; mCharacteristic = characteristicWrapper; + mChromeBluetoothDevice = chromeBluetoothDevice; + + mChromeBluetoothDevice.mWrapperToChromeCharacteristicsMap.put(characteristicWrapper, this); + Log.v(TAG, "ChromeBluetoothRemoteGattCharacteristic created."); } + /** + * Handles C++ object being destroyed. + */ + @CalledByNative + private void onBluetoothRemoteGattCharacteristicAndroidDestruction() { + mNativeBluetoothRemoteGattCharacteristicAndroid = 0; + mChromeBluetoothDevice.mWrapperToChromeCharacteristicsMap.remove(mCharacteristic); + } + + void onCharacteristicRead(int status) { + Log.i(TAG, "onCharacteristicRead status:%d==%s", status, + status == android.bluetooth.BluetoothGatt.GATT_SUCCESS ? "OK" : "Error"); + if (mNativeBluetoothRemoteGattCharacteristicAndroid != 0) { + nativeOnRead(mNativeBluetoothRemoteGattCharacteristicAndroid, status, + mCharacteristic.getValue()); + } + } + + void onCharacteristicWrite(int status) { + Log.i(TAG, "onCharacteristicWrite status:%d==%s", status, + status == android.bluetooth.BluetoothGatt.GATT_SUCCESS ? "OK" : "Error"); + if (mNativeBluetoothRemoteGattCharacteristicAndroid != 0) { + nativeOnWrite(mNativeBluetoothRemoteGattCharacteristicAndroid, status); + } + } + // --------------------------------------------------------------------------------------------- // BluetoothRemoteGattCharacteristicAndroid methods implemented in java: // Implements BluetoothRemoteGattCharacteristicAndroid::Create. - // 'Object' type must be used because inner class Wrappers.BluetoothGattCharacteristicWrapper - // reference is not handled by jni_generator.py JavaToJni. http://crbug.com/505554 + // TODO(http://crbug.com/505554): Replace 'Object' with specific type when JNI fixed. @CalledByNative - private static ChromeBluetoothRemoteGattCharacteristic create(Object characteristicWrapper) { + private static ChromeBluetoothRemoteGattCharacteristic create( + long nativeBluetoothRemoteGattCharacteristicAndroid, + Object bluetoothGattCarachteristicWrapper, Object chromeBluetoothDevice) { return new ChromeBluetoothRemoteGattCharacteristic( - (Wrappers.BluetoothGattCharacteristicWrapper) characteristicWrapper); + nativeBluetoothRemoteGattCharacteristicAndroid, + (Wrappers.BluetoothGattCharacteristicWrapper) bluetoothGattCarachteristicWrapper, + (ChromeBluetoothDevice) chromeBluetoothDevice); } // Implements BluetoothRemoteGattCharacteristicAndroid::GetUUID. @@ -51,4 +90,38 @@ // TODO(scheib): Must read Extended Properties Descriptor. crbug.com/548449 return mCharacteristic.getProperties(); } + + // Implements BluetoothRemoteGattCharacteristicAndroid::ReadRemoteCharacteristic. + @CalledByNative + private boolean readRemoteCharacteristic() { + if (!mChromeBluetoothDevice.mBluetoothGatt.readCharacteristic(mCharacteristic)) { + Log.i(TAG, "readRemoteCharacteristic readCharacteristic failed."); + return false; + } + return true; + } + + // Implements BluetoothRemoteGattCharacteristicAndroid::WriteRemoteCharacteristic. + @CalledByNative + private boolean writeRemoteCharacteristic(byte[] value) { + if (!mCharacteristic.setValue(value)) { + Log.i(TAG, "writeRemoteCharacteristic setValue failed."); + return false; + } + if (!mChromeBluetoothDevice.mBluetoothGatt.writeCharacteristic(mCharacteristic)) { + Log.i(TAG, "writeRemoteCharacteristic writeCharacteristic failed."); + return false; + } + return true; + } + + // --------------------------------------------------------------------------------------------- + // BluetoothAdapterDevice C++ methods declared for access from java: + + // Binds to BluetoothRemoteGattServiceAndroid::OnRead. + native void nativeOnRead( + long nativeBluetoothRemoteGattCharacteristicAndroid, int status, byte[] value); + + // Binds to BluetoothRemoteGattServiceAndroid::OnWrite. + native void nativeOnWrite(long nativeBluetoothRemoteGattCharacteristicAndroid, int status); }
diff --git a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothRemoteGattService.java b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothRemoteGattService.java index 86a79e8..1041c95 100644 --- a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothRemoteGattService.java +++ b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothRemoteGattService.java
@@ -24,12 +24,15 @@ private long mNativeBluetoothRemoteGattServiceAndroid; final Wrappers.BluetoothGattServiceWrapper mService; final String mInstanceId; + ChromeBluetoothDevice mChromeBluetoothDevice; private ChromeBluetoothRemoteGattService(long nativeBluetoothRemoteGattServiceAndroid, - Wrappers.BluetoothGattServiceWrapper serviceWrapper, String instanceId) { + Wrappers.BluetoothGattServiceWrapper serviceWrapper, String instanceId, + ChromeBluetoothDevice chromeBluetoothDevice) { mNativeBluetoothRemoteGattServiceAndroid = nativeBluetoothRemoteGattServiceAndroid; mService = serviceWrapper; mInstanceId = instanceId; + mChromeBluetoothDevice = chromeBluetoothDevice; Log.v(TAG, "ChromeBluetoothRemoteGattService created."); } @@ -45,14 +48,14 @@ // BluetoothRemoteGattServiceAndroid methods implemented in java: // Implements BluetoothRemoteGattServiceAndroid::Create. - // 'Object' type must be used because inner class Wrappers.BluetoothGattServiceWrapper reference - // is not handled by jni_generator.py JavaToJni. http://crbug.com/505554 + // TODO(http://crbug.com/505554): Replace 'Object' with specific type when JNI fixed. @CalledByNative private static ChromeBluetoothRemoteGattService create( - long nativeBluetoothRemoteGattServiceAndroid, Object serviceWrapper, - String instanceId) { + long nativeBluetoothRemoteGattServiceAndroid, Object bluetoothGattServiceWrapper, + String instanceId, Object chromeBluetoothDevice) { return new ChromeBluetoothRemoteGattService(nativeBluetoothRemoteGattServiceAndroid, - (Wrappers.BluetoothGattServiceWrapper) serviceWrapper, instanceId); + (Wrappers.BluetoothGattServiceWrapper) bluetoothGattServiceWrapper, instanceId, + (ChromeBluetoothDevice) chromeBluetoothDevice); } // Implements BluetoothRemoteGattServiceAndroid::GetUUID. @@ -72,18 +75,16 @@ String characteristicInstanceId = mInstanceId + "/" + characteristic.getUuid().toString() + "," + characteristic.getInstanceId(); nativeCreateGattRemoteCharacteristic(mNativeBluetoothRemoteGattServiceAndroid, - characteristicInstanceId, characteristic); + characteristicInstanceId, characteristic, mChromeBluetoothDevice); } } // --------------------------------------------------------------------------------------------- // BluetoothAdapterDevice C++ methods declared for access from java: + // Binds to BluetoothRemoteGattServiceAndroid::CreateGattRemoteCharacteristic. - // 'Object' type must be used for |bluetoothGattCarachteristicWrapper| because inner class - // Wrappers.BluetoothGattCharacteristicWrapper reference is not handled by jni_generator.py - // JavaToJni. - // http://crbug.com/505554 + // TODO(http://crbug.com/505554): Replace 'Object' with specific type when JNI fixed. private native void nativeCreateGattRemoteCharacteristic( long nativeBluetoothRemoteGattServiceAndroid, String instanceId, - Object bluetoothGattCarachteristicWrapper); + Object bluetoothGattCarachteristicWrapper, Object chromeBluetoothDevice); }
diff --git a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java index 115c3179..e8e6306 100644 --- a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java +++ b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java
@@ -226,15 +226,21 @@ */ static class BluetoothDeviceWrapper { private final BluetoothDevice mDevice; + private final HashMap<BluetoothGattCharacteristic, BluetoothGattCharacteristicWrapper> + mCharacteristicsToWrappers; public BluetoothDeviceWrapper(BluetoothDevice device) { mDevice = device; + mCharacteristicsToWrappers = + new HashMap<BluetoothGattCharacteristic, BluetoothGattCharacteristicWrapper>(); } public BluetoothGattWrapper connectGatt( Context context, boolean autoConnect, BluetoothGattCallbackWrapper callback) { - return new BluetoothGattWrapper(mDevice.connectGatt( - context, autoConnect, new ForwardBluetoothGattCallbackToWrapper(callback))); + return new BluetoothGattWrapper( + mDevice.connectGatt(context, autoConnect, + new ForwardBluetoothGattCallbackToWrapper(callback, this)), + this); } public String getAddress() { @@ -259,9 +265,11 @@ */ static class BluetoothGattWrapper { private final BluetoothGatt mGatt; + private final BluetoothDeviceWrapper mDeviceWrapper; - BluetoothGattWrapper(BluetoothGatt gatt) { + BluetoothGattWrapper(BluetoothGatt gatt, BluetoothDeviceWrapper deviceWrapper) { mGatt = gatt; + mDeviceWrapper = deviceWrapper; } public void disconnect() { @@ -277,10 +285,18 @@ ArrayList<BluetoothGattServiceWrapper> servicesWrapped = new ArrayList<BluetoothGattServiceWrapper>(services.size()); for (BluetoothGattService service : services) { - servicesWrapped.add(new BluetoothGattServiceWrapper(service)); + servicesWrapped.add(new BluetoothGattServiceWrapper(service, mDeviceWrapper)); } return servicesWrapped; } + + boolean readCharacteristic(BluetoothGattCharacteristicWrapper characteristic) { + return mGatt.readCharacteristic(characteristic.mCharacteristic); + } + + boolean writeCharacteristic(BluetoothGattCharacteristicWrapper characteristic) { + return mGatt.writeCharacteristic(characteristic.mCharacteristic); + } } /** @@ -293,9 +309,26 @@ */ static class ForwardBluetoothGattCallbackToWrapper extends BluetoothGattCallback { final BluetoothGattCallbackWrapper mWrapperCallback; + final BluetoothDeviceWrapper mDeviceWrapper; - ForwardBluetoothGattCallbackToWrapper(BluetoothGattCallbackWrapper wrapperCallback) { + ForwardBluetoothGattCallbackToWrapper(BluetoothGattCallbackWrapper wrapperCallback, + BluetoothDeviceWrapper deviceWrapper) { mWrapperCallback = wrapperCallback; + mDeviceWrapper = deviceWrapper; + } + + @Override + public void onCharacteristicRead( + BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { + mWrapperCallback.onCharacteristicRead( + mDeviceWrapper.mCharacteristicsToWrappers.get(characteristic), status); + } + + @Override + public void onCharacteristicWrite( + BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { + mWrapperCallback.onCharacteristicWrite( + mDeviceWrapper.mCharacteristicsToWrappers.get(characteristic), status); } @Override @@ -314,10 +347,16 @@ * work on older SDK versions without having a dependency on the class not defined there. * * BluetoothGatt gatt parameters are omitted from methods as each call would - * need to wrap them in a BluetoothGattWrapper. Client code should cache the - * BluetoothGattWrapper provided on the initial BluetoothDeviceWrapper.connectGatt call. + * need to look up the correct BluetoothGattWrapper instance. + * Client code should cache the BluetoothGattWrapper provided if + * necessary from the initial BluetoothDeviceWrapper.connectGatt + * call. */ abstract static class BluetoothGattCallbackWrapper { + public abstract void onCharacteristicRead( + BluetoothGattCharacteristicWrapper characteristic, int status); + public abstract void onCharacteristicWrite( + BluetoothGattCharacteristicWrapper characteristic, int status); public abstract void onConnectionStateChange(int status, int newState); public abstract void onServicesDiscovered(int status); } @@ -327,9 +366,12 @@ */ static class BluetoothGattServiceWrapper { private final BluetoothGattService mService; + private final BluetoothDeviceWrapper mDeviceWrapper; - public BluetoothGattServiceWrapper(BluetoothGattService service) { + public BluetoothGattServiceWrapper( + BluetoothGattService service, BluetoothDeviceWrapper deviceWrapper) { mService = service; + mDeviceWrapper = deviceWrapper; } public List<BluetoothGattCharacteristicWrapper> getCharacteristics() { @@ -337,7 +379,14 @@ ArrayList<BluetoothGattCharacteristicWrapper> characteristicsWrapped = new ArrayList<BluetoothGattCharacteristicWrapper>(characteristics.size()); for (BluetoothGattCharacteristic characteristic : characteristics) { - characteristicsWrapped.add(new BluetoothGattCharacteristicWrapper(characteristic)); + BluetoothGattCharacteristicWrapper characteristicWrapper = + mDeviceWrapper.mCharacteristicsToWrappers.get(characteristic); + if (characteristicWrapper == null) { + characteristicWrapper = new BluetoothGattCharacteristicWrapper(characteristic); + mDeviceWrapper.mCharacteristicsToWrappers.put( + characteristic, characteristicWrapper); + } + characteristicsWrapped.add(characteristicWrapper); } return characteristicsWrapped; } @@ -372,5 +421,13 @@ public UUID getUuid() { return mCharacteristic.getUuid(); } + + public byte[] getValue() { + return mCharacteristic.getValue(); + } + + public boolean setValue(byte[] value) { + return mCharacteristic.setValue(value); + } } }
diff --git a/device/bluetooth/bluetooth.gyp b/device/bluetooth/bluetooth.gyp index f862660..90306d10 100644 --- a/device/bluetooth/bluetooth.gyp +++ b/device/bluetooth/bluetooth.gyp
@@ -133,6 +133,96 @@ 'bluetooth_uuid.h', ], 'conditions': [ + # This block will also build for Linux once we write the linux + # implementation of BluezDbusManager. + ['chromeos==1', { + 'defines': [ + 'DEVICE_BLUETOOTH_IMPLEMENTATION', + ], + 'sources': [ + 'dbus/bluetooth_adapter_client.cc', + 'dbus/bluetooth_adapter_client.h', + 'dbus/bluetooth_le_advertising_manager_client.cc', + 'dbus/bluetooth_le_advertising_manager_client.h', + 'dbus/bluetooth_le_advertisement_service_provider.cc', + 'dbus/bluetooth_le_advertisement_service_provider.h', + 'dbus/bluetooth_agent_manager_client.cc', + 'dbus/bluetooth_agent_manager_client.h', + 'dbus/bluetooth_agent_service_provider.cc', + 'dbus/bluetooth_agent_service_provider.h', + 'dbus/bluetooth_dbus_client_bundle.cc', + 'dbus/bluetooth_dbus_client_bundle.h', + 'dbus/bluetooth_device_client.cc', + 'dbus/bluetooth_device_client.h', + 'dbus/bluetooth_gatt_characteristic_client.cc', + 'dbus/bluetooth_gatt_characteristic_client.h', + 'dbus/bluetooth_gatt_characteristic_service_provider.cc', + 'dbus/bluetooth_gatt_characteristic_service_provider.h', + 'dbus/bluetooth_gatt_descriptor_client.cc', + 'dbus/bluetooth_gatt_descriptor_client.h', + 'dbus/bluetooth_gatt_descriptor_service_provider.cc', + 'dbus/bluetooth_gatt_descriptor_service_provider.h', + 'dbus/bluetooth_gatt_manager_client.cc', + 'dbus/bluetooth_gatt_manager_client.h', + 'dbus/bluetooth_gatt_service_client.cc', + 'dbus/bluetooth_gatt_service_client.h', + 'dbus/bluetooth_gatt_service_service_provider.cc', + 'dbus/bluetooth_gatt_service_service_provider.h', + 'dbus/bluetooth_input_client.cc', + 'dbus/bluetooth_input_client.h', + 'dbus/bluetooth_media_client.cc', + 'dbus/bluetooth_media_client.h', + 'dbus/bluetooth_media_endpoint_service_provider.cc', + 'dbus/bluetooth_media_endpoint_service_provider.h', + 'dbus/bluetooth_media_transport_client.cc', + 'dbus/bluetooth_media_transport_client.h', + 'dbus/bluetooth_profile_manager_client.cc', + 'dbus/bluetooth_profile_manager_client.h', + 'dbus/bluetooth_profile_service_provider.cc', + 'dbus/bluetooth_profile_service_provider.h', + 'dbus/bluez_dbus_client.h', + 'dbus/bluez_dbus_manager.cc', + 'dbus/bluez_dbus_manager.h', + 'dbus/fake_bluetooth_adapter_client.cc', + 'dbus/fake_bluetooth_adapter_client.h', + 'dbus/fake_bluetooth_le_advertising_manager_client.cc', + 'dbus/fake_bluetooth_le_advertising_manager_client.h', + 'dbus/fake_bluetooth_le_advertisement_service_provider.cc', + 'dbus/fake_bluetooth_le_advertisement_service_provider.h', + 'dbus/fake_bluetooth_agent_manager_client.cc', + 'dbus/fake_bluetooth_agent_manager_client.h', + 'dbus/fake_bluetooth_agent_service_provider.cc', + 'dbus/fake_bluetooth_agent_service_provider.h', + 'dbus/fake_bluetooth_device_client.cc', + 'dbus/fake_bluetooth_device_client.h', + 'dbus/fake_bluetooth_gatt_characteristic_client.cc', + 'dbus/fake_bluetooth_gatt_characteristic_client.h', + 'dbus/fake_bluetooth_gatt_characteristic_service_provider.cc', + 'dbus/fake_bluetooth_gatt_characteristic_service_provider.h', + 'dbus/fake_bluetooth_gatt_descriptor_client.cc', + 'dbus/fake_bluetooth_gatt_descriptor_client.h', + 'dbus/fake_bluetooth_gatt_descriptor_service_provider.cc', + 'dbus/fake_bluetooth_gatt_descriptor_service_provider.h', + 'dbus/fake_bluetooth_gatt_manager_client.cc', + 'dbus/fake_bluetooth_gatt_manager_client.h', + 'dbus/fake_bluetooth_gatt_service_client.cc', + 'dbus/fake_bluetooth_gatt_service_client.h', + 'dbus/fake_bluetooth_gatt_service_service_provider.cc', + 'dbus/fake_bluetooth_gatt_service_service_provider.h', + 'dbus/fake_bluetooth_input_client.cc', + 'dbus/fake_bluetooth_input_client.h', + 'dbus/fake_bluetooth_media_client.cc', + 'dbus/fake_bluetooth_media_client.h', + 'dbus/fake_bluetooth_media_endpoint_service_provider.cc', + 'dbus/fake_bluetooth_media_endpoint_service_provider.h', + 'dbus/fake_bluetooth_media_transport_client.cc', + 'dbus/fake_bluetooth_media_transport_client.h', + 'dbus/fake_bluetooth_profile_manager_client.cc', + 'dbus/fake_bluetooth_profile_manager_client.h', + 'dbus/fake_bluetooth_profile_service_provider.cc', + 'dbus/fake_bluetooth_profile_service_provider.h', + ], + }], ['chromeos==1', { 'dependencies': [ '../../build/linux/system.gyp:dbus',
diff --git a/device/bluetooth/bluetooth_adapter_chromeos.cc b/device/bluetooth/bluetooth_adapter_chromeos.cc index 70ec7fb..55d0bef 100644 --- a/device/bluetooth/bluetooth_adapter_chromeos.cc +++ b/device/bluetooth/bluetooth_adapter_chromeos.cc
@@ -13,12 +13,6 @@ #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" #include "base/thread_task_runner_handle.h" -#include "chromeos/dbus/bluetooth_adapter_client.h" -#include "chromeos/dbus/bluetooth_agent_manager_client.h" -#include "chromeos/dbus/bluetooth_agent_service_provider.h" -#include "chromeos/dbus/bluetooth_device_client.h" -#include "chromeos/dbus/bluetooth_input_client.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/system/devicetype.h" #include "device/bluetooth/bluetooth_adapter_profile_chromeos.h" #include "device/bluetooth/bluetooth_advertisement_chromeos.h" @@ -33,6 +27,12 @@ #include "device/bluetooth/bluetooth_socket_chromeos.h" #include "device/bluetooth/bluetooth_socket_thread.h" #include "device/bluetooth/bluetooth_uuid.h" +#include "device/bluetooth/dbus/bluetooth_adapter_client.h" +#include "device/bluetooth/dbus/bluetooth_agent_manager_client.h" +#include "device/bluetooth/dbus/bluetooth_agent_service_provider.h" +#include "device/bluetooth/dbus/bluetooth_device_client.h" +#include "device/bluetooth/dbus/bluetooth_input_client.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" #include "third_party/cros_system_api/dbus/service_constants.h" using device::BluetoothAdapter; @@ -61,9 +61,9 @@ UMABluetoothDiscoverySessionOutcome TranslateDiscoveryErrorToUMA( const std::string& error_name) { - if (error_name == chromeos::BluetoothAdapterClient::kUnknownAdapterError) { + if (error_name == bluez::BluetoothAdapterClient::kUnknownAdapterError) { return UMABluetoothDiscoverySessionOutcome::CHROMEOS_DBUS_UNKNOWN_ADAPTER; - } else if (error_name == chromeos::BluetoothAdapterClient::kNoResponseError) { + } else if (error_name == bluez::BluetoothAdapterClient::kNoResponseError) { return UMABluetoothDiscoverySessionOutcome::CHROMEOS_DBUS_NO_RESPONSE; } else if (error_name == bluetooth_device::kErrorInProgress) { return UMABluetoothDiscoverySessionOutcome::CHROMEOS_DBUS_IN_PROGRESS; @@ -100,9 +100,9 @@ void BluetoothAdapterChromeOS::Shutdown() { if (dbus_is_shutdown_) return; - DCHECK(DBusThreadManager::IsInitialized()) + DCHECK(bluez::BluezDBusManager::IsInitialized()) << "Call BluetoothAdapterFactory::Shutdown() before " - "DBusThreadManager::Shutdown()."; + "BluezDBusManager::Shutdown()."; if (IsPresent()) RemoveAdapter(); // Also deletes devices_. @@ -115,14 +115,19 @@ delete it.second; profile_queues_.clear(); - DBusThreadManager::Get()->GetBluetoothAdapterClient()->RemoveObserver(this); - DBusThreadManager::Get()->GetBluetoothDeviceClient()->RemoveObserver(this); - DBusThreadManager::Get()->GetBluetoothInputClient()->RemoveObserver(this); + bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->RemoveObserver( + this); + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->RemoveObserver( + this); + bluez::BluezDBusManager::Get()->GetBluetoothInputClient()->RemoveObserver( + this); VLOG(1) << "Unregistering pairing agent"; - DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->UnregisterAgent( - dbus::ObjectPath(kAgentPath), base::Bind(&base::DoNothing), - base::Bind(&OnUnregisterAgentError)); + bluez::BluezDBusManager::Get() + ->GetBluetoothAgentManagerClient() + ->UnregisterAgent(dbus::ObjectPath(kAgentPath), + base::Bind(&base::DoNothing), + base::Bind(&OnUnregisterAgentError)); agent_.reset(); dbus_is_shutdown_ = true; @@ -136,18 +141,20 @@ ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); socket_thread_ = device::BluetoothSocketThread::Get(); - DBusThreadManager::Get()->GetBluetoothAdapterClient()->AddObserver(this); - DBusThreadManager::Get()->GetBluetoothDeviceClient()->AddObserver(this); - DBusThreadManager::Get()->GetBluetoothInputClient()->AddObserver(this); + bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->AddObserver( + this); + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->AddObserver(this); + bluez::BluezDBusManager::Get()->GetBluetoothInputClient()->AddObserver(this); // Register the pairing agent. - dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus(); - agent_.reset(BluetoothAgentServiceProvider::Create( + dbus::Bus* system_bus = bluez::BluezDBusManager::Get()->GetSystemBus(); + agent_.reset(bluez::BluetoothAgentServiceProvider::Create( system_bus, dbus::ObjectPath(kAgentPath), this)); DCHECK(agent_.get()); - std::vector<dbus::ObjectPath> object_paths = - DBusThreadManager::Get()->GetBluetoothAdapterClient()->GetAdapters(); + std::vector<dbus::ObjectPath> object_paths = bluez::BluezDBusManager::Get() + ->GetBluetoothAdapterClient() + ->GetAdapters(); if (!object_paths.empty()) { VLOG(1) << object_paths.size() << " Bluetooth adapter(s) available."; @@ -163,9 +170,10 @@ if (!IsPresent()) return std::string(); - BluetoothAdapterClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothAdapterClient()->GetProperties( - object_path_); + bluez::BluetoothAdapterClient::Properties* properties = + bluez::BluezDBusManager::Get() + ->GetBluetoothAdapterClient() + ->GetProperties(object_path_); DCHECK(properties); return BluetoothDevice::CanonicalizeAddress(properties->address.value()); @@ -175,9 +183,10 @@ if (!IsPresent()) return std::string(); - BluetoothAdapterClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothAdapterClient()->GetProperties( - object_path_); + bluez::BluetoothAdapterClient::Properties* properties = + bluez::BluezDBusManager::Get() + ->GetBluetoothAdapterClient() + ->GetProperties(object_path_); DCHECK(properties); return properties->alias.value(); @@ -191,7 +200,7 @@ return; } - DBusThreadManager::Get() + bluez::BluezDBusManager::Get() ->GetBluetoothAdapterClient() ->GetProperties(object_path_) ->alias.Set( @@ -212,9 +221,10 @@ if (!IsPresent()) return false; - BluetoothAdapterClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothAdapterClient()->GetProperties( - object_path_); + bluez::BluetoothAdapterClient::Properties* properties = + bluez::BluezDBusManager::Get() + ->GetBluetoothAdapterClient() + ->GetProperties(object_path_); return properties->powered.value(); } @@ -228,7 +238,7 @@ return; } - DBusThreadManager::Get() + bluez::BluezDBusManager::Get() ->GetBluetoothAdapterClient() ->GetProperties(object_path_) ->powered.Set( @@ -241,9 +251,10 @@ if (!IsPresent()) return false; - BluetoothAdapterClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothAdapterClient()->GetProperties( - object_path_); + bluez::BluetoothAdapterClient::Properties* properties = + bluez::BluezDBusManager::Get() + ->GetBluetoothAdapterClient() + ->GetProperties(object_path_); return properties->discoverable.value(); } @@ -257,7 +268,7 @@ return; } - DBusThreadManager::Get() + bluez::BluezDBusManager::Get() ->GetBluetoothAdapterClient() ->GetProperties(object_path_) ->discoverable.Set( @@ -270,9 +281,10 @@ if (!IsPresent()) return false; - BluetoothAdapterClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothAdapterClient()->GetProperties( - object_path_); + bluez::BluetoothAdapterClient::Properties* properties = + bluez::BluezDBusManager::Get() + ->GetBluetoothAdapterClient() + ->GetProperties(object_path_); return properties->discovering.value(); } @@ -377,9 +389,10 @@ return; DCHECK(IsPresent()); - BluetoothAdapterClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothAdapterClient()->GetProperties( - object_path_); + bluez::BluetoothAdapterClient::Properties* properties = + bluez::BluezDBusManager::Get() + ->GetBluetoothAdapterClient() + ->GetProperties(object_path_); if (property_name == properties->powered.name()) { PoweredChanged(properties->powered.value()); @@ -392,9 +405,9 @@ void BluetoothAdapterChromeOS::DeviceAdded( const dbus::ObjectPath& object_path) { - DCHECK(DBusThreadManager::Get()); - BluetoothDeviceClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothDeviceClient()->GetProperties( + DCHECK(bluez::BluezDBusManager::Get()); + bluez::BluetoothDeviceClient::Properties* properties = + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties( object_path); if (!properties || properties->adapter.value() != object_path_) return; @@ -438,8 +451,8 @@ if (!device_chromeos) return; - BluetoothDeviceClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothDeviceClient()->GetProperties( + bluez::BluetoothDeviceClient::Properties* properties = + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties( object_path); if (property_name == properties->address.name()) { @@ -513,8 +526,8 @@ if (!device_chromeos) return; - BluetoothInputClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothInputClient()->GetProperties( + bluez::BluetoothInputClient::Properties* properties = + bluez::BluezDBusManager::Get()->GetBluetoothInputClient()->GetProperties( object_path); // Properties structure can be removed, which triggers a change in the @@ -672,7 +685,7 @@ void BluetoothAdapterChromeOS::OnRegisterAgent() { VLOG(1) << "Pairing agent registered, requesting to be made default"; - DBusThreadManager::Get() + bluez::BluezDBusManager::Get() ->GetBluetoothAgentManagerClient() ->RequestDefaultAgent( dbus::ObjectPath(kAgentPath), @@ -765,19 +778,22 @@ VLOG(1) << object_path_.value() << ": using adapter."; VLOG(1) << "Registering pairing agent"; - DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->RegisterAgent( - dbus::ObjectPath(kAgentPath), - bluetooth_agent_manager::kKeyboardDisplayCapability, - base::Bind(&BluetoothAdapterChromeOS::OnRegisterAgent, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothAdapterChromeOS::OnRegisterAgentError, - weak_ptr_factory_.GetWeakPtr())); + bluez::BluezDBusManager::Get() + ->GetBluetoothAgentManagerClient() + ->RegisterAgent( + dbus::ObjectPath(kAgentPath), + bluetooth_agent_manager::kKeyboardDisplayCapability, + base::Bind(&BluetoothAdapterChromeOS::OnRegisterAgent, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAdapterChromeOS::OnRegisterAgentError, + weak_ptr_factory_.GetWeakPtr())); SetDefaultAdapterName(); - BluetoothAdapterClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothAdapterClient()->GetProperties( - object_path_); + bluez::BluetoothAdapterClient::Properties* properties = + bluez::BluezDBusManager::Get() + ->GetBluetoothAdapterClient() + ->GetProperties(object_path_); PresentChanged(true); @@ -789,7 +805,7 @@ DiscoveringChanged(true); std::vector<dbus::ObjectPath> device_paths = - DBusThreadManager::Get() + bluez::BluezDBusManager::Get() ->GetBluetoothDeviceClient() ->GetDevicesForAdapter(object_path_); @@ -828,9 +844,10 @@ DCHECK(IsPresent()); VLOG(1) << object_path_.value() << ": adapter removed."; - BluetoothAdapterClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothAdapterClient()->GetProperties( - object_path_); + bluez::BluetoothAdapterClient::Properties* properties = + bluez::BluezDBusManager::Get() + ->GetBluetoothAdapterClient() + ->GetProperties(object_path_); object_path_ = dbus::ObjectPath(""); @@ -1025,8 +1042,8 @@ void BluetoothAdapterChromeOS::UseProfile( const BluetoothUUID& uuid, const dbus::ObjectPath& device_path, - const BluetoothProfileManagerClient::Options& options, - BluetoothProfileServiceProvider::Delegate* delegate, + const bluez::BluetoothProfileManagerClient::Options& options, + bluez::BluetoothProfileServiceProvider::Delegate* delegate, const ProfileRegisteredCallback& success_callback, const ErrorCompletionCallback& error_callback) { DCHECK(delegate); @@ -1097,7 +1114,7 @@ void BluetoothAdapterChromeOS::SetProfileDelegate( const BluetoothUUID& uuid, const dbus::ObjectPath& device_path, - BluetoothProfileServiceProvider::Delegate* delegate, + bluez::BluetoothProfileServiceProvider::Delegate* delegate, const ProfileRegisteredCallback& success_callback, const ErrorCompletionCallback& error_callback) { if (profiles_.find(uuid) == profiles_.end()) { @@ -1140,7 +1157,7 @@ // Set the discoverable_timeout property to zero so the adapter remains // discoverable forever. - DBusThreadManager::Get() + bluez::BluezDBusManager::Get() ->GetBluetoothAdapterClient() ->GetProperties(object_path_) ->discoverable_timeout.Set( @@ -1214,7 +1231,7 @@ // This is the first request to start device discovery. discovery_request_pending_ = true; - DBusThreadManager::Get()->GetBluetoothAdapterClient()->StartDiscovery( + bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->StartDiscovery( object_path_, base::Bind(&BluetoothAdapterChromeOS::OnStartDiscovery, weak_ptr_factory_.GetWeakPtr(), callback, error_callback), @@ -1268,7 +1285,7 @@ // discovery. DCHECK_EQ(num_discovery_sessions_, 1); discovery_request_pending_ = true; - DBusThreadManager::Get()->GetBluetoothAdapterClient()->StopDiscovery( + bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->StopDiscovery( object_path_, base::Bind(&BluetoothAdapterChromeOS::OnStopDiscovery, weak_ptr_factory_.GetWeakPtr(), callback), base::Bind(&BluetoothAdapterChromeOS::OnStopDiscoveryError, @@ -1301,7 +1318,7 @@ current_filter_.reset(discovery_filter.release()); - chromeos::BluetoothAdapterClient::DiscoveryFilter dbus_discovery_filter; + bluez::BluetoothAdapterClient::DiscoveryFilter dbus_discovery_filter; if (current_filter_.get()) { uint16_t pathloss; @@ -1336,12 +1353,14 @@ } } - DBusThreadManager::Get()->GetBluetoothAdapterClient()->SetDiscoveryFilter( - object_path_, dbus_discovery_filter, - base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoveryFilter, - weak_ptr_factory_.GetWeakPtr(), callback, error_callback), - base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoveryFilterError, - weak_ptr_factory_.GetWeakPtr(), callback, error_callback)); + bluez::BluezDBusManager::Get() + ->GetBluetoothAdapterClient() + ->SetDiscoveryFilter( + object_path_, dbus_discovery_filter, + base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoveryFilter, + weak_ptr_factory_.GetWeakPtr(), callback, error_callback), + base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoveryFilterError, + weak_ptr_factory_.GetWeakPtr(), callback, error_callback)); } void BluetoothAdapterChromeOS::OnStartDiscovery( @@ -1431,7 +1450,7 @@ DCHECK(discovery_request_pending_); DCHECK_EQ(num_discovery_sessions_, 0); - DBusThreadManager::Get()->GetBluetoothAdapterClient()->StartDiscovery( + bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->StartDiscovery( object_path_, base::Bind(&BluetoothAdapterChromeOS::OnStartDiscovery, weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
diff --git a/device/bluetooth/bluetooth_adapter_chromeos.h b/device/bluetooth/bluetooth_adapter_chromeos.h index 46c634f..53b271f6 100644 --- a/device/bluetooth/bluetooth_adapter_chromeos.h +++ b/device/bluetooth/bluetooth_adapter_chromeos.h
@@ -12,18 +12,18 @@ #include <vector> #include "base/memory/weak_ptr.h" -#include "chromeos/dbus/bluetooth_adapter_client.h" -#include "chromeos/dbus/bluetooth_agent_service_provider.h" -#include "chromeos/dbus/bluetooth_device_client.h" -#include "chromeos/dbus/bluetooth_input_client.h" -#include "chromeos/dbus/bluetooth_profile_manager_client.h" -#include "chromeos/dbus/bluetooth_profile_service_provider.h" #include "dbus/object_path.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_audio_sink.h" #include "device/bluetooth/bluetooth_device.h" #include "device/bluetooth/bluetooth_discovery_session.h" #include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_adapter_client.h" +#include "device/bluetooth/dbus/bluetooth_agent_service_provider.h" +#include "device/bluetooth/dbus/bluetooth_device_client.h" +#include "device/bluetooth/dbus/bluetooth_input_client.h" +#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h" +#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h" namespace base { class SequencedTaskRunner; @@ -60,10 +60,10 @@ // BluetoothChromeOSTest, Shutdown. class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterChromeOS : public device::BluetoothAdapter, - public chromeos::BluetoothAdapterClient::Observer, - public chromeos::BluetoothDeviceClient::Observer, - public chromeos::BluetoothInputClient::Observer, - public chromeos::BluetoothAgentServiceProvider::Delegate { + public bluez::BluetoothAdapterClient::Observer, + public bluez::BluetoothDeviceClient::Observer, + public bluez::BluetoothInputClient::Observer, + public bluez::BluetoothAgentServiceProvider::Delegate { public: typedef base::Callback<void(const std::string& error_message)> ErrorCompletionCallback; @@ -157,8 +157,8 @@ // |error_callback| will be called. void UseProfile(const device::BluetoothUUID& uuid, const dbus::ObjectPath& device_path, - const BluetoothProfileManagerClient::Options& options, - BluetoothProfileServiceProvider::Delegate* delegate, + const bluez::BluetoothProfileManagerClient::Options& options, + bluez::BluetoothProfileServiceProvider::Delegate* delegate, const ProfileRegisteredCallback& success_callback, const ErrorCompletionCallback& error_callback); @@ -194,23 +194,23 @@ BluetoothAdapterChromeOS(); ~BluetoothAdapterChromeOS() override; - // BluetoothAdapterClient::Observer override. + // bluez::BluetoothAdapterClient::Observer override. void AdapterAdded(const dbus::ObjectPath& object_path) override; void AdapterRemoved(const dbus::ObjectPath& object_path) override; void AdapterPropertyChanged(const dbus::ObjectPath& object_path, const std::string& property_name) override; - // BluetoothDeviceClient::Observer override. + // bluez::BluetoothDeviceClient::Observer override. void DeviceAdded(const dbus::ObjectPath& object_path) override; void DeviceRemoved(const dbus::ObjectPath& object_path) override; void DevicePropertyChanged(const dbus::ObjectPath& object_path, const std::string& property_name) override; - // BluetoothInputClient::Observer override. + // bluez::BluetoothInputClient::Observer override. void InputPropertyChanged(const dbus::ObjectPath& object_path, const std::string& property_name) override; - // BluetoothAgentServiceProvider::Delegate override. + // bluez::BluetoothAgentServiceProvider::Delegate override. void Released() override; void RequestPinCode(const dbus::ObjectPath& device_path, const PinCodeCallback& callback) override; @@ -333,11 +333,12 @@ void OnRegisterProfile(const device::BluetoothUUID& uuid, scoped_ptr<BluetoothAdapterProfileChromeOS> profile); - void SetProfileDelegate(const device::BluetoothUUID& uuid, - const dbus::ObjectPath& device_path, - BluetoothProfileServiceProvider::Delegate* delegate, - const ProfileRegisteredCallback& success_callback, - const ErrorCompletionCallback& error_callback); + void SetProfileDelegate( + const device::BluetoothUUID& uuid, + const dbus::ObjectPath& device_path, + bluez::BluetoothProfileServiceProvider::Delegate* delegate, + const ProfileRegisteredCallback& success_callback, + const ErrorCompletionCallback& error_callback); void OnRegisterProfileError(const device::BluetoothUUID& uuid, const std::string& error_name, const std::string& error_message); @@ -377,7 +378,7 @@ // Instance of the D-Bus agent object used for pairing, initialized with // our own class as its delegate. - scoped_ptr<BluetoothAgentServiceProvider> agent_; + scoped_ptr<bluez::BluetoothAgentServiceProvider> agent_; // UI thread task runner and socket thread object used to create sockets. scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
diff --git a/device/bluetooth/bluetooth_adapter_profile_chromeos.cc b/device/bluetooth/bluetooth_adapter_profile_chromeos.cc index aeab2aef..27779f28 100644 --- a/device/bluetooth/bluetooth_adapter_profile_chromeos.cc +++ b/device/bluetooth/bluetooth_adapter_profile_chromeos.cc
@@ -9,29 +9,31 @@ #include "base/bind.h" #include "base/logging.h" #include "base/strings/string_util.h" -#include "chromeos/dbus/bluetooth_profile_service_provider.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "dbus/bus.h" #include "dbus/object_path.h" #include "device/bluetooth/bluetooth_adapter_chromeos.h" #include "device/bluetooth/bluetooth_uuid.h" +#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" namespace chromeos { // static void BluetoothAdapterProfileChromeOS::Register( const device::BluetoothUUID& uuid, - const BluetoothProfileManagerClient::Options& options, + const bluez::BluetoothProfileManagerClient::Options& options, const ProfileRegisteredCallback& success_callback, - const BluetoothProfileManagerClient::ErrorCallback& error_callback) { + const bluez::BluetoothProfileManagerClient::ErrorCallback& error_callback) { scoped_ptr<BluetoothAdapterProfileChromeOS> profile( new BluetoothAdapterProfileChromeOS(uuid)); VLOG(1) << "Registering profile: " << profile->object_path().value(); const dbus::ObjectPath& object_path = profile->object_path(); - DBusThreadManager::Get()->GetBluetoothProfileManagerClient()->RegisterProfile( - object_path, uuid.canonical_value(), options, - base::Bind(success_callback, base::Passed(&profile)), error_callback); + bluez::BluezDBusManager::Get() + ->GetBluetoothProfileManagerClient() + ->RegisterProfile(object_path, uuid.canonical_value(), options, + base::Bind(success_callback, base::Passed(&profile)), + error_callback); } BluetoothAdapterProfileChromeOS::BluetoothAdapterProfileChromeOS( @@ -42,9 +44,9 @@ object_path_ = dbus::ObjectPath("/org/chromium/bluetooth_profile/" + uuid_path); - dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus(); - profile_.reset( - BluetoothProfileServiceProvider::Create(system_bus, object_path_, this)); + dbus::Bus* system_bus = bluez::BluezDBusManager::Get()->GetSystemBus(); + profile_.reset(bluez::BluetoothProfileServiceProvider::Create( + system_bus, object_path_, this)); DCHECK(profile_.get()); } @@ -53,7 +55,7 @@ bool BluetoothAdapterProfileChromeOS::SetDelegate( const dbus::ObjectPath& device_path, - BluetoothProfileServiceProvider::Delegate* delegate) { + bluez::BluetoothProfileServiceProvider::Delegate* delegate) { DCHECK(delegate); VLOG(1) << "SetDelegate: " << object_path_.value() << " dev " << device_path.value(); @@ -83,7 +85,7 @@ VLOG(1) << device_path.value() << " No delegates left, unregistering."; // No users left, release the profile. - DBusThreadManager::Get() + bluez::BluezDBusManager::Get() ->GetBluetoothProfileManagerClient() ->UnregisterProfile( object_path_, unregistered_callback, @@ -102,7 +104,7 @@ unregistered_callback.Run(); } -// BluetoothProfileServiceProvider::Delegate: +// bluez::BluetoothProfileServiceProvider::Delegate: void BluetoothAdapterProfileChromeOS::Released() { VLOG(1) << object_path_.value() << ": Release"; } @@ -110,7 +112,7 @@ void BluetoothAdapterProfileChromeOS::NewConnection( const dbus::ObjectPath& device_path, scoped_ptr<dbus::FileDescriptor> fd, - const BluetoothProfileServiceProvider::Delegate::Options& options, + const bluez::BluetoothProfileServiceProvider::Delegate::Options& options, const ConfirmationCallback& callback) { dbus::ObjectPath delegate_path = device_path;
diff --git a/device/bluetooth/bluetooth_adapter_profile_chromeos.h b/device/bluetooth/bluetooth_adapter_profile_chromeos.h index 85e2ffe..35971e8 100644 --- a/device/bluetooth/bluetooth_adapter_profile_chromeos.h +++ b/device/bluetooth/bluetooth_adapter_profile_chromeos.h
@@ -6,10 +6,10 @@ #define DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_PROFILE_CHROMEOS_H_ #include "base/memory/weak_ptr.h" -#include "chromeos/dbus/bluetooth_profile_manager_client.h" -#include "chromeos/dbus/bluetooth_profile_service_provider.h" #include "device/bluetooth/bluetooth_adapter_chromeos.h" #include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h" +#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h" namespace device { class BluetoothUUID; @@ -28,7 +28,7 @@ // BluetoothAdapterProfileChromeOS objects are owned by the // BluetoothAdapterChromeOS and allocated through Register() class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterProfileChromeOS - : public chromeos::BluetoothProfileServiceProvider::Delegate { + : public bluez::BluetoothProfileServiceProvider::Delegate { public: typedef base::Callback<void(scoped_ptr<BluetoothAdapterProfileChromeOS> profile)> ProfileRegisteredCallback; @@ -39,9 +39,10 @@ // will be called. static void Register( const device::BluetoothUUID& uuid, - const BluetoothProfileManagerClient::Options& options, + const bluez::BluetoothProfileManagerClient::Options& options, const ProfileRegisteredCallback& success_callback, - const BluetoothProfileManagerClient::ErrorCallback& error_callback); + const bluez::BluetoothProfileManagerClient::ErrorCallback& + error_callback); ~BluetoothAdapterProfileChromeOS() override; @@ -56,7 +57,7 @@ // Returns true if the delegate was set, and false if the |device_path| // already had a delegate set. bool SetDelegate(const dbus::ObjectPath& device_path, - BluetoothProfileServiceProvider::Delegate* delegate); + bluez::BluetoothProfileServiceProvider::Delegate* delegate); // Remove the delegate for a device. |unregistered_callback| will be called // if this unregisters the profile. @@ -69,12 +70,12 @@ private: BluetoothAdapterProfileChromeOS(const device::BluetoothUUID& uuid); - // BluetoothProfileServiceProvider::Delegate: + // bluez::BluetoothProfileServiceProvider::Delegate: void Released() override; void NewConnection( const dbus::ObjectPath& device_path, scoped_ptr<dbus::FileDescriptor> fd, - const BluetoothProfileServiceProvider::Delegate::Options& options, + const bluez::BluetoothProfileServiceProvider::Delegate::Options& options, const ConfirmationCallback& callback) override; void RequestDisconnection(const dbus::ObjectPath& device_path, const ConfirmationCallback& callback) override; @@ -86,7 +87,8 @@ const std::string& error_message); // List of delegates which this profile is multiplexing to. - std::map<std::string, BluetoothProfileServiceProvider::Delegate*> delegates_; + std::map<std::string, bluez::BluetoothProfileServiceProvider::Delegate*> + delegates_; // The UUID that this profile represents. const device::BluetoothUUID& uuid_; @@ -95,7 +97,7 @@ dbus::ObjectPath object_path_; // Profile dbus object for receiving profile method calls from BlueZ - scoped_ptr<BluetoothProfileServiceProvider> profile_; + scoped_ptr<bluez::BluetoothProfileServiceProvider> profile_; // Note: This should remain the last member so it'll be destroyed and // invalidate its weak pointers before any other members are destroyed.
diff --git a/device/bluetooth/bluetooth_adapter_profile_chromeos_unittest.cc b/device/bluetooth/bluetooth_adapter_profile_chromeos_unittest.cc index 1b9c0b3..be999019 100644 --- a/device/bluetooth/bluetooth_adapter_profile_chromeos_unittest.cc +++ b/device/bluetooth/bluetooth_adapter_profile_chromeos_unittest.cc
@@ -4,17 +4,17 @@ #include "base/bind.h" #include "base/message_loop/message_loop.h" -#include "chromeos/dbus/bluetooth_profile_service_provider.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_adapter_client.h" -#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" -#include "chromeos/dbus/fake_bluetooth_device_client.h" -#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_adapter_chromeos.h" #include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/bluetooth_adapter_profile_chromeos.h" #include "device/bluetooth/bluetooth_uuid.h" +#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_device_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h" #include "testing/gtest/include/gtest/gtest.h" using device::BluetoothAdapter; @@ -27,25 +27,29 @@ BluetoothAdapterProfileChromeOSTest() : success_callback_count_(0), error_callback_count_(0), - fake_delegate_paired_(FakeBluetoothDeviceClient::kPairedDevicePath), - fake_delegate_autopair_(FakeBluetoothDeviceClient::kLegacyAutopairPath), + fake_delegate_paired_( + bluez::FakeBluetoothDeviceClient::kPairedDevicePath), + fake_delegate_autopair_( + bluez::FakeBluetoothDeviceClient::kLegacyAutopairPath), fake_delegate_listen_(""), profile_user_ptr_(nullptr) {} void SetUp() override { - scoped_ptr<DBusThreadManagerSetter> dbus_setter = - DBusThreadManager::GetSetterForTesting(); + scoped_ptr<bluez::BluezDBusManagerSetter> dbus_setter = + bluez::BluezDBusManager::GetSetterForTesting(); dbus_setter->SetBluetoothAdapterClient( - scoped_ptr<BluetoothAdapterClient>(new FakeBluetoothAdapterClient)); + scoped_ptr<bluez::BluetoothAdapterClient>( + new bluez::FakeBluetoothAdapterClient)); dbus_setter->SetBluetoothAgentManagerClient( - scoped_ptr<BluetoothAgentManagerClient>( - new FakeBluetoothAgentManagerClient)); + scoped_ptr<bluez::BluetoothAgentManagerClient>( + new bluez::FakeBluetoothAgentManagerClient)); dbus_setter->SetBluetoothDeviceClient( - scoped_ptr<BluetoothDeviceClient>(new FakeBluetoothDeviceClient)); + scoped_ptr<bluez::BluetoothDeviceClient>( + new bluez::FakeBluetoothDeviceClient)); dbus_setter->SetBluetoothProfileManagerClient( - scoped_ptr<BluetoothProfileManagerClient>( - new FakeBluetoothProfileManagerClient)); + scoped_ptr<bluez::BluetoothProfileManagerClient>( + new bluez::FakeBluetoothProfileManagerClient)); // Grab a pointer to the adapter. device::BluetoothAdapterFactory::GetAdapter( @@ -64,21 +68,20 @@ void TearDown() override { profile_.reset(); adapter_ = nullptr; - DBusThreadManager::Shutdown(); + bluez::BluezDBusManager::Shutdown(); } void AdapterCallback(scoped_refptr<BluetoothAdapter> adapter) { adapter_ = adapter; } - class FakeDelegate - : public chromeos::BluetoothProfileServiceProvider::Delegate { + class FakeDelegate : public bluez::BluetoothProfileServiceProvider::Delegate { public: FakeDelegate(const std::string& device_path) : connections_(0) { device_path_ = dbus::ObjectPath(device_path); } - // BluetoothProfileServiceProvider::Delegate: + // bluez::BluetoothProfileServiceProvider::Delegate: void Released() override { // noop } @@ -86,7 +89,8 @@ void NewConnection( const dbus::ObjectPath& device_path, scoped_ptr<dbus::FileDescriptor> fd, - const BluetoothProfileServiceProvider::Delegate::Options& options, + const bluez::BluetoothProfileServiceProvider::Delegate::Options& + options, const ConfirmationCallback& callback) override { ++connections_; fd->CheckValidity(); @@ -157,8 +161,8 @@ }; TEST_F(BluetoothAdapterProfileChromeOSTest, DelegateCount) { - BluetoothUUID uuid(FakeBluetoothProfileManagerClient::kRfcommUuid); - BluetoothProfileManagerClient::Options options; + BluetoothUUID uuid(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid); + bluez::BluetoothProfileManagerClient::Options options; options.require_authentication.reset(new bool(false)); @@ -194,8 +198,8 @@ } TEST_F(BluetoothAdapterProfileChromeOSTest, BlackHole) { - BluetoothUUID uuid(FakeBluetoothProfileManagerClient::kRfcommUuid); - BluetoothProfileManagerClient::Options options; + BluetoothUUID uuid(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid); + bluez::BluetoothProfileManagerClient::Options options; options.require_authentication.reset(new bool(false)); @@ -212,9 +216,9 @@ EXPECT_EQ(1U, success_callback_count_); EXPECT_EQ(0U, error_callback_count_); - DBusThreadManager::Get()->GetBluetoothDeviceClient()->ConnectProfile( - dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath), - FakeBluetoothProfileManagerClient::kRfcommUuid, + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->ConnectProfile( + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kPairedDevicePath), + bluez::FakeBluetoothProfileManagerClient::kRfcommUuid, base::Bind( &BluetoothAdapterProfileChromeOSTest::DBusConnectSuccessCallback, base::Unretained(this)), @@ -230,8 +234,8 @@ } TEST_F(BluetoothAdapterProfileChromeOSTest, Routing) { - BluetoothUUID uuid(FakeBluetoothProfileManagerClient::kRfcommUuid); - BluetoothProfileManagerClient::Options options; + BluetoothUUID uuid(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid); + bluez::BluetoothProfileManagerClient::Options options; options.require_authentication.reset(new bool(false)); @@ -255,9 +259,9 @@ profile_->SetDelegate(fake_delegate_listen_.device_path_, &fake_delegate_listen_); - DBusThreadManager::Get()->GetBluetoothDeviceClient()->ConnectProfile( - dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath), - FakeBluetoothProfileManagerClient::kRfcommUuid, + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->ConnectProfile( + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kPairedDevicePath), + bluez::FakeBluetoothProfileManagerClient::kRfcommUuid, base::Bind( &BluetoothAdapterProfileChromeOSTest::DBusConnectSuccessCallback, base::Unretained(this)), @@ -271,9 +275,9 @@ EXPECT_EQ(1U, fake_delegate_paired_.connections_); - DBusThreadManager::Get()->GetBluetoothDeviceClient()->ConnectProfile( - dbus::ObjectPath(FakeBluetoothDeviceClient::kLegacyAutopairPath), - FakeBluetoothProfileManagerClient::kRfcommUuid, + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->ConnectProfile( + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLegacyAutopairPath), + bluez::FakeBluetoothProfileManagerClient::kRfcommUuid, base::Bind( &BluetoothAdapterProfileChromeOSTest::DBusConnectSuccessCallback, base::Unretained(this)), @@ -288,9 +292,9 @@ EXPECT_EQ(1U, fake_delegate_autopair_.connections_); // Incoming connections look the same from BlueZ. - DBusThreadManager::Get()->GetBluetoothDeviceClient()->ConnectProfile( - dbus::ObjectPath(FakeBluetoothDeviceClient::kDisplayPinCodePath), - FakeBluetoothProfileManagerClient::kRfcommUuid, + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->ConnectProfile( + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kDisplayPinCodePath), + bluez::FakeBluetoothProfileManagerClient::kRfcommUuid, base::Bind( &BluetoothAdapterProfileChromeOSTest::DBusConnectSuccessCallback, base::Unretained(this)), @@ -306,8 +310,8 @@ } TEST_F(BluetoothAdapterProfileChromeOSTest, SimultaneousRegister) { - BluetoothUUID uuid(FakeBluetoothProfileManagerClient::kRfcommUuid); - BluetoothProfileManagerClient::Options options; + BluetoothUUID uuid(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid); + bluez::BluetoothProfileManagerClient::Options options; BluetoothAdapterChromeOS* adapter = static_cast<BluetoothAdapterChromeOS*>(adapter_.get()); @@ -347,8 +351,9 @@ } TEST_F(BluetoothAdapterProfileChromeOSTest, SimultaneousRegisterFail) { - BluetoothUUID uuid(FakeBluetoothProfileManagerClient::kUnregisterableUuid); - BluetoothProfileManagerClient::Options options; + BluetoothUUID uuid( + bluez::FakeBluetoothProfileManagerClient::kUnregisterableUuid); + bluez::BluetoothProfileManagerClient::Options options; BluetoothAdapterChromeOS* adapter = static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
diff --git a/device/bluetooth/bluetooth_advertisement_chromeos.cc b/device/bluetooth/bluetooth_advertisement_chromeos.cc index 8cdfe90e..671977dc 100644 --- a/device/bluetooth/bluetooth_advertisement_chromeos.cc +++ b/device/bluetooth/bluetooth_advertisement_chromeos.cc
@@ -12,11 +12,11 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string_util.h" -#include "chromeos/dbus/bluetooth_le_advertising_manager_client.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "dbus/bus.h" #include "dbus/object_path.h" #include "device/bluetooth/bluetooth_adapter_chromeos.h" +#include "device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" #include "third_party/cros_system_api/dbus/service_constants.h" namespace { @@ -82,10 +82,12 @@ dbus::ObjectPath advertisement_object_path = dbus::ObjectPath("/org/chromium/bluetooth_advertisement/" + GuidString); - DCHECK(DBusThreadManager::Get()); - provider_ = BluetoothLEAdvertisementServiceProvider::Create( - DBusThreadManager::Get()->GetSystemBus(), advertisement_object_path, this, - static_cast<BluetoothLEAdvertisementServiceProvider::AdvertisementType>( + DCHECK(bluez::BluezDBusManager::Get()); + provider_ = bluez::BluetoothLEAdvertisementServiceProvider::Create( + bluez::BluezDBusManager::Get()->GetSystemBus(), advertisement_object_path, + this, + static_cast< + bluez::BluetoothLEAdvertisementServiceProvider::AdvertisementType>( data->type()), data->service_uuids().Pass(), data->manufacturer_data().Pass(), data->solicit_uuids().Pass(), data->service_data().Pass()); @@ -95,8 +97,8 @@ const base::Closure& success_callback, const device::BluetoothAdapter::CreateAdvertisementErrorCallback& error_callback) { - DCHECK(DBusThreadManager::Get()); - DBusThreadManager::Get() + DCHECK(bluez::BluezDBusManager::Get()); + bluez::BluezDBusManager::Get() ->GetBluetoothLEAdvertisingManagerClient() ->RegisterAdvertisement( adapter_->object_path(), provider_->object_path(), success_callback, @@ -118,8 +120,8 @@ return; } - DCHECK(DBusThreadManager::Get()); - DBusThreadManager::Get() + DCHECK(bluez::BluezDBusManager::Get()); + bluez::BluezDBusManager::Get() ->GetBluetoothLEAdvertisingManagerClient() ->UnregisterAdvertisement( adapter_->object_path(), provider_->object_path(), success_callback,
diff --git a/device/bluetooth/bluetooth_advertisement_chromeos.h b/device/bluetooth/bluetooth_advertisement_chromeos.h index aeb59b7c..44abec27 100644 --- a/device/bluetooth/bluetooth_advertisement_chromeos.h +++ b/device/bluetooth/bluetooth_advertisement_chromeos.h
@@ -6,21 +6,24 @@ #define DEVICE_BLUETOOTH_BLUETOOTH_ADVERTISEMENT_CHROMEOS_H_ #include "base/macros.h" -#include "chromeos/dbus/bluetooth_le_advertisement_service_provider.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_advertisement.h" #include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.h" + +namespace bluez { +class BluetoothLEAdvertisementServiceProvider; +} namespace chromeos { -class BluetoothLEAdvertisementServiceProvider; class BluetoothAdapterChromeOS; // The BluetoothAdvertisementChromeOS class implements BluetoothAdvertisement // for the Chrome OS platform. class DEVICE_BLUETOOTH_EXPORT BluetoothAdvertisementChromeOS : public device::BluetoothAdvertisement, - public BluetoothLEAdvertisementServiceProvider::Delegate { + public bluez::BluetoothLEAdvertisementServiceProvider::Delegate { public: BluetoothAdvertisementChromeOS( scoped_ptr<device::BluetoothAdvertisement::Data> data, @@ -30,7 +33,7 @@ void Unregister(const SuccessCallback& success_callback, const ErrorCallback& error_callback) override; - // BluetoothLEAdvertisementServiceProvider::Delegate overrides: + // bluez::BluetoothLEAdvertisementServiceProvider::Delegate overrides: void Released() override; void Register( @@ -40,7 +43,7 @@ // Used from tests to be able to trigger events on the fake advertisement // provider. - BluetoothLEAdvertisementServiceProvider* provider() { + bluez::BluetoothLEAdvertisementServiceProvider* provider() { return provider_.get(); } @@ -49,7 +52,7 @@ // Adapter this advertisement is advertising on. scoped_refptr<BluetoothAdapterChromeOS> adapter_; - scoped_ptr<BluetoothLEAdvertisementServiceProvider> provider_; + scoped_ptr<bluez::BluetoothLEAdvertisementServiceProvider> provider_; DISALLOW_COPY_AND_ASSIGN(BluetoothAdvertisementChromeOS); };
diff --git a/device/bluetooth/bluetooth_advertisement_chromeos_unittest.cc b/device/bluetooth/bluetooth_advertisement_chromeos_unittest.cc index 02fe1e4a..165dc8d9 100644 --- a/device/bluetooth/bluetooth_advertisement_chromeos_unittest.cc +++ b/device/bluetooth/bluetooth_advertisement_chromeos_unittest.cc
@@ -9,12 +9,12 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/bluetooth_advertisement.h" #include "device/bluetooth/bluetooth_advertisement_chromeos.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.h" #include "testing/gtest/include/gtest/gtest.h" using device::BluetoothAdapter; @@ -52,7 +52,7 @@ class BluetoothAdvertisementChromeOSTest : public testing::Test { public: void SetUp() override { - DBusThreadManager::Initialize(); + bluez::BluezDBusManager::Initialize(NULL, true); callback_count_ = 0; error_callback_count_ = 0; @@ -70,7 +70,7 @@ // The adapter should outlive the advertisement. advertisement_ = nullptr; adapter_ = nullptr; - DBusThreadManager::Shutdown(); + bluez::BluezDBusManager::Shutdown(); } // Gets the existing Bluetooth adapter. @@ -134,8 +134,8 @@ void TriggerReleased(scoped_refptr<BluetoothAdvertisement> advertisement) { BluetoothAdvertisementChromeOS* adv = static_cast<BluetoothAdvertisementChromeOS*>(advertisement.get()); - FakeBluetoothLEAdvertisementServiceProvider* provider = - static_cast<FakeBluetoothLEAdvertisementServiceProvider*>( + bluez::FakeBluetoothLEAdvertisementServiceProvider* provider = + static_cast<bluez::FakeBluetoothLEAdvertisementServiceProvider*>( adv->provider()); provider->Release(); }
diff --git a/device/bluetooth/bluetooth_audio_sink_chromeos.cc b/device/bluetooth/bluetooth_audio_sink_chromeos.cc index 18ab219..9bb4b60 100644 --- a/device/bluetooth/bluetooth_audio_sink_chromeos.cc +++ b/device/bluetooth/bluetooth_audio_sink_chromeos.cc
@@ -14,9 +14,9 @@ #include "base/debug/stack_trace.h" #include "base/files/file_util.h" #include "base/logging.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "dbus/message.h" #include "device/bluetooth/bluetooth_adapter_chromeos.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" using dbus::ObjectPath; using device::BluetoothAudioSink; @@ -94,17 +94,17 @@ CHECK(adapter_.get()); CHECK(adapter_->IsPresent()); - CHECK(DBusThreadManager::IsInitialized()); + CHECK(bluez::BluezDBusManager::IsInitialized()); adapter_->AddObserver(this); - BluetoothMediaClient* media = - DBusThreadManager::Get()->GetBluetoothMediaClient(); + bluez::BluetoothMediaClient* media = + bluez::BluezDBusManager::Get()->GetBluetoothMediaClient(); CHECK(media); media->AddObserver(this); - BluetoothMediaTransportClient* transport = - DBusThreadManager::Get()->GetBluetoothMediaTransportClient(); + bluez::BluetoothMediaTransportClient* transport = + bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient(); CHECK(transport); transport->AddObserver(this); @@ -123,13 +123,13 @@ adapter_->RemoveObserver(this); - BluetoothMediaClient* media = - DBusThreadManager::Get()->GetBluetoothMediaClient(); + bluez::BluetoothMediaClient* media = + bluez::BluezDBusManager::Get()->GetBluetoothMediaClient(); CHECK(media); media->RemoveObserver(this); - BluetoothMediaTransportClient* transport = - DBusThreadManager::Get()->GetBluetoothMediaTransportClient(); + bluez::BluetoothMediaTransportClient* transport = + bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient(); CHECK(transport); transport->RemoveObserver(this); } @@ -139,11 +139,11 @@ const device::BluetoothAudioSink::ErrorCallback& error_callback) { VLOG(1) << "Unregister"; - if (!DBusThreadManager::IsInitialized()) + if (!bluez::BluezDBusManager::IsInitialized()) error_callback.Run(BluetoothAudioSink::ERROR_NOT_UNREGISTERED); - BluetoothMediaClient* media = - DBusThreadManager::Get()->GetBluetoothMediaClient(); + bluez::BluetoothMediaClient* media = + bluez::BluezDBusManager::Get()->GetBluetoothMediaClient(); CHECK(media); media->UnregisterEndpoint( @@ -185,27 +185,28 @@ DCHECK_EQ(state_, BluetoothAudioSink::STATE_DISCONNECTED); // Gets system bus. - dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus(); + dbus::Bus* system_bus = bluez::BluezDBusManager::Get()->GetSystemBus(); // Creates a Media Endpoint with newly-generated path. endpoint_path_ = GenerateEndpointPath(); - media_endpoint_.reset(BluetoothMediaEndpointServiceProvider::Create( + media_endpoint_.reset(bluez::BluetoothMediaEndpointServiceProvider::Create( system_bus, endpoint_path_, this)); DCHECK(media_endpoint_.get()); // Creates endpoint properties with |options|. options_ = options; - chromeos::BluetoothMediaClient::EndpointProperties endpoint_properties; - endpoint_properties.uuid = BluetoothMediaClient::kBluetoothAudioSinkUUID; + bluez::BluetoothMediaClient::EndpointProperties endpoint_properties; + endpoint_properties.uuid = + bluez::BluetoothMediaClient::kBluetoothAudioSinkUUID; endpoint_properties.codec = options_.codec; endpoint_properties.capabilities = options_.capabilities; media_path_ = static_cast<BluetoothAdapterChromeOS*>( adapter_.get())->object_path(); - BluetoothMediaClient* media = - DBusThreadManager::Get()->GetBluetoothMediaClient(); + bluez::BluetoothMediaClient* media = + bluez::BluezDBusManager::Get()->GetBluetoothMediaClient(); CHECK(media); media->RegisterEndpoint( media_path_, @@ -217,7 +218,7 @@ weak_ptr_factory_.GetWeakPtr(), error_callback)); } -BluetoothMediaEndpointServiceProvider* +bluez::BluetoothMediaEndpointServiceProvider* BluetoothAudioSinkChromeOS::GetEndpointServiceProvider() { return media_endpoint_.get(); } @@ -279,21 +280,21 @@ VLOG(1) << "MediaTransportPropertyChanged: " << property_name; // Retrieves the property set of the transport object with |object_path|. - BluetoothMediaTransportClient::Properties* properties = - DBusThreadManager::Get() + bluez::BluetoothMediaTransportClient::Properties* properties = + bluez::BluezDBusManager::Get() ->GetBluetoothMediaTransportClient() ->GetProperties(object_path); // Dispatches a property changed event to the corresponding handler. if (property_name == properties->state.name()) { if (properties->state.value() == - BluetoothMediaTransportClient::kStateIdle) { + bluez::BluetoothMediaTransportClient::kStateIdle) { StateChanged(BluetoothAudioSink::STATE_IDLE); } else if (properties->state.value() == - BluetoothMediaTransportClient::kStatePending) { + bluez::BluetoothMediaTransportClient::kStatePending) { StateChanged(BluetoothAudioSink::STATE_PENDING); } else if (properties->state.value() == - BluetoothMediaTransportClient::kStateActive) { + bluez::BluetoothMediaTransportClient::kStateActive) { StateChanged(BluetoothAudioSink::STATE_ACTIVE); } } else if (property_name == properties->volume.name()) { @@ -308,7 +309,7 @@ transport_path_ = transport_path; // The initial state for a connection should be "idle". - if (properties.state != BluetoothMediaTransportClient::kStateIdle) { + if (properties.state != bluez::BluetoothMediaTransportClient::kStateIdle) { VLOG(1) << "SetConfiugration - unexpected state :" << properties.state; return; } @@ -355,7 +356,7 @@ read_has_failed_ = false; - DBusThreadManager::Get()->GetBluetoothMediaTransportClient()->Acquire( + bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient()->Acquire( transport_path_, base::Bind(&BluetoothAudioSinkChromeOS::OnAcquireSucceeded, weak_ptr_factory_.GetWeakPtr()),
diff --git a/device/bluetooth/bluetooth_audio_sink_chromeos.h b/device/bluetooth/bluetooth_audio_sink_chromeos.h index 6261ace2..750b31d 100644 --- a/device/bluetooth/bluetooth_audio_sink_chromeos.h +++ b/device/bluetooth/bluetooth_audio_sink_chromeos.h
@@ -14,14 +14,14 @@ #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" #include "base/observer_list.h" -#include "chromeos/dbus/bluetooth_media_client.h" -#include "chromeos/dbus/bluetooth_media_endpoint_service_provider.h" -#include "chromeos/dbus/bluetooth_media_transport_client.h" #include "dbus/file_descriptor.h" #include "dbus/object_path.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_audio_sink.h" #include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_media_client.h" +#include "device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.h" +#include "device/bluetooth/dbus/bluetooth_media_transport_client.h" namespace chromeos { @@ -30,9 +30,9 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAudioSinkChromeOS : public device::BluetoothAudioSink, public device::BluetoothAdapter::Observer, - public BluetoothMediaClient::Observer, - public BluetoothMediaTransportClient::Observer, - public BluetoothMediaEndpointServiceProvider::Delegate, + public bluez::BluetoothMediaClient::Observer, + public bluez::BluetoothMediaTransportClient::Observer, + public bluez::BluetoothMediaEndpointServiceProvider::Delegate, public base::MessageLoopForIO::Watcher { public: explicit BluetoothAudioSinkChromeOS( @@ -61,7 +61,7 @@ // Returns a pointer to the media endpoint object. This function should be // used for testing purpose only. - BluetoothMediaEndpointServiceProvider* GetEndpointServiceProvider(); + bluez::BluetoothMediaEndpointServiceProvider* GetEndpointServiceProvider(); private: ~BluetoothAudioSinkChromeOS() override; @@ -72,15 +72,15 @@ void AdapterPoweredChanged(device::BluetoothAdapter* adapter, bool powered) override; - // BluetoothMediaClient::Observer overrides. + // bluez::BluetoothMediaClient::Observer overrides. void MediaRemoved(const dbus::ObjectPath& object_path) override; - // BluetoothMediaTransportClient::Observer overrides. + // bluez::BluetoothMediaTransportClient::Observer overrides. void MediaTransportRemoved(const dbus::ObjectPath& object_path) override; void MediaTransportPropertyChanged(const dbus::ObjectPath& object_path, const std::string& property_name) override; - // BluetoothMediaEndpointServiceProvider::Delegate overrides. + // bluez::BluetoothMediaEndpointServiceProvider::Delegate overrides. void SetConfiguration(const dbus::ObjectPath& transport_path, const TransportProperties& properties) override; void SelectConfiguration( @@ -204,7 +204,7 @@ device::BluetoothAudioSink::Options options_; // Media Endpoint object owned by the audio sink object. - scoped_ptr<BluetoothMediaEndpointServiceProvider> media_endpoint_; + scoped_ptr<bluez::BluetoothMediaEndpointServiceProvider> media_endpoint_; // List of observers interested in event notifications from us. Objects in // |observers_| are expected to outlive a BluetoothAudioSinkChromeOS object.
diff --git a/device/bluetooth/bluetooth_audio_sink_chromeos_unittest.cc b/device/bluetooth/bluetooth_audio_sink_chromeos_unittest.cc index a585f3d4..5f51cb8a0 100644 --- a/device/bluetooth/bluetooth_audio_sink_chromeos_unittest.cc +++ b/device/bluetooth/bluetooth_audio_sink_chromeos_unittest.cc
@@ -8,20 +8,21 @@ #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/message_loop/message_loop.h" -#include "chromeos/dbus/bluetooth_media_client.h" -#include "chromeos/dbus/bluetooth_media_endpoint_service_provider.h" -#include "chromeos/dbus/bluetooth_media_transport_client.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_media_client.h" -#include "chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h" -#include "chromeos/dbus/fake_bluetooth_media_transport_client.h" #include "dbus/object_path.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/bluetooth_audio_sink.h" #include "device/bluetooth/bluetooth_audio_sink_chromeos.h" +#include "device/bluetooth/dbus/bluetooth_media_client.h" +#include "device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.h" +#include "device/bluetooth/dbus/bluetooth_media_transport_client.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_media_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h" +#include "device/bluetooth/dbus/fake_bluetooth_media_transport_client.h" #include "testing/gtest/include/gtest/gtest.h" +using bluez::FakeBluetoothMediaTransportClient; using dbus::ObjectPath; using device::BluetoothAdapter; using device::BluetoothAdapterFactory; @@ -81,26 +82,26 @@ class BluetoothAudioSinkChromeOSTest : public testing::Test { public: void SetUp() override { - DBusThreadManager::Initialize(); + bluez::BluezDBusManager::Initialize(NULL, true); callback_count_ = 0; error_callback_count_ = 0; - fake_media_ = static_cast<FakeBluetoothMediaClient*>( - DBusThreadManager::Get()->GetBluetoothMediaClient()); + fake_media_ = static_cast<bluez::FakeBluetoothMediaClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothMediaClient()); fake_transport_ = static_cast<FakeBluetoothMediaTransportClient*>( - DBusThreadManager::Get()->GetBluetoothMediaTransportClient()); + bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient()); // Initiates Delegate::TransportProperties with default values. properties_.device = ObjectPath(FakeBluetoothMediaTransportClient::kTransportDevicePath); - properties_.uuid = BluetoothMediaClient::kBluetoothAudioSinkUUID; + properties_.uuid = bluez::BluetoothMediaClient::kBluetoothAudioSinkUUID; properties_.codec = FakeBluetoothMediaTransportClient::kTransportCodec; properties_.configuration = std::vector<uint8_t>( FakeBluetoothMediaTransportClient::kTransportConfiguration, FakeBluetoothMediaTransportClient::kTransportConfiguration + FakeBluetoothMediaTransportClient::kTransportConfigurationLength); - properties_.state = BluetoothMediaTransportClient::kStateIdle; + properties_.state = bluez::BluetoothMediaTransportClient::kStateIdle; properties_.delay.reset( new uint16_t(FakeBluetoothMediaTransportClient::kTransportDelay)); properties_.volume.reset( @@ -119,7 +120,7 @@ // The adapter should outlive audio sink. audio_sink_ = nullptr; adapter_ = nullptr; - DBusThreadManager::Shutdown(); + bluez::BluezDBusManager::Shutdown(); } // Gets the existing Bluetooth adapter. @@ -180,8 +181,9 @@ static_cast<BluetoothAudioSinkChromeOS*>(audio_sink_.get()); ASSERT_NE(audio_sink_chromeos, nullptr); - media_endpoint_ = static_cast<FakeBluetoothMediaEndpointServiceProvider*>( - audio_sink_chromeos->GetEndpointServiceProvider()); + media_endpoint_ = + static_cast<bluez::FakeBluetoothMediaEndpointServiceProvider*>( + audio_sink_chromeos->GetEndpointServiceProvider()); } // Called whenever RegisterAudioSink is completed successfully. @@ -233,16 +235,16 @@ base::MessageLoopForIO message_loop_; - FakeBluetoothMediaClient* fake_media_; + bluez::FakeBluetoothMediaClient* fake_media_; FakeBluetoothMediaTransportClient* fake_transport_; - FakeBluetoothMediaEndpointServiceProvider* media_endpoint_; + bluez::FakeBluetoothMediaEndpointServiceProvider* media_endpoint_; scoped_ptr<TestAudioSinkObserver> observer_; scoped_refptr<BluetoothAdapter> adapter_; scoped_refptr<BluetoothAudioSink> audio_sink_; // The default property set used while calling SetConfiguration on a media // endpoint object. - BluetoothMediaEndpointServiceProvider::Delegate::TransportProperties + bluez::BluetoothMediaEndpointServiceProvider::Delegate::TransportProperties properties_; };
diff --git a/device/bluetooth/bluetooth_chromeos_unittest.cc b/device/bluetooth/bluetooth_chromeos_unittest.cc index 49b5b59..cea92d9 100644 --- a/device/bluetooth/bluetooth_chromeos_unittest.cc +++ b/device/bluetooth/bluetooth_chromeos_unittest.cc
@@ -6,12 +6,6 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_adapter_client.h" -#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" -#include "chromeos/dbus/fake_bluetooth_device_client.h" -#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h" -#include "chromeos/dbus/fake_bluetooth_input_client.h" #include "dbus/object_path.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_adapter_chromeos.h" @@ -20,6 +14,12 @@ #include "device/bluetooth/bluetooth_device_chromeos.h" #include "device/bluetooth/bluetooth_discovery_session.h" #include "device/bluetooth/bluetooth_pairing_chromeos.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_device_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_input_client.h" #include "device/bluetooth/test/test_bluetooth_adapter_observer.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -57,17 +57,18 @@ } class FakeBluetoothProfileServiceProviderDelegate - : public chromeos::BluetoothProfileServiceProvider::Delegate { + : public bluez::BluetoothProfileServiceProvider::Delegate { public: FakeBluetoothProfileServiceProviderDelegate() {} - // BluetoothProfileServiceProvider::Delegate: + // bluez::BluetoothProfileServiceProvider::Delegate: void Released() override {} - void NewConnection(const dbus::ObjectPath&, - scoped_ptr<dbus::FileDescriptor>, - const BluetoothProfileServiceProvider::Delegate::Options&, - const ConfirmationCallback&) override {} + void NewConnection( + const dbus::ObjectPath&, + scoped_ptr<dbus::FileDescriptor>, + const bluez::BluetoothProfileServiceProvider::Delegate::Options&, + const ConfirmationCallback&) override {} void RequestDisconnection(const dbus::ObjectPath&, const ConfirmationCallback&) override {} @@ -165,25 +166,28 @@ class BluetoothChromeOSTest : public testing::Test { public: void SetUp() override { - scoped_ptr<DBusThreadManagerSetter> dbus_setter = - chromeos::DBusThreadManager::GetSetterForTesting(); - // We need to initialize DBusThreadManager early to prevent + scoped_ptr<bluez::BluezDBusManagerSetter> dbus_setter = + bluez::BluezDBusManager::GetSetterForTesting(); + // We need to initialize BluezDBusManager early to prevent // Bluetooth*::Create() methods from picking the real instead of fake // implementations. - fake_bluetooth_adapter_client_ = new FakeBluetoothAdapterClient; + fake_bluetooth_adapter_client_ = new bluez::FakeBluetoothAdapterClient; dbus_setter->SetBluetoothAdapterClient( - scoped_ptr<BluetoothAdapterClient>(fake_bluetooth_adapter_client_)); - fake_bluetooth_device_client_ = new FakeBluetoothDeviceClient; + scoped_ptr<bluez::BluetoothAdapterClient>( + fake_bluetooth_adapter_client_)); + fake_bluetooth_device_client_ = new bluez::FakeBluetoothDeviceClient; dbus_setter->SetBluetoothDeviceClient( - scoped_ptr<BluetoothDeviceClient>(fake_bluetooth_device_client_)); + scoped_ptr<bluez::BluetoothDeviceClient>( + fake_bluetooth_device_client_)); dbus_setter->SetBluetoothInputClient( - scoped_ptr<BluetoothInputClient>(new FakeBluetoothInputClient)); + scoped_ptr<bluez::BluetoothInputClient>( + new bluez::FakeBluetoothInputClient)); dbus_setter->SetBluetoothAgentManagerClient( - scoped_ptr<BluetoothAgentManagerClient>( - new FakeBluetoothAgentManagerClient)); + scoped_ptr<bluez::BluetoothAgentManagerClient>( + new bluez::FakeBluetoothAgentManagerClient)); dbus_setter->SetBluetoothGattServiceClient( - scoped_ptr<BluetoothGattServiceClient>( - new FakeBluetoothGattServiceClient)); + scoped_ptr<bluez::BluetoothGattServiceClient>( + new bluez::FakeBluetoothGattServiceClient)); fake_bluetooth_adapter_client_->SetSimulationIntervalMs(10); @@ -208,7 +212,7 @@ } discovery_sessions_.clear(); adapter_ = nullptr; - DBusThreadManager::Shutdown(); + bluez::BluezDBusManager::Shutdown(); } // Generic callbacks @@ -337,8 +341,8 @@ protected: base::MessageLoop message_loop_; - FakeBluetoothAdapterClient* fake_bluetooth_adapter_client_; - FakeBluetoothDeviceClient* fake_bluetooth_device_client_; + bluez::FakeBluetoothAdapterClient* fake_bluetooth_adapter_client_; + bluez::FakeBluetoothDeviceClient* fake_bluetooth_device_client_; scoped_refptr<BluetoothAdapter> adapter_; int callback_count_; @@ -366,7 +370,7 @@ // and initializes with an existing adapter if there is one. EXPECT_TRUE(adapter_->IsPresent()); EXPECT_FALSE(adapter_->IsPowered()); - EXPECT_EQ(FakeBluetoothAdapterClient::kAdapterAddress, + EXPECT_EQ(bluez::FakeBluetoothAdapterClient::kAdapterAddress, adapter_->GetAddress()); EXPECT_FALSE(adapter_->IsDiscovering()); @@ -375,12 +379,14 @@ EXPECT_EQ(2U, devices.size()); // |devices| are not ordered, verify it contains the 2 device addresses. - EXPECT_NE(-1, GetDeviceIndexByAddress( - devices, FakeBluetoothDeviceClient::kPairedDeviceAddress)); - EXPECT_NE(-1, - GetDeviceIndexByAddress( - devices, - FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress)); + EXPECT_NE( + -1, GetDeviceIndexByAddress( + devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress)); + EXPECT_NE( + -1, + GetDeviceIndexByAddress( + devices, + bluez::FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress)); } TEST_F(BluetoothChromeOSTest, BecomePresent) { @@ -401,7 +407,7 @@ // We should have had a device announced. EXPECT_EQ(2, observer.device_added_count()); - EXPECT_EQ(FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress, + EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress, observer.last_device_address()); // Other callbacks shouldn't be called if the values are false. @@ -430,10 +436,10 @@ EXPECT_EQ(2, observer.device_removed_count()); // 2 possibilities for the last device here. std::string address = observer.last_device_address(); - EXPECT_TRUE( - address.compare( - FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress) == 0 || - address.compare(FakeBluetoothDeviceClient::kPairedDeviceAddress) == 0); + EXPECT_TRUE(address.compare(bluez::FakeBluetoothDeviceClient:: + kPairedUnconnectableDeviceAddress) == 0 || + address.compare( + bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress) == 0); // Other callbacks shouldn't be called since the values are false. EXPECT_EQ(0, observer.powered_changed_count()); @@ -455,7 +461,7 @@ EXPECT_EQ(0, observer.present_changed_count()); EXPECT_TRUE(adapter_->IsPresent()); - EXPECT_EQ(FakeBluetoothAdapterClient::kAdapterAddress, + EXPECT_EQ(bluez::FakeBluetoothAdapterClient::kAdapterAddress, adapter_->GetAddress()); // Try removing the first adapter, we should now act as if the adapter @@ -472,10 +478,10 @@ // As BluetoothAdapter devices removal does not keep the order of adding them, // 2 possibilities for the last device here. std::string address = observer.last_device_address(); - EXPECT_TRUE( - address.compare( - FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress) == 0 || - address.compare(FakeBluetoothDeviceClient::kPairedDeviceAddress) == 0); + EXPECT_TRUE(address.compare(bluez::FakeBluetoothDeviceClient:: + kPairedUnconnectableDeviceAddress) == 0 || + address.compare( + bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress) == 0); // Other callbacks shouldn't be called since the values are false. EXPECT_EQ(0, observer.powered_changed_count()); @@ -745,7 +751,7 @@ message_loop_.Run(); EXPECT_EQ(2, observer.device_added_count()); - EXPECT_EQ(FakeBluetoothDeviceClient::kLowEnergyAddress, + EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress, observer.last_device_address()); // Next we should get another two devices... @@ -757,7 +763,7 @@ message_loop_.Run(); EXPECT_EQ(1, observer.device_removed_count()); - EXPECT_EQ(FakeBluetoothDeviceClient::kVanishingDeviceAddress, + EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kVanishingDeviceAddress, observer.last_device_address()); } @@ -777,7 +783,7 @@ // Stop the timers that the simulation uses fake_bluetooth_device_client_->EndDiscoverySimulation( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath)); ASSERT_TRUE(adapter_->IsPowered()); ASSERT_TRUE(adapter_->IsDiscovering()); @@ -971,21 +977,23 @@ // Stop the timers that the simulation uses fake_bluetooth_device_client_->EndDiscoverySimulation( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath)); ASSERT_TRUE(adapter_->IsPowered()); ASSERT_TRUE(adapter_->IsDiscovering()); // Stop device discovery behind the adapter. The adapter and the observer // should be notified of the change and the reference count should be reset. - // Even though FakeBluetoothAdapterClient does its own reference counting and + // Even though bluez::FakeBluetoothAdapterClient does its own reference + // counting and // we called 3 BluetoothAdapter::StartDiscoverySession 3 times, the - // FakeBluetoothAdapterClient's count should be only 1 and a single call to - // FakeBluetoothAdapterClient::StopDiscovery should work. + // bluez::FakeBluetoothAdapterClient's count should be only 1 and a single + // call to + // bluez::FakeBluetoothAdapterClient::StopDiscovery should work. fake_bluetooth_adapter_client_->StopDiscovery( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), GetCallback(), - base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, - base::Unretained(this))); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, + base::Unretained(this))); message_loop_.Run(); EXPECT_EQ(2, observer.discovering_changed_count()); EXPECT_EQ(4, callback_count_); @@ -1018,7 +1026,7 @@ EXPECT_TRUE(discovery_sessions_[i]->IsActive()); fake_bluetooth_device_client_->EndDiscoverySimulation( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath)); // Make the adapter disappear and appear. This will make it come back as // discovering. When this happens, the reference count should become and @@ -1043,7 +1051,8 @@ EXPECT_TRUE(observer.last_discovering()); EXPECT_TRUE(adapter_->IsDiscovering()); - // Start and stop discovery. At this point, FakeBluetoothAdapterClient has + // Start and stop discovery. At this point, bluez::FakeBluetoothAdapterClient + // has // a reference count that is equal to 1. Pretend that this was done by an // application other than us. Starting and stopping discovery will succeed // but it won't cause the discovery state to change. @@ -1088,9 +1097,9 @@ // the discovery state won't change since our BluetoothAdapter also just // requested it via D-Bus. fake_bluetooth_adapter_client_->StopDiscovery( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), GetCallback(), - base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, - base::Unretained(this))); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, + base::Unretained(this))); message_loop_.Run(); EXPECT_EQ(5, observer.discovering_changed_count()); EXPECT_EQ(10, callback_count_); @@ -1149,7 +1158,7 @@ // Stop the timers that the simulation uses fake_bluetooth_device_client_->EndDiscoverySimulation( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath)); ASSERT_TRUE(adapter_->IsPowered()); ASSERT_TRUE(adapter_->IsDiscovering()); @@ -1166,9 +1175,9 @@ // memory errors as the sessions that we explicitly deleted should get // cleaned up. fake_bluetooth_adapter_client_->StopDiscovery( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), GetCallback(), - base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, - base::Unretained(this))); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, + base::Unretained(this))); message_loop_.Run(); EXPECT_EQ(2, observer.discovering_changed_count()); EXPECT_EQ(4, callback_count_); @@ -1201,7 +1210,7 @@ EXPECT_EQ(0, callback_count_); fake_bluetooth_device_client_->EndDiscoverySimulation( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath)); // The underlying adapter has started discovery, but our call hasn't returned // yet. @@ -2119,14 +2128,15 @@ ASSERT_EQ(2U, devices.size()); int idx = GetDeviceIndexByAddress( - devices, FakeBluetoothDeviceClient::kPairedDeviceAddress); + devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); ASSERT_NE(-1, idx); - ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress, + ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress, devices[idx]->GetAddress()); // Verify the other device properties. - EXPECT_EQ(base::UTF8ToUTF16(FakeBluetoothDeviceClient::kPairedDeviceName), - devices[idx]->GetName()); + EXPECT_EQ( + base::UTF8ToUTF16(bluez::FakeBluetoothDeviceClient::kPairedDeviceName), + devices[idx]->GetName()); EXPECT_EQ(BluetoothDevice::DEVICE_COMPUTER, devices[idx]->GetDeviceType()); EXPECT_TRUE(devices[idx]->IsPaired()); EXPECT_FALSE(devices[idx]->IsConnected()); @@ -2155,7 +2165,7 @@ ASSERT_EQ(2U, devices.size()); int idx = GetDeviceIndexByAddress( - devices, FakeBluetoothDeviceClient::kPairedDeviceAddress); + devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); ASSERT_NE(-1, idx); ASSERT_EQ(BluetoothDevice::DEVICE_COMPUTER, devices[idx]->GetDeviceType()); @@ -2163,9 +2173,9 @@ // we change the class of the device. TestBluetoothAdapterObserver observer(adapter_); - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kPairedDevicePath)); properties->bluetooth_class.ReplaceValue(0x002580); @@ -2183,20 +2193,21 @@ ASSERT_EQ(2U, devices.size()); int idx = GetDeviceIndexByAddress( - devices, FakeBluetoothDeviceClient::kPairedDeviceAddress); + devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); ASSERT_NE(-1, idx); - ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress, + ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress, devices[idx]->GetAddress()); - ASSERT_EQ(base::UTF8ToUTF16(FakeBluetoothDeviceClient::kPairedDeviceName), - devices[idx]->GetName()); + ASSERT_EQ( + base::UTF8ToUTF16(bluez::FakeBluetoothDeviceClient::kPairedDeviceName), + devices[idx]->GetName()); // Install an observer; expect the DeviceChanged method to be called when // we change the alias of the device. TestBluetoothAdapterObserver observer(adapter_); - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kPairedDevicePath)); static const std::string new_name("New Device Name"); properties->alias.ReplaceValue(new_name); @@ -2215,20 +2226,21 @@ ASSERT_EQ(2U, devices.size()); int idx = GetDeviceIndexByAddress( - devices, FakeBluetoothDeviceClient::kPairedDeviceAddress); + devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); ASSERT_NE(-1, idx); - ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress, + ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress, devices[idx]->GetAddress()); - ASSERT_EQ(base::UTF8ToUTF16(FakeBluetoothDeviceClient::kPairedDeviceName), - devices[idx]->GetName()); + ASSERT_EQ( + base::UTF8ToUTF16(bluez::FakeBluetoothDeviceClient::kPairedDeviceName), + devices[idx]->GetName()); // Install an observer; expect the DeviceAddressChanged method to be called // when we change the alias of the device. TestBluetoothAdapterObserver observer(adapter_); - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kPairedDevicePath)); static const char* kNewAddress = "D9:1F:FC:11:22:33"; properties->address.ReplaceValue(kNewAddress); @@ -2248,9 +2260,9 @@ ASSERT_EQ(2U, devices.size()); int idx = GetDeviceIndexByAddress( - devices, FakeBluetoothDeviceClient::kPairedDeviceAddress); + devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); ASSERT_NE(-1, idx); - ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress, + ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress, devices[idx]->GetAddress()); BluetoothDevice::UUIDList uuids = devices[idx]->GetUUIDs(); @@ -2262,9 +2274,9 @@ // we change the class of the device. TestBluetoothAdapterObserver observer(adapter_); - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kPairedDevicePath)); std::vector<std::string> new_uuids; new_uuids.push_back(uuids[0].canonical_value()); @@ -2297,12 +2309,12 @@ ASSERT_EQ(2U, devices.size()); int idx = GetDeviceIndexByAddress( - devices, FakeBluetoothDeviceClient::kPairedDeviceAddress); + devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); ASSERT_NE(-1, idx); - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kPairedDevicePath)); // During discovery, rssi is a valid value (-75) properties->rssi.ReplaceValue(-75); @@ -2334,12 +2346,12 @@ ASSERT_EQ(2U, devices.size()); int idx = GetDeviceIndexByAddress( - devices, FakeBluetoothDeviceClient::kPairedDeviceAddress); + devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); ASSERT_NE(-1, idx); - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kPairedDevicePath)); // During discovery, tx_power is a valid value (0) properties->tx_power.ReplaceValue(0); @@ -2369,9 +2381,9 @@ ASSERT_EQ(2U, devices.size()); int idx = GetDeviceIndexByAddress( - devices, FakeBluetoothDeviceClient::kPairedDeviceAddress); + devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); ASSERT_NE(-1, idx); - ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress, + ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress, devices[idx]->GetAddress()); std::string address = devices[idx]->GetAddress(); @@ -2395,8 +2407,8 @@ GetAdapter(); DiscoverDevices(); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kConnectUnpairableAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kConnectUnpairableAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -2413,9 +2425,9 @@ ASSERT_FALSE(device->IsConnecting()); // Make sure the trusted property has been set to true. - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kConnectUnpairablePath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kConnectUnpairablePath)); ASSERT_TRUE(properties->trusted.value()); // Install an observer; expect the DeviceRemoved method to be called @@ -2426,20 +2438,20 @@ EXPECT_EQ(0, error_callback_count_); EXPECT_EQ(1, observer.device_removed_count()); - EXPECT_EQ(FakeBluetoothDeviceClient::kConnectUnpairableAddress, + EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kConnectUnpairableAddress, observer.last_device_address()); // GetDevices shouldn't return the device either. - device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kConnectUnpairableAddress); + device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kConnectUnpairableAddress); EXPECT_FALSE(device != nullptr); } TEST_F(BluetoothChromeOSTest, ConnectPairedDevice) { GetAdapter(); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kPairedDeviceAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); ASSERT_TRUE(device != nullptr); ASSERT_TRUE(device->IsPaired()); @@ -2467,8 +2479,8 @@ GetAdapter(); DiscoverDevices(); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kConnectUnpairableAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kConnectUnpairableAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -2492,9 +2504,9 @@ EXPECT_FALSE(device->IsConnecting()); // Make sure the trusted property has been set to true. - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kConnectUnpairablePath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kConnectUnpairablePath)); EXPECT_TRUE(properties->trusted.value()); // Verify is a HID device and is not connectable. @@ -2507,8 +2519,8 @@ TEST_F(BluetoothChromeOSTest, ConnectConnectedDevice) { GetAdapter(); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kPairedDeviceAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); ASSERT_TRUE(device != nullptr); ASSERT_TRUE(device->IsPaired()); @@ -2545,8 +2557,8 @@ GetAdapter(); DiscoverDevices(); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kLegacyAutopairAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kLegacyAutopairAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -2571,8 +2583,8 @@ TEST_F(BluetoothChromeOSTest, DisconnectDevice) { GetAdapter(); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kPairedDeviceAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); ASSERT_TRUE(device != nullptr); ASSERT_TRUE(device->IsPaired()); @@ -2605,8 +2617,8 @@ TEST_F(BluetoothChromeOSTest, DisconnectUnconnectedDevice) { GetAdapter(); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kPairedDeviceAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); ASSERT_TRUE(device != nullptr); ASSERT_TRUE(device->IsPaired()); ASSERT_FALSE(device->IsConnected()); @@ -2630,18 +2642,20 @@ GetAdapter(); fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath( - FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDevicePath)); - BluetoothDevice* device = adapter_->GetDevice( - FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDeviceAddress); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient:: + kConnectedTrustedNotPairedDevicePath)); + BluetoothDevice* device = + adapter_->GetDevice(bluez::FakeBluetoothDeviceClient:: + kConnectedTrustedNotPairedDeviceAddress); ASSERT_TRUE(device != nullptr); // On the DBus level the device is trusted but not paired. But the current // implementation of |BluetoothDevice::IsPaired()| returns true in this case. - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( - FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDevicePath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties( + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient:: + kConnectedTrustedNotPairedDevicePath)); EXPECT_FALSE(properties->paired.value()); EXPECT_TRUE(properties->trusted.value()); ASSERT_TRUE(device->IsPaired()); @@ -2667,7 +2681,7 @@ // Make sure the paired property has been set to true. properties = fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( - FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDevicePath)); + bluez::FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDevicePath)); EXPECT_TRUE(properties->paired.value()); } @@ -2675,16 +2689,16 @@ GetAdapter(); fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath)); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kPairedDeviceAddress); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kPairedDevicePath)); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); ASSERT_TRUE(device != nullptr); // On the DBus level a device can be trusted but not paired. - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kPairedDevicePath)); EXPECT_TRUE(properties->paired.value()); EXPECT_TRUE(properties->trusted.value()); ASSERT_TRUE(device->IsPaired()); @@ -2712,8 +2726,8 @@ // The Legacy Autopair device requires no PIN or Passkey to pair because // the daemon provides 0000 to the device for us. - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kLegacyAutopairAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kLegacyAutopairAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -2750,9 +2764,9 @@ EXPECT_TRUE(device->IsConnectable()); // Make sure the trusted property has been set to true. - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kLegacyAutopairPath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kLegacyAutopairPath)); EXPECT_TRUE(properties->trusted.value()); } @@ -2763,8 +2777,8 @@ DiscoverDevices(); // Requires that we display a randomly generated PIN on the screen. - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kDisplayPinCodeAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kDisplayPinCodeAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -2803,9 +2817,9 @@ EXPECT_TRUE(device->IsConnectable()); // Make sure the trusted property has been set to true. - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kDisplayPinCodePath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kDisplayPinCodePath)); EXPECT_TRUE(properties->trusted.value()); } @@ -2817,8 +2831,8 @@ // Requires that we display a randomly generated Passkey on the screen, // and notifies us as it's typed in. - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kDisplayPasskeyAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kDisplayPasskeyAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -2878,9 +2892,9 @@ EXPECT_FALSE(device->IsConnectable()); // Make sure the trusted property has been set to true. - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kDisplayPasskeyPath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kDisplayPasskeyPath)); EXPECT_TRUE(properties->trusted.value()); } @@ -2891,8 +2905,8 @@ DiscoverDevices(); // Requires that the user enters a PIN for them. - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kRequestPinCodeAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kRequestPinCodeAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -2932,9 +2946,9 @@ EXPECT_TRUE(device->IsConnectable()); // Make sure the trusted property has been set to true. - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPinCodePath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kRequestPinCodePath)); EXPECT_TRUE(properties->trusted.value()); } @@ -2945,8 +2959,8 @@ DiscoverDevices(); // Requests that we confirm a displayed passkey. - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kConfirmPasskeyAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kConfirmPasskeyAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -2983,9 +2997,9 @@ EXPECT_TRUE(device->IsConnectable()); // Make sure the trusted property has been set to true. - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kConfirmPasskeyPath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath)); EXPECT_TRUE(properties->trusted.value()); } @@ -2997,8 +3011,8 @@ // Requires that the user enters a Passkey, this would be some kind of // device that has a display, but doesn't use "just works" - maybe a car? - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kRequestPasskeyAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -3034,9 +3048,9 @@ EXPECT_TRUE(device->IsConnectable()); // Make sure the trusted property has been set to true. - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPasskeyPath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath)); EXPECT_TRUE(properties->trusted.value()); } @@ -3049,7 +3063,7 @@ // Uses just-works pairing, since this is an outgoing pairing, no delegate // interaction is required. BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kJustWorksAddress); + adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kJustWorksAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -3081,9 +3095,9 @@ EXPECT_TRUE(device->IsConnectable()); // Make sure the trusted property has been set to true. - FakeBluetoothDeviceClient::Properties* properties = + bluez::FakeBluetoothDeviceClient::Properties* properties = fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kJustWorksPath)); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath)); EXPECT_TRUE(properties->trusted.value()); } @@ -3091,10 +3105,10 @@ fake_bluetooth_device_client_->SetSimulationIntervalMs(10); GetAdapter(); - DiscoverDevice(FakeBluetoothDeviceClient::kUnconnectableDeviceAddress); + DiscoverDevice(bluez::FakeBluetoothDeviceClient::kUnconnectableDeviceAddress); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kUnpairableDeviceAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kUnpairableDeviceAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -3125,11 +3139,11 @@ fake_bluetooth_device_client_->SetSimulationIntervalMs(10); GetAdapter(); - DiscoverDevice(FakeBluetoothDeviceClient::kVanishingDeviceAddress); + DiscoverDevice(bluez::FakeBluetoothDeviceClient::kVanishingDeviceAddress); // The vanishing device times out during pairing - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kVanishingDeviceAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kVanishingDeviceAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -3165,7 +3179,7 @@ // Everything seems to go according to plan with the unconnectable device; // it pairs, but then you can't make connections to it after. BluetoothDevice* device = adapter_->GetDevice( - FakeBluetoothDeviceClient::kUnconnectableDeviceAddress); + bluez::FakeBluetoothDeviceClient::kUnconnectableDeviceAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -3197,9 +3211,9 @@ // Make sure the trusted property has been set to true still (since pairing // worked). - FakeBluetoothDeviceClient::Properties* properties = + bluez::FakeBluetoothDeviceClient::Properties* properties = fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( - FakeBluetoothDeviceClient::kUnconnectableDevicePath)); + bluez::FakeBluetoothDeviceClient::kUnconnectableDevicePath)); EXPECT_TRUE(properties->trusted.value()); } @@ -3210,8 +3224,8 @@ DiscoverDevices(); // Reject the pairing after we receive a request for the PIN code. - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kRequestPinCodeAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kRequestPinCodeAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -3248,8 +3262,8 @@ DiscoverDevices(); // Cancel the pairing after we receive a request for the PIN code. - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kRequestPinCodeAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kRequestPinCodeAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -3286,8 +3300,8 @@ DiscoverDevices(); // Reject the pairing after we receive a request for the passkey. - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kRequestPasskeyAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -3324,8 +3338,8 @@ DiscoverDevices(); // Cancel the pairing after we receive a request for the passkey. - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kRequestPasskeyAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -3362,8 +3376,8 @@ DiscoverDevices(); // Reject the pairing after we receive a request for passkey confirmation. - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kConfirmPasskeyAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kConfirmPasskeyAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -3400,8 +3414,8 @@ DiscoverDevices(); // Cancel the pairing after we receive a request for the passkey. - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kConfirmPasskeyAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kConfirmPasskeyAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -3438,8 +3452,8 @@ DiscoverDevices(); // Cancel the pairing while we're waiting for the remote host. - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kLegacyAutopairAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kLegacyAutopairAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); @@ -3480,19 +3494,19 @@ // Requires that we provide a PIN code. fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPinCodePath)); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kRequestPinCodeAddress); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPinCodePath)); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kRequestPinCodeAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); TestBluetoothAdapterObserver observer(adapter_); fake_bluetooth_device_client_->SimulatePairing( - dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPinCodePath), true, - GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, - base::Unretained(this))); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPinCodePath), + true, GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, + base::Unretained(this))); EXPECT_EQ(1, pairing_delegate.call_count_); EXPECT_EQ(1, pairing_delegate.request_pincode_count_); @@ -3511,9 +3525,9 @@ EXPECT_TRUE(device->IsPaired()); // Make sure the trusted property has been set to true. - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPinCodePath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kRequestPinCodePath)); ASSERT_TRUE(properties->trusted.value()); // No pairing context should remain on the device. @@ -3534,19 +3548,19 @@ // Requests that we confirm a displayed passkey. fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kConfirmPasskeyPath)); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kConfirmPasskeyAddress); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath)); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kConfirmPasskeyAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); TestBluetoothAdapterObserver observer(adapter_); fake_bluetooth_device_client_->SimulatePairing( - dbus::ObjectPath(FakeBluetoothDeviceClient::kConfirmPasskeyPath), true, - GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, - base::Unretained(this))); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath), + true, GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, + base::Unretained(this))); EXPECT_EQ(1, pairing_delegate.call_count_); EXPECT_EQ(1, pairing_delegate.confirm_passkey_count_); @@ -3566,9 +3580,9 @@ EXPECT_TRUE(device->IsPaired()); // Make sure the trusted property has been set to true. - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kConfirmPasskeyPath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath)); ASSERT_TRUE(properties->trusted.value()); // No pairing context should remain on the device. @@ -3589,19 +3603,19 @@ // Requests that we provide a Passkey. fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPasskeyPath)); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kRequestPasskeyAddress); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath)); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); TestBluetoothAdapterObserver observer(adapter_); fake_bluetooth_device_client_->SimulatePairing( - dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPasskeyPath), true, - GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, - base::Unretained(this))); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath), + true, GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, + base::Unretained(this))); EXPECT_EQ(1, pairing_delegate.call_count_); EXPECT_EQ(1, pairing_delegate.request_passkey_count_); @@ -3620,9 +3634,9 @@ EXPECT_TRUE(device->IsPaired()); // Make sure the trusted property has been set to true. - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPasskeyPath)); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath)); ASSERT_TRUE(properties->trusted.value()); // No pairing context should remain on the device. @@ -3644,17 +3658,17 @@ // Uses just-works pairing so, sinec this an incoming pairing, require // authorization from the user. fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kJustWorksPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath)); BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kJustWorksAddress); + adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kJustWorksAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); TestBluetoothAdapterObserver observer(adapter_); fake_bluetooth_device_client_->SimulatePairing( - dbus::ObjectPath(FakeBluetoothDeviceClient::kJustWorksPath), true, + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath), true, GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, base::Unretained(this))); @@ -3675,9 +3689,9 @@ EXPECT_TRUE(device->IsPaired()); // Make sure the trusted property has been set to true. - FakeBluetoothDeviceClient::Properties* properties = + bluez::FakeBluetoothDeviceClient::Properties* properties = fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kJustWorksPath)); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath)); ASSERT_TRUE(properties->trusted.value()); // No pairing context should remain on the device. @@ -3694,19 +3708,19 @@ // Requires that we provide a PIN Code, without a pairing delegate, // that will be rejected. fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPinCodePath)); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kRequestPinCodeAddress); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPinCodePath)); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kRequestPinCodeAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); TestBluetoothAdapterObserver observer(adapter_); fake_bluetooth_device_client_->SimulatePairing( - dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPinCodePath), true, - GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, - base::Unretained(this))); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPinCodePath), + true, GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, + base::Unretained(this))); message_loop_.Run(); @@ -3733,19 +3747,19 @@ // Requests that we confirm a displayed passkey, without a pairing delegate, // that will be rejected. fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kConfirmPasskeyPath)); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kConfirmPasskeyAddress); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath)); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kConfirmPasskeyAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); TestBluetoothAdapterObserver observer(adapter_); fake_bluetooth_device_client_->SimulatePairing( - dbus::ObjectPath(FakeBluetoothDeviceClient::kConfirmPasskeyPath), true, - GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, - base::Unretained(this))); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath), + true, GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, + base::Unretained(this))); message_loop_.Run(); @@ -3772,19 +3786,19 @@ // Requests that we provide a displayed passkey, without a pairing delegate, // that will be rejected. fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPasskeyPath)); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kRequestPasskeyAddress); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath)); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); TestBluetoothAdapterObserver observer(adapter_); fake_bluetooth_device_client_->SimulatePairing( - dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPasskeyPath), true, - GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, - base::Unretained(this))); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath), + true, GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, + base::Unretained(this))); message_loop_.Run(); @@ -3811,17 +3825,17 @@ // Uses just-works pairing and thus requires authorization for incoming // pairings, without a pairing delegate, that will be rejected. fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kJustWorksPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath)); BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kJustWorksAddress); + adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kJustWorksAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); TestBluetoothAdapterObserver observer(adapter_); fake_bluetooth_device_client_->SimulatePairing( - dbus::ObjectPath(FakeBluetoothDeviceClient::kJustWorksPath), true, + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath), true, GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, base::Unretained(this))); @@ -3854,19 +3868,19 @@ // Requests that we provide a Passkey. fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPasskeyPath)); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kRequestPasskeyAddress); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath)); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress); ASSERT_TRUE(device != nullptr); ASSERT_FALSE(device->IsPaired()); TestBluetoothAdapterObserver observer(adapter_); fake_bluetooth_device_client_->SimulatePairing( - dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPasskeyPath), true, - GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, - base::Unretained(this))); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath), + true, GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, + base::Unretained(this))); EXPECT_EQ(1, pairing_delegate.call_count_); EXPECT_EQ(1, pairing_delegate.request_passkey_count_); @@ -3897,11 +3911,11 @@ // Use the built-in paired device for this test, grab its Properties // structure so we can adjust the underlying modalias property. - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kPairedDeviceAddress); - FakeBluetoothDeviceClient::Properties* properties = - fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath)); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); + bluez::FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath( + bluez::FakeBluetoothDeviceClient::kPairedDevicePath)); ASSERT_TRUE(device != nullptr); ASSERT_TRUE(properties != nullptr); @@ -3949,8 +3963,8 @@ TEST_F(BluetoothChromeOSTest, GetConnectionInfoForDisconnectedDevice) { GetAdapter(); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kPairedDeviceAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); // Calling GetConnectionInfo for an unconnected device should return a result // in which all fields are filled with BluetoothDevice::kUnknownPower. @@ -3965,8 +3979,8 @@ TEST_F(BluetoothChromeOSTest, GetConnectionInfoForConnectedDevice) { GetAdapter(); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kPairedDeviceAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); device->Connect(nullptr, GetCallback(), base::Bind(&BluetoothChromeOSTest::ConnectErrorCallback, @@ -4011,8 +4025,9 @@ EXPECT_TRUE(adapter_->IsDiscoverable()); EXPECT_TRUE(adapter_->IsDiscovering()); EXPECT_EQ(2U, adapter_->GetDevices().size()); - EXPECT_NE(nullptr, adapter_->GetDevice( - FakeBluetoothDeviceClient::kPairedDeviceAddress)); + EXPECT_NE(nullptr, + adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress)); EXPECT_NE(dbus::ObjectPath(""), static_cast<BluetoothAdapterChromeOS*>( adapter_.get())->object_path()); @@ -4089,7 +4104,7 @@ FakeBluetoothProfileServiceProviderDelegate profile_delegate; adapter_chrome_os->UseProfile( BluetoothUUID(), dbus::ObjectPath(""), - BluetoothProfileManagerClient::Options(), &profile_delegate, + bluez::BluetoothProfileManagerClient::Options(), &profile_delegate, base::Bind(&BluetoothChromeOSTest::ProfileRegisteredCallback, base::Unretained(this)), base::Bind(&BluetoothChromeOSTest::ErrorCompletionCallback, @@ -4109,7 +4124,8 @@ adapter_chrome_os->DeviceRemoved(dbus::ObjectPath("")); adapter_chrome_os->DevicePropertyChanged(dbus::ObjectPath(""), ""); adapter_chrome_os->InputPropertyChanged(dbus::ObjectPath(""), ""); - // BluetoothAgentServiceProvider::Delegate omitted, dbus will be shutdown, + // bluez::BluetoothAgentServiceProvider::Delegate omitted, dbus will be + // shutdown, // with the exception of Released. adapter_chrome_os->Released(); @@ -4166,7 +4182,7 @@ // UseProfile to be set first, do so again here just before calling them. adapter_chrome_os->UseProfile( BluetoothUUID(), dbus::ObjectPath(""), - BluetoothProfileManagerClient::Options(), &profile_delegate, + bluez::BluetoothProfileManagerClient::Options(), &profile_delegate, base::Bind(&BluetoothChromeOSTest::ProfileRegisteredCallback, base::Unretained(this)), base::Bind(&BluetoothChromeOSTest::ErrorCompletionCallback, @@ -4201,8 +4217,9 @@ EXPECT_EQ(1, error_callback_count_--) << "StartDiscoverySession error"; EXPECT_EQ(0U, adapter_->GetDevices().size()); - EXPECT_EQ(nullptr, adapter_->GetDevice( - FakeBluetoothDeviceClient::kPairedDeviceAddress)); + EXPECT_EQ(nullptr, + adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress)); TestPairingDelegate pairing_delegate2; adapter_->AddPairingDelegate( &pairing_delegate2, BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
diff --git a/device/bluetooth/bluetooth_device_android.cc b/device/bluetooth/bluetooth_device_android.cc index 7350a4a..ecb1097 100644 --- a/device/bluetooth/bluetooth_device_android.cc +++ b/device/bluetooth/bluetooth_device_android.cc
@@ -233,9 +233,7 @@ JNIEnv* env, jobject caller, const jstring& instanceId, - jobject bluetooth_gatt_service_wrapper // Java Type: - // BluetoothGattServiceWrapper - ) { + jobject /* BluetoothGattServiceWrapper */ bluetooth_gatt_service_wrapper) { std::string instanceIdString = base::android::ConvertJavaStringToUTF8(env, instanceId); @@ -246,7 +244,7 @@ gatt_services_.set(instanceIdString, BluetoothRemoteGattServiceAndroid::Create( GetAdapter(), this, bluetooth_gatt_service_wrapper, - instanceIdString)); + instanceIdString, j_device_.obj())); FOR_EACH_OBSERVER(BluetoothAdapter::Observer, GetAdapter()->GetObservers(), GattServiceAdded(adapter_, this, service_iterator->second));
diff --git a/device/bluetooth/bluetooth_device_android.h b/device/bluetooth/bluetooth_device_android.h index 24d4a7f..be9df2a 100644 --- a/device/bluetooth/bluetooth_device_android.h +++ b/device/bluetooth/bluetooth_device_android.h
@@ -104,8 +104,7 @@ JNIEnv* env, jobject caller, const jstring& instanceId, - jobject bluetooth_gatt_service_wrapper); // Java Type: - // BluetoothGattServiceWrapper + jobject /* BluetoothGattServiceWrapper */ bluetooth_gatt_service_wrapper); protected: BluetoothDeviceAndroid(BluetoothAdapterAndroid* adapter);
diff --git a/device/bluetooth/bluetooth_device_chromeos.cc b/device/bluetooth/bluetooth_device_chromeos.cc index 898fd512..ea4a168c 100644 --- a/device/bluetooth/bluetooth_device_chromeos.cc +++ b/device/bluetooth/bluetooth_device_chromeos.cc
@@ -11,11 +11,6 @@ #include "base/metrics/histogram.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" -#include "chromeos/dbus/bluetooth_adapter_client.h" -#include "chromeos/dbus/bluetooth_device_client.h" -#include "chromeos/dbus/bluetooth_gatt_service_client.h" -#include "chromeos/dbus/bluetooth_input_client.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "dbus/bus.h" #include "device/bluetooth/bluetooth_adapter_chromeos.h" #include "device/bluetooth/bluetooth_gatt_connection_chromeos.h" @@ -25,6 +20,11 @@ #include "device/bluetooth/bluetooth_socket_chromeos.h" #include "device/bluetooth/bluetooth_socket_thread.h" #include "device/bluetooth/bluetooth_uuid.h" +#include "device/bluetooth/dbus/bluetooth_adapter_client.h" +#include "device/bluetooth/dbus/bluetooth_device_client.h" +#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h" +#include "device/bluetooth/dbus/bluetooth_input_client.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" #include "third_party/cros_system_api/dbus/service_constants.h" using device::BluetoothDevice; @@ -55,10 +55,9 @@ uint16* vendor_id, uint16* product_id, uint16* device_id) { - chromeos::BluetoothDeviceClient::Properties* properties = - chromeos::DBusThreadManager::Get() - ->GetBluetoothDeviceClient() - ->GetProperties(object_path); + bluez::BluetoothDeviceClient::Properties* properties = + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties( + object_path); DCHECK(properties); std::string modalias = properties->modalias.value(); @@ -153,11 +152,14 @@ ui_task_runner_(ui_task_runner), socket_thread_(socket_thread), weak_ptr_factory_(this) { - DBusThreadManager::Get()->GetBluetoothGattServiceClient()->AddObserver(this); + bluez::BluezDBusManager::Get()->GetBluetoothGattServiceClient()->AddObserver( + this); // Add all known GATT services. const std::vector<dbus::ObjectPath> gatt_services = - DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetServices(); + bluez::BluezDBusManager::Get() + ->GetBluetoothGattServiceClient() + ->GetServices(); for (std::vector<dbus::ObjectPath>::const_iterator it = gatt_services.begin(); it != gatt_services.end(); ++it) { GattServiceAdded(*it); @@ -165,8 +167,9 @@ } BluetoothDeviceChromeOS::~BluetoothDeviceChromeOS() { - DBusThreadManager::Get()->GetBluetoothGattServiceClient()->RemoveObserver( - this); + bluez::BluezDBusManager::Get() + ->GetBluetoothGattServiceClient() + ->RemoveObserver(this); // Copy the GATT services list here and clear the original so that when we // send GattServiceRemoved(), GetGattServices() returns no services. @@ -180,8 +183,8 @@ } uint32 BluetoothDeviceChromeOS::GetBluetoothClass() const { - BluetoothDeviceClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothDeviceClient()->GetProperties( + bluez::BluetoothDeviceClient::Properties* properties = + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties( object_path_); DCHECK(properties); @@ -189,8 +192,8 @@ } std::string BluetoothDeviceChromeOS::GetDeviceName() const { - BluetoothDeviceClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothDeviceClient()->GetProperties( + bluez::BluetoothDeviceClient::Properties* properties = + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties( object_path_); DCHECK(properties); @@ -210,8 +213,8 @@ } std::string BluetoothDeviceChromeOS::GetAddress() const { - BluetoothDeviceClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothDeviceClient()->GetProperties( + bluez::BluetoothDeviceClient::Properties* properties = + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties( object_path_); DCHECK(properties); @@ -244,8 +247,8 @@ } bool BluetoothDeviceChromeOS::IsPaired() const { - BluetoothDeviceClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothDeviceClient()->GetProperties( + bluez::BluetoothDeviceClient::Properties* properties = + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties( object_path_); DCHECK(properties); @@ -256,8 +259,8 @@ } bool BluetoothDeviceChromeOS::IsConnected() const { - BluetoothDeviceClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothDeviceClient()->GetProperties( + bluez::BluetoothDeviceClient::Properties* properties = + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties( object_path_); DCHECK(properties); @@ -270,8 +273,8 @@ } bool BluetoothDeviceChromeOS::IsConnectable() const { - BluetoothInputClient::Properties* input_properties = - DBusThreadManager::Get()->GetBluetoothInputClient()->GetProperties( + bluez::BluetoothInputClient::Properties* input_properties = + bluez::BluezDBusManager::Get()->GetBluetoothInputClient()->GetProperties( object_path_); // GetProperties returns NULL when the device does not implement the given // interface. Non HID devices are normally connectable. @@ -286,8 +289,8 @@ } BluetoothDeviceChromeOS::UUIDList BluetoothDeviceChromeOS::GetUUIDs() const { - BluetoothDeviceClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothDeviceClient()->GetProperties( + bluez::BluetoothDeviceClient::Properties* properties = + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties( object_path_); DCHECK(properties); @@ -303,8 +306,8 @@ } int16 BluetoothDeviceChromeOS::GetInquiryRSSI() const { - BluetoothDeviceClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothDeviceClient()->GetProperties( + bluez::BluetoothDeviceClient::Properties* properties = + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties( object_path_); DCHECK(properties); @@ -315,8 +318,8 @@ } int16 BluetoothDeviceChromeOS::GetInquiryTxPower() const { - BluetoothDeviceClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothDeviceClient()->GetProperties( + bluez::BluetoothDeviceClient::Properties* properties = + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties( object_path_); DCHECK(properties); @@ -342,7 +345,7 @@ const ConnectionInfoCallback& callback) { // DBus method call should gracefully return an error if the device is not // currently connected. - DBusThreadManager::Get()->GetBluetoothDeviceClient()->GetConnInfo( + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetConnInfo( object_path_, base::Bind(&BluetoothDeviceChromeOS::OnGetConnInfo, weak_ptr_factory_.GetWeakPtr(), callback), base::Bind(&BluetoothDeviceChromeOS::OnGetConnInfoError, @@ -366,7 +369,7 @@ // Initiate high-security connection with pairing. BeginPairing(pairing_delegate); - DBusThreadManager::Get()->GetBluetoothDeviceClient()->Pair( + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->Pair( object_path_, base::Bind(&BluetoothDeviceChromeOS::OnPairDuringConnect, weak_ptr_factory_.GetWeakPtr(), callback, error_callback), @@ -382,7 +385,7 @@ DCHECK(pairing_delegate); BeginPairing(pairing_delegate); - DBusThreadManager::Get()->GetBluetoothDeviceClient()->Pair( + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->Pair( object_path_, base::Bind(&BluetoothDeviceChromeOS::OnPair, weak_ptr_factory_.GetWeakPtr(), callback), base::Bind(&BluetoothDeviceChromeOS::OnPairError, @@ -429,7 +432,7 @@ if (!canceled) { VLOG(1) << object_path_.value() << ": No pairing context or callback. " << "Sending explicit cancel"; - DBusThreadManager::Get()->GetBluetoothDeviceClient()->CancelPairing( + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->CancelPairing( object_path_, base::Bind(&base::DoNothing), base::Bind(&BluetoothDeviceChromeOS::OnCancelPairingError, weak_ptr_factory_.GetWeakPtr())); @@ -445,7 +448,7 @@ void BluetoothDeviceChromeOS::Disconnect(const base::Closure& callback, const ErrorCallback& error_callback) { VLOG(1) << object_path_.value() << ": Disconnecting"; - DBusThreadManager::Get()->GetBluetoothDeviceClient()->Disconnect( + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->Disconnect( object_path_, base::Bind(&BluetoothDeviceChromeOS::OnDisconnect, weak_ptr_factory_.GetWeakPtr(), callback), base::Bind(&BluetoothDeviceChromeOS::OnDisconnectError, @@ -454,7 +457,7 @@ void BluetoothDeviceChromeOS::Forget(const ErrorCallback& error_callback) { VLOG(1) << object_path_.value() << ": Removing device"; - DBusThreadManager::Get()->GetBluetoothAdapterClient()->RemoveDevice( + bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->RemoveDevice( adapter()->object_path(), object_path_, base::Bind(&base::DoNothing), base::Bind(&BluetoothDeviceChromeOS::OnForgetError, weak_ptr_factory_.GetWeakPtr(), error_callback)); @@ -533,9 +536,10 @@ return; } - BluetoothGattServiceClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetProperties( - object_path); + bluez::BluetoothGattServiceClient::Properties* properties = + bluez::BluezDBusManager::Get() + ->GetBluetoothGattServiceClient() + ->GetProperties(object_path); DCHECK(properties); if (properties->device.value() != object_path_) { VLOG(2) << "Remote GATT service does not belong to this device."; @@ -603,7 +607,7 @@ const base::Closure& callback, const ConnectErrorCallback& error_callback) { VLOG(1) << object_path_.value() << ": Connecting"; - DBusThreadManager::Get()->GetBluetoothDeviceClient()->Connect( + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->Connect( object_path_, base::Bind(&BluetoothDeviceChromeOS::OnConnect, weak_ptr_factory_.GetWeakPtr(), after_pairing, callback), @@ -731,7 +735,7 @@ // first; there's no harm in doing this and it solves any race conditions // with the property becoming true or false and this call happening before // we get the D-Bus signal about the earlier change. - DBusThreadManager::Get() + bluez::BluezDBusManager::Get() ->GetBluetoothDeviceClient() ->GetProperties(object_path_) ->trusted.Set(true, base::Bind(&BluetoothDeviceChromeOS::OnSetTrusted,
diff --git a/device/bluetooth/bluetooth_device_chromeos.h b/device/bluetooth/bluetooth_device_chromeos.h index 7f66a43..544fdafe 100644 --- a/device/bluetooth/bluetooth_device_chromeos.h +++ b/device/bluetooth/bluetooth_device_chromeos.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_CHROMEOS_H -#define DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_CHROMEOS_H +#ifndef DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_CHROMEOS_H_ +#define DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_CHROMEOS_H_ #include <string> @@ -11,11 +11,11 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" -#include "chromeos/dbus/bluetooth_device_client.h" -#include "chromeos/dbus/bluetooth_gatt_service_client.h" #include "dbus/object_path.h" #include "device/bluetooth/bluetooth_device.h" #include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_device_client.h" +#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h" namespace device { class BluetoothSocketThread; @@ -35,7 +35,7 @@ // thread. class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceChromeOS : public device::BluetoothDevice, - public BluetoothGattServiceClient::Observer { + public bluez::BluetoothGattServiceClient::Observer { public: // BluetoothDevice override uint32 GetBluetoothClass() const override; @@ -118,7 +118,7 @@ scoped_refptr<device::BluetoothSocketThread> socket_thread); ~BluetoothDeviceChromeOS() override; - // BluetoothGattServiceClient::Observer overrides. + // bluez::BluetoothGattServiceClient::Observer overrides. void GattServiceAdded(const dbus::ObjectPath& object_path) override; void GattServiceRemoved(const dbus::ObjectPath& object_path) override; @@ -215,4 +215,4 @@ } // namespace chromeos -#endif // DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_CHROMEOS_H +#endif // DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_CHROMEOS_H_
diff --git a/device/bluetooth/bluetooth_gatt_characteristic_unittest.cc b/device/bluetooth/bluetooth_gatt_characteristic_unittest.cc index 914be35..095d2b3b 100644 --- a/device/bluetooth/bluetooth_gatt_characteristic_unittest.cc +++ b/device/bluetooth/bluetooth_gatt_characteristic_unittest.cc
@@ -4,6 +4,7 @@ #include "device/bluetooth/bluetooth_gatt_characteristic.h" +#include "base/run_loop.h" #include "device/bluetooth/bluetooth_gatt_service.h" #include "testing/gtest/include/gtest/gtest.h" @@ -16,7 +17,35 @@ namespace device { #if defined(OS_ANDROID) || defined(OS_MACOSX) -class BluetoothGattCharacteristicTest : public BluetoothTest {}; +class BluetoothGattCharacteristicTest : public BluetoothTest { + public: + // Create adapter_, device_, service, and provides. + void FakeCharacteristicBoilerplate() { + InitWithFakeAdapter(); + StartLowEnergyDiscoverySession(); + device_ = DiscoverLowEnergyDevice(3); + device_->CreateGattConnection(GetGattConnectionCallback(), + GetConnectErrorCallback()); + SimulateGattConnection(device_); + std::vector<std::string> services; + std::string uuid("00000000-0000-1000-8000-00805f9b34fb"); + services.push_back(uuid); + SimulateGattServicesDiscovered(device_, services); + ASSERT_EQ(1u, device_->GetGattServices().size()); + service_ = device_->GetGattServices()[0]; + SimulateGattCharacteristic(service_, uuid, /* properties */ 0); + SimulateGattCharacteristic(service_, uuid, /* properties */ 0); + characteristic1_ = service_->GetCharacteristics()[0]; + characteristic2_ = service_->GetCharacteristics()[1]; + ASSERT_EQ(2u, service_->GetCharacteristics().size()); + ResetEventCounts(); + } + + BluetoothDevice* device_ = nullptr; + BluetoothGattService* service_ = nullptr; + BluetoothGattCharacteristic* characteristic1_ = nullptr; + BluetoothGattCharacteristic* characteristic2_ = nullptr; +}; #endif #if defined(OS_ANDROID) @@ -148,4 +177,388 @@ } #endif // defined(OS_ANDROID) +#if defined(OS_ANDROID) +// Tests ReadRemoteCharacteristic and GetValue with empty value buffer. +TEST_F(BluetoothGattCharacteristicTest, ReadRemoteCharacteristic_Empty) { + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); + + characteristic1_->ReadRemoteCharacteristic(GetReadValueCallback(), + GetGattErrorCallback()); + EXPECT_EQ(1, gatt_read_characteristic_attempts_); + std::vector<uint8_t> empty_vector; + SimulateGattCharacteristicRead(characteristic1_, empty_vector); + + // Duplicate read reported from OS shouldn't cause a problem: + SimulateGattCharacteristicRead(characteristic1_, empty_vector); + + EXPECT_EQ(1, callback_count_); + EXPECT_EQ(0, error_callback_count_); + EXPECT_EQ(empty_vector, last_read_value_); + EXPECT_EQ(empty_vector, characteristic1_->GetValue()); +} +#endif // defined(OS_ANDROID) + +#if defined(OS_ANDROID) +// Tests WriteRemoteCharacteristic with empty value buffer. +TEST_F(BluetoothGattCharacteristicTest, WriteRemoteCharacteristic_Empty) { + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); + + std::vector<uint8_t> empty_vector; + characteristic1_->WriteRemoteCharacteristic(empty_vector, GetCallback(), + GetGattErrorCallback()); + EXPECT_EQ(1, gatt_write_characteristic_attempts_); + SimulateGattCharacteristicWrite(characteristic1_); + + EXPECT_EQ(1, callback_count_); + EXPECT_EQ(0, error_callback_count_); + EXPECT_EQ(empty_vector, last_write_value_); +} +#endif // defined(OS_ANDROID) + +#if defined(OS_ANDROID) +// Tests ReadRemoteCharacteristic and GetValue with non-empty value buffer. +TEST_F(BluetoothGattCharacteristicTest, ReadRemoteCharacteristic) { + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); + + characteristic1_->ReadRemoteCharacteristic(GetReadValueCallback(), + GetGattErrorCallback()); + EXPECT_EQ(1, gatt_read_characteristic_attempts_); + + uint8_t values[] = {0, 1, 2, 3, 4, 0xf, 0xf0, 0xff}; + std::vector<uint8_t> test_vector(values, values + arraysize(values)); + SimulateGattCharacteristicRead(characteristic1_, test_vector); + + // Duplicate read reported from OS shouldn't cause a problem: + std::vector<uint8_t> empty_vector; + SimulateGattCharacteristicRead(characteristic1_, empty_vector); + + EXPECT_EQ(1, callback_count_); + EXPECT_EQ(0, error_callback_count_); + EXPECT_EQ(test_vector, last_read_value_); + EXPECT_EQ(test_vector, characteristic1_->GetValue()); +} +#endif // defined(OS_ANDROID) + +#if defined(OS_ANDROID) +// Tests WriteRemoteCharacteristic with non-empty value buffer. +TEST_F(BluetoothGattCharacteristicTest, WriteRemoteCharacteristic) { + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); + + uint8_t values[] = {0, 1, 2, 3, 4, 0xf, 0xf0, 0xff}; + std::vector<uint8_t> test_vector(values, values + arraysize(values)); + characteristic1_->WriteRemoteCharacteristic(test_vector, GetCallback(), + GetGattErrorCallback()); + EXPECT_EQ(1, gatt_write_characteristic_attempts_); + + SimulateGattCharacteristicWrite(characteristic1_); + + EXPECT_EQ(1, callback_count_); + EXPECT_EQ(0, error_callback_count_); + EXPECT_EQ(test_vector, last_write_value_); +} +#endif // defined(OS_ANDROID) + +#if defined(OS_ANDROID) +// Tests ReadRemoteCharacteristic and GetValue multiple times. +TEST_F(BluetoothGattCharacteristicTest, ReadRemoteCharacteristic_Twice) { + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); + + characteristic1_->ReadRemoteCharacteristic(GetReadValueCallback(), + GetGattErrorCallback()); + EXPECT_EQ(1, gatt_read_characteristic_attempts_); + + uint8_t values[] = {0, 1, 2, 3, 4, 0xf, 0xf0, 0xff}; + std::vector<uint8_t> test_vector(values, values + arraysize(values)); + SimulateGattCharacteristicRead(characteristic1_, test_vector); + EXPECT_EQ(1, callback_count_); + EXPECT_EQ(0, error_callback_count_); + EXPECT_EQ(test_vector, last_read_value_); + EXPECT_EQ(test_vector, characteristic1_->GetValue()); + + // Read again, with different value: + ResetEventCounts(); + characteristic1_->ReadRemoteCharacteristic(GetReadValueCallback(), + GetGattErrorCallback()); + EXPECT_EQ(1, gatt_read_characteristic_attempts_); + std::vector<uint8_t> empty_vector; + SimulateGattCharacteristicRead(characteristic1_, empty_vector); + EXPECT_EQ(1, callback_count_); + EXPECT_EQ(0, error_callback_count_); + EXPECT_EQ(empty_vector, last_read_value_); + EXPECT_EQ(empty_vector, characteristic1_->GetValue()); +} +#endif // defined(OS_ANDROID) + +#if defined(OS_ANDROID) +// Tests WriteRemoteCharacteristic multiple times. +TEST_F(BluetoothGattCharacteristicTest, WriteRemoteCharacteristic_Twice) { + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); + + uint8_t values[] = {0, 1, 2, 3, 4, 0xf, 0xf0, 0xff}; + std::vector<uint8_t> test_vector(values, values + arraysize(values)); + characteristic1_->WriteRemoteCharacteristic(test_vector, GetCallback(), + GetGattErrorCallback()); + EXPECT_EQ(1, gatt_write_characteristic_attempts_); + + SimulateGattCharacteristicWrite(characteristic1_); + EXPECT_EQ(1, callback_count_); + EXPECT_EQ(0, error_callback_count_); + EXPECT_EQ(test_vector, last_write_value_); + + // Write again, with different value: + ResetEventCounts(); + std::vector<uint8_t> empty_vector; + characteristic1_->WriteRemoteCharacteristic(empty_vector, GetCallback(), + GetGattErrorCallback()); + EXPECT_EQ(1, gatt_write_characteristic_attempts_); + SimulateGattCharacteristicWrite(characteristic1_); + EXPECT_EQ(1, callback_count_); + EXPECT_EQ(0, error_callback_count_); + EXPECT_EQ(empty_vector, last_write_value_); +} +#endif // defined(OS_ANDROID) + +#if defined(OS_ANDROID) +// Tests ReadRemoteCharacteristic on two characteristics. +TEST_F(BluetoothGattCharacteristicTest, + ReadRemoteCharacteristic_MultipleCharacteristics) { + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); + + characteristic1_->ReadRemoteCharacteristic(GetReadValueCallback(), + GetGattErrorCallback()); + characteristic2_->ReadRemoteCharacteristic(GetReadValueCallback(), + GetGattErrorCallback()); + EXPECT_EQ(2, gatt_read_characteristic_attempts_); + EXPECT_EQ(0, callback_count_); + EXPECT_EQ(0, error_callback_count_); + + std::vector<uint8_t> test_vector1; + test_vector1.push_back(111); + SimulateGattCharacteristicRead(characteristic1_, test_vector1); + EXPECT_EQ(test_vector1, last_read_value_); + + std::vector<uint8_t> test_vector2; + test_vector2.push_back(222); + SimulateGattCharacteristicRead(characteristic2_, test_vector2); + EXPECT_EQ(test_vector2, last_read_value_); + + EXPECT_EQ(2, callback_count_); + EXPECT_EQ(0, error_callback_count_); + EXPECT_EQ(test_vector1, characteristic1_->GetValue()); + EXPECT_EQ(test_vector2, characteristic2_->GetValue()); +} +#endif // defined(OS_ANDROID) + +#if defined(OS_ANDROID) +// Tests WriteRemoteCharacteristic on two characteristics. +TEST_F(BluetoothGattCharacteristicTest, + WriteRemoteCharacteristic_MultipleCharacteristics) { + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); + + std::vector<uint8_t> test_vector1; + test_vector1.push_back(111); + characteristic1_->WriteRemoteCharacteristic(test_vector1, GetCallback(), + GetGattErrorCallback()); + EXPECT_EQ(test_vector1, last_write_value_); + + std::vector<uint8_t> test_vector2; + test_vector2.push_back(222); + characteristic2_->WriteRemoteCharacteristic(test_vector2, GetCallback(), + GetGattErrorCallback()); + EXPECT_EQ(test_vector2, last_write_value_); + + EXPECT_EQ(2, gatt_write_characteristic_attempts_); + EXPECT_EQ(0, callback_count_); + EXPECT_EQ(0, error_callback_count_); + + SimulateGattCharacteristicWrite(characteristic1_); + SimulateGattCharacteristicWrite(characteristic2_); + + EXPECT_EQ(2, callback_count_); + EXPECT_EQ(0, error_callback_count_); +} +#endif // defined(OS_ANDROID) + +#if defined(OS_ANDROID) +// Tests ReadRemoteCharacteristic asynchronous error. +TEST_F(BluetoothGattCharacteristicTest, ReadError) { + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); + + characteristic1_->ReadRemoteCharacteristic(GetReadValueCallback(), + GetGattErrorCallback()); + SimulateGattCharacteristicReadError( + characteristic1_, BluetoothGattService::GATT_ERROR_INVALID_LENGTH); + SimulateGattCharacteristicReadError(characteristic1_, + BluetoothGattService::GATT_ERROR_FAILED); + EXPECT_EQ(0, callback_count_); + EXPECT_EQ(1, error_callback_count_); + EXPECT_EQ(BluetoothGattService::GATT_ERROR_INVALID_LENGTH, + last_gatt_error_code_); +} +#endif // defined(OS_ANDROID) + +#if defined(OS_ANDROID) +// Tests WriteRemoteCharacteristic asynchronous error. +TEST_F(BluetoothGattCharacteristicTest, WriteError) { + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); + + std::vector<uint8_t> empty_vector; + characteristic1_->WriteRemoteCharacteristic(empty_vector, GetCallback(), + GetGattErrorCallback()); + SimulateGattCharacteristicWriteError( + characteristic1_, BluetoothGattService::GATT_ERROR_INVALID_LENGTH); + SimulateGattCharacteristicWriteError(characteristic1_, + BluetoothGattService::GATT_ERROR_FAILED); + EXPECT_EQ(0, callback_count_); + EXPECT_EQ(1, error_callback_count_); + EXPECT_EQ(BluetoothGattService::GATT_ERROR_INVALID_LENGTH, + last_gatt_error_code_); +} +#endif // defined(OS_ANDROID) + +#if defined(OS_ANDROID) +// Tests ReadRemoteCharacteristic synchronous error. +TEST_F(BluetoothGattCharacteristicTest, ReadSynchronousError) { + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); + + SimulateGattCharacteristicReadWillFailSynchronouslyOnce(characteristic1_); + characteristic1_->ReadRemoteCharacteristic(GetReadValueCallback(), + GetGattErrorCallback()); + EXPECT_EQ(0, gatt_read_characteristic_attempts_); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(0, callback_count_); + EXPECT_EQ(1, error_callback_count_); + EXPECT_EQ(BluetoothGattService::GATT_ERROR_FAILED, last_gatt_error_code_); + + // After failing once, can succeed: + ResetEventCounts(); + characteristic1_->ReadRemoteCharacteristic(GetReadValueCallback(), + GetGattErrorCallback()); + EXPECT_EQ(1, gatt_read_characteristic_attempts_); + std::vector<uint8_t> empty_vector; + SimulateGattCharacteristicRead(characteristic1_, empty_vector); + EXPECT_EQ(1, callback_count_); + EXPECT_EQ(0, error_callback_count_); +} +#endif // defined(OS_ANDROID) + +#if defined(OS_ANDROID) +// Tests WriteRemoteCharacteristic synchronous error. +TEST_F(BluetoothGattCharacteristicTest, WriteSynchronousError) { + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); + + SimulateGattCharacteristicWriteWillFailSynchronouslyOnce(characteristic1_); + std::vector<uint8_t> empty_vector; + characteristic1_->WriteRemoteCharacteristic(empty_vector, GetCallback(), + GetGattErrorCallback()); + EXPECT_EQ(0, gatt_write_characteristic_attempts_); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(0, callback_count_); + EXPECT_EQ(1, error_callback_count_); + EXPECT_EQ(BluetoothGattService::GATT_ERROR_FAILED, last_gatt_error_code_); + + // After failing once, can succeed: + ResetEventCounts(); + characteristic1_->WriteRemoteCharacteristic(empty_vector, GetCallback(), + GetGattErrorCallback()); + EXPECT_EQ(1, gatt_write_characteristic_attempts_); + SimulateGattCharacteristicWrite(characteristic1_); + EXPECT_EQ(1, callback_count_); + EXPECT_EQ(0, error_callback_count_); +} +#endif // defined(OS_ANDROID) + +#if defined(OS_ANDROID) +// Tests ReadRemoteCharacteristic error with a pending read operation. +TEST_F(BluetoothGattCharacteristicTest, ReadRemoteCharacteristic_ReadPending) { + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); + + characteristic1_->ReadRemoteCharacteristic(GetReadValueCallback(), + GetGattErrorCallback()); + characteristic1_->ReadRemoteCharacteristic(GetReadValueCallback(), + GetGattErrorCallback()); + EXPECT_EQ(0, callback_count_); + EXPECT_EQ(1, error_callback_count_); + EXPECT_EQ(BluetoothGattService::GATT_ERROR_IN_PROGRESS, + last_gatt_error_code_); + + // Initial read should still succeed: + ResetEventCounts(); + std::vector<uint8_t> empty_vector; + SimulateGattCharacteristicRead(characteristic1_, empty_vector); + EXPECT_EQ(1, callback_count_); + EXPECT_EQ(0, error_callback_count_); +} +#endif // defined(OS_ANDROID) + +#if defined(OS_ANDROID) +// Tests WriteRemoteCharacteristic error with a pending write operation. +TEST_F(BluetoothGattCharacteristicTest, + WriteRemoteCharacteristic_WritePending) { + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); + + std::vector<uint8_t> empty_vector; + characteristic1_->WriteRemoteCharacteristic(empty_vector, GetCallback(), + GetGattErrorCallback()); + characteristic1_->WriteRemoteCharacteristic(empty_vector, GetCallback(), + GetGattErrorCallback()); + EXPECT_EQ(0, callback_count_); + EXPECT_EQ(1, error_callback_count_); + EXPECT_EQ(BluetoothGattService::GATT_ERROR_IN_PROGRESS, + last_gatt_error_code_); + + // Initial write should still succeed: + ResetEventCounts(); + SimulateGattCharacteristicWrite(characteristic1_); + EXPECT_EQ(1, callback_count_); + EXPECT_EQ(0, error_callback_count_); +} +#endif // defined(OS_ANDROID) + +#if defined(OS_ANDROID) +// Tests ReadRemoteCharacteristic error with a pending write operation. +TEST_F(BluetoothGattCharacteristicTest, ReadRemoteCharacteristic_WritePending) { + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); + + std::vector<uint8_t> empty_vector; + characteristic1_->WriteRemoteCharacteristic(empty_vector, GetCallback(), + GetGattErrorCallback()); + characteristic1_->ReadRemoteCharacteristic(GetReadValueCallback(), + GetGattErrorCallback()); + EXPECT_EQ(0, callback_count_); + EXPECT_EQ(1, error_callback_count_); + EXPECT_EQ(BluetoothGattService::GATT_ERROR_IN_PROGRESS, + last_gatt_error_code_); + + // Initial write should still succeed: + ResetEventCounts(); + SimulateGattCharacteristicWrite(characteristic1_); + EXPECT_EQ(1, callback_count_); + EXPECT_EQ(0, error_callback_count_); +} +#endif // defined(OS_ANDROID) + +#if defined(OS_ANDROID) +// Tests WriteRemoteCharacteristic error with a pending Read operation. +TEST_F(BluetoothGattCharacteristicTest, WriteRemoteCharacteristic_ReadPending) { + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); + + std::vector<uint8_t> empty_vector; + characteristic1_->ReadRemoteCharacteristic(GetReadValueCallback(), + GetGattErrorCallback()); + characteristic1_->WriteRemoteCharacteristic(empty_vector, GetCallback(), + GetGattErrorCallback()); + EXPECT_EQ(0, callback_count_); + EXPECT_EQ(1, error_callback_count_); + EXPECT_EQ(BluetoothGattService::GATT_ERROR_IN_PROGRESS, + last_gatt_error_code_); + + // Initial read should still succeed: + ResetEventCounts(); + SimulateGattCharacteristicRead(characteristic1_, empty_vector); + EXPECT_EQ(1, callback_count_); + EXPECT_EQ(0, error_callback_count_); +} +#endif // defined(OS_ANDROID) + } // namespace device
diff --git a/device/bluetooth/bluetooth_gatt_chromeos_unittest.cc b/device/bluetooth/bluetooth_gatt_chromeos_unittest.cc index 5cf067c..cf9e441f 100644 --- a/device/bluetooth/bluetooth_gatt_chromeos_unittest.cc +++ b/device/bluetooth/bluetooth_gatt_chromeos_unittest.cc
@@ -5,14 +5,6 @@ #include "base/memory/scoped_vector.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_adapter_client.h" -#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" -#include "chromeos/dbus/fake_bluetooth_device_client.h" -#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h" -#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h" -#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h" -#include "chromeos/dbus/fake_bluetooth_input_client.h" #include "dbus/object_path.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_adapter_factory.h" @@ -23,6 +15,14 @@ #include "device/bluetooth/bluetooth_gatt_notify_session.h" #include "device/bluetooth/bluetooth_gatt_service.h" #include "device/bluetooth/bluetooth_uuid.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_device_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_input_client.h" #include "device/bluetooth/test/test_bluetooth_adapter_observer.h" #include "testing/gtest/include/gtest/gtest.h" @@ -41,11 +41,11 @@ namespace { const BluetoothUUID kHeartRateMeasurementUUID( - FakeBluetoothGattCharacteristicClient::kHeartRateMeasurementUUID); + bluez::FakeBluetoothGattCharacteristicClient::kHeartRateMeasurementUUID); const BluetoothUUID kBodySensorLocationUUID( - FakeBluetoothGattCharacteristicClient::kBodySensorLocationUUID); + bluez::FakeBluetoothGattCharacteristicClient::kBodySensorLocationUUID); const BluetoothUUID kHeartRateControlPointUUID( - FakeBluetoothGattCharacteristicClient::kHeartRateControlPointUUID); + bluez::FakeBluetoothGattCharacteristicClient::kHeartRateControlPointUUID); // Compares GATT characteristic/descriptor values. Returns true, if the values // are equal. @@ -70,32 +70,36 @@ } void SetUp() override { - scoped_ptr<DBusThreadManagerSetter> dbus_setter = - chromeos::DBusThreadManager::GetSetterForTesting(); - fake_bluetooth_device_client_ = new FakeBluetoothDeviceClient; - fake_bluetooth_gatt_service_client_ = new FakeBluetoothGattServiceClient; + scoped_ptr<bluez::BluezDBusManagerSetter> dbus_setter = + bluez::BluezDBusManager::GetSetterForTesting(); + fake_bluetooth_device_client_ = new bluez::FakeBluetoothDeviceClient; + fake_bluetooth_gatt_service_client_ = + new bluez::FakeBluetoothGattServiceClient; fake_bluetooth_gatt_characteristic_client_ = - new FakeBluetoothGattCharacteristicClient; + new bluez::FakeBluetoothGattCharacteristicClient; fake_bluetooth_gatt_descriptor_client_ = - new FakeBluetoothGattDescriptorClient; + new bluez::FakeBluetoothGattDescriptorClient; dbus_setter->SetBluetoothDeviceClient( - scoped_ptr<BluetoothDeviceClient>(fake_bluetooth_device_client_)); + scoped_ptr<bluez::BluetoothDeviceClient>( + fake_bluetooth_device_client_)); dbus_setter->SetBluetoothGattServiceClient( - scoped_ptr<BluetoothGattServiceClient>( + scoped_ptr<bluez::BluetoothGattServiceClient>( fake_bluetooth_gatt_service_client_)); dbus_setter->SetBluetoothGattCharacteristicClient( - scoped_ptr<BluetoothGattCharacteristicClient>( + scoped_ptr<bluez::BluetoothGattCharacteristicClient>( fake_bluetooth_gatt_characteristic_client_)); dbus_setter->SetBluetoothGattDescriptorClient( - scoped_ptr<BluetoothGattDescriptorClient>( + scoped_ptr<bluez::BluetoothGattDescriptorClient>( fake_bluetooth_gatt_descriptor_client_)); dbus_setter->SetBluetoothAdapterClient( - scoped_ptr<BluetoothAdapterClient>(new FakeBluetoothAdapterClient)); + scoped_ptr<bluez::BluetoothAdapterClient>( + new bluez::FakeBluetoothAdapterClient)); dbus_setter->SetBluetoothInputClient( - scoped_ptr<BluetoothInputClient>(new FakeBluetoothInputClient)); + scoped_ptr<bluez::BluetoothInputClient>( + new bluez::FakeBluetoothInputClient)); dbus_setter->SetBluetoothAgentManagerClient( - scoped_ptr<BluetoothAgentManagerClient>( - new FakeBluetoothAgentManagerClient)); + scoped_ptr<bluez::BluetoothAgentManagerClient>( + new bluez::FakeBluetoothAgentManagerClient)); GetAdapter(); @@ -110,7 +114,7 @@ adapter_ = NULL; update_sessions_.clear(); gatt_conn_.reset(); - DBusThreadManager::Shutdown(); + bluez::BluezDBusManager::Shutdown(); } void GetAdapter() { @@ -173,11 +177,12 @@ base::MessageLoop message_loop_; - FakeBluetoothDeviceClient* fake_bluetooth_device_client_; - FakeBluetoothGattServiceClient* fake_bluetooth_gatt_service_client_; - FakeBluetoothGattCharacteristicClient* + bluez::FakeBluetoothDeviceClient* fake_bluetooth_device_client_; + bluez::FakeBluetoothGattServiceClient* fake_bluetooth_gatt_service_client_; + bluez::FakeBluetoothGattCharacteristicClient* fake_bluetooth_gatt_characteristic_client_; - FakeBluetoothGattDescriptorClient* fake_bluetooth_gatt_descriptor_client_; + bluez::FakeBluetoothGattDescriptorClient* + fake_bluetooth_gatt_descriptor_client_; scoped_ptr<device::BluetoothGattConnection> gatt_conn_; ScopedVector<BluetoothGattNotifySession> update_sessions_; scoped_refptr<BluetoothAdapter> adapter_; @@ -190,10 +195,10 @@ TEST_F(BluetoothGattChromeOSTest, GattConnection) { fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress); + adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress); ASSERT_TRUE(device); ASSERT_FALSE(device->IsConnected()); ASSERT_FALSE(gatt_conn_.get()); @@ -211,7 +216,7 @@ EXPECT_TRUE(device->IsConnected()); ASSERT_TRUE(gatt_conn_.get()); EXPECT_TRUE(gatt_conn_->IsConnected()); - EXPECT_EQ(FakeBluetoothDeviceClient::kLowEnergyAddress, + EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress, gatt_conn_->GetDeviceAddress()); gatt_conn_->Disconnect(); @@ -253,8 +258,8 @@ EXPECT_TRUE(gatt_conn_->IsConnected()); fake_bluetooth_device_client_->RemoveDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); ASSERT_TRUE(gatt_conn_.get()); EXPECT_FALSE(gatt_conn_->IsConnected()); } @@ -263,10 +268,10 @@ // Create a fake LE device. We store the device pointer here because this is a // test. It's unsafe to do this in production as the device might get deleted. fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress); + adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress); ASSERT_TRUE(device); TestBluetoothAdapterObserver observer(adapter_); @@ -279,14 +284,14 @@ // Expose the fake Heart Rate Service. fake_bluetooth_gatt_service_client_->ExposeHeartRateService( - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); EXPECT_EQ(1, observer.gatt_service_added_count()); EXPECT_EQ(0, observer.gatt_service_removed_count()); EXPECT_FALSE(observer.last_gatt_service_id().empty()); EXPECT_EQ(1U, device->GetGattServices().size()); - EXPECT_EQ( - BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID), - observer.last_gatt_service_uuid()); + EXPECT_EQ(BluetoothUUID( + bluez::FakeBluetoothGattServiceClient::kHeartRateServiceUUID), + observer.last_gatt_service_uuid()); BluetoothGattService* service = device->GetGattService(observer.last_gatt_service_id()); @@ -306,9 +311,9 @@ EXPECT_EQ(1, observer.gatt_service_removed_count()); EXPECT_FALSE(observer.last_gatt_service_id().empty()); EXPECT_TRUE(device->GetGattServices().empty()); - EXPECT_EQ( - BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID), - observer.last_gatt_service_uuid()); + EXPECT_EQ(BluetoothUUID( + bluez::FakeBluetoothGattServiceClient::kHeartRateServiceUUID), + observer.last_gatt_service_uuid()); EXPECT_EQ(NULL, device->GetGattService(observer.last_gatt_service_id())); @@ -316,14 +321,14 @@ observer.last_gatt_service_uuid() = BluetoothUUID(); observer.last_gatt_service_id().clear(); fake_bluetooth_gatt_service_client_->ExposeHeartRateService( - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); EXPECT_EQ(2, observer.gatt_service_added_count()); EXPECT_EQ(1, observer.gatt_service_removed_count()); EXPECT_FALSE(observer.last_gatt_service_id().empty()); EXPECT_EQ(1U, device->GetGattServices().size()); - EXPECT_EQ( - BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID), - observer.last_gatt_service_uuid()); + EXPECT_EQ(BluetoothUUID( + bluez::FakeBluetoothGattServiceClient::kHeartRateServiceUUID), + observer.last_gatt_service_uuid()); // The object |service| points to should have been deallocated. |device| // should contain a brand new instance. @@ -339,30 +344,30 @@ observer.last_gatt_service_uuid() = BluetoothUUID(); observer.last_gatt_service_id().clear(); fake_bluetooth_device_client_->RemoveDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); EXPECT_EQ(2, observer.gatt_service_added_count()); EXPECT_EQ(2, observer.gatt_service_removed_count()); EXPECT_FALSE(observer.last_gatt_service_id().empty()); - EXPECT_EQ( - BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID), - observer.last_gatt_service_uuid()); - EXPECT_EQ(NULL, - adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress)); + EXPECT_EQ(BluetoothUUID( + bluez::FakeBluetoothGattServiceClient::kHeartRateServiceUUID), + observer.last_gatt_service_uuid()); + EXPECT_EQ(NULL, adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kLowEnergyAddress)); } TEST_F(BluetoothGattChromeOSTest, ServicesDiscovered) { // Create a fake LE device. We store the device pointer here because this is a // test. It's unsafe to do this in production as the device might get deleted. fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress); - FakeBluetoothDeviceClient::Properties* properties = + adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress); + bluez::FakeBluetoothDeviceClient::Properties* properties = fake_bluetooth_device_client_->GetProperties( - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); ASSERT_TRUE(device); @@ -372,23 +377,23 @@ // Expose the fake Heart Rate Service. fake_bluetooth_gatt_service_client_->ExposeHeartRateService( - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); // Notify that all services have been discovered. properties->gatt_services.ReplaceValue( fake_bluetooth_gatt_service_client_->GetServices()); EXPECT_EQ(1, observer.gatt_services_discovered_count()); EXPECT_EQ(device, observer.last_device()); - EXPECT_EQ(FakeBluetoothDeviceClient::kLowEnergyAddress, + EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress, observer.last_device_address()); } TEST_F(BluetoothGattChromeOSTest, GattCharacteristicAddedAndRemoved) { fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress); + adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress); ASSERT_TRUE(device); TestBluetoothAdapterObserver observer(adapter_); @@ -396,7 +401,7 @@ // Expose the fake Heart Rate service. This will asynchronously expose // characteristics. fake_bluetooth_gatt_service_client_->ExposeHeartRateService( - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); ASSERT_EQ(1, observer.gatt_service_added_count()); BluetoothGattService* service = @@ -453,10 +458,10 @@ TEST_F(BluetoothGattChromeOSTest, GattDescriptorAddedAndRemoved) { fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress); + adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress); ASSERT_TRUE(device); TestBluetoothAdapterObserver observer(adapter_); @@ -464,7 +469,7 @@ // Expose the fake Heart Rate service. This will asynchronously expose // characteristics. fake_bluetooth_gatt_service_client_->ExposeHeartRateService( - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); ASSERT_EQ(1, observer.gatt_service_added_count()); BluetoothGattService* service = @@ -525,7 +530,7 @@ observer.last_gatt_descriptor_uuid() = BluetoothUUID(); fake_bluetooth_gatt_descriptor_client_->ExposeDescriptor( dbus::ObjectPath(characteristic->GetIdentifier()), - FakeBluetoothGattDescriptorClient:: + bluez::FakeBluetoothGattDescriptorClient:: kClientCharacteristicConfigurationUUID); EXPECT_EQ(0, observer.gatt_service_changed_count()); EXPECT_EQ(1U, characteristic->GetDescriptors().size()); @@ -549,10 +554,10 @@ // Create the fake D-Bus objects. fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); fake_bluetooth_gatt_service_client_->ExposeHeartRateService( - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); while (!fake_bluetooth_gatt_characteristic_client_->IsHeartRateVisible()) base::RunLoop().RunUntilIdle(); ASSERT_TRUE(fake_bluetooth_gatt_service_client_->IsHeartRateVisible()); @@ -561,7 +566,7 @@ // Create the adapter. This should create all the GATT objects. GetAdapter(); BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress); + adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress); ASSERT_TRUE(device); EXPECT_EQ(1U, device->GetGattServices().size()); @@ -569,9 +574,9 @@ ASSERT_TRUE(service); EXPECT_FALSE(service->IsLocal()); EXPECT_TRUE(service->IsPrimary()); - EXPECT_EQ( - BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID), - service->GetUUID()); + EXPECT_EQ(BluetoothUUID( + bluez::FakeBluetoothGattServiceClient::kHeartRateServiceUUID), + service->GetUUID()); EXPECT_EQ(service, device->GetGattServices()[0]); EXPECT_EQ(service, device->GetGattService(service->GetIdentifier())); EXPECT_FALSE(service->IsLocal()); @@ -581,8 +586,8 @@ fake_bluetooth_gatt_characteristic_client_-> GetBodySensorLocationPath().value()); ASSERT_TRUE(characteristic); - EXPECT_EQ(BluetoothUUID( - FakeBluetoothGattCharacteristicClient::kBodySensorLocationUUID), + EXPECT_EQ(BluetoothUUID(bluez::FakeBluetoothGattCharacteristicClient:: + kBodySensorLocationUUID), characteristic->GetUUID()); EXPECT_FALSE(characteristic->IsLocal()); EXPECT_TRUE(characteristic->GetDescriptors().empty()); @@ -591,10 +596,9 @@ fake_bluetooth_gatt_characteristic_client_-> GetHeartRateControlPointPath().value()); ASSERT_TRUE(characteristic); - EXPECT_EQ( - BluetoothUUID( - FakeBluetoothGattCharacteristicClient::kHeartRateControlPointUUID), - characteristic->GetUUID()); + EXPECT_EQ(BluetoothUUID(bluez::FakeBluetoothGattCharacteristicClient:: + kHeartRateControlPointUUID), + characteristic->GetUUID()); EXPECT_FALSE(characteristic->IsLocal()); EXPECT_TRUE(characteristic->GetDescriptors().empty()); @@ -602,10 +606,9 @@ fake_bluetooth_gatt_characteristic_client_-> GetHeartRateMeasurementPath().value()); ASSERT_TRUE(characteristic); - EXPECT_EQ( - BluetoothUUID( - FakeBluetoothGattCharacteristicClient::kHeartRateMeasurementUUID), - characteristic->GetUUID()); + EXPECT_EQ(BluetoothUUID(bluez::FakeBluetoothGattCharacteristicClient:: + kHeartRateMeasurementUUID), + characteristic->GetUUID()); EXPECT_FALSE(characteristic->IsLocal()); EXPECT_EQ(1U, characteristic->GetDescriptors().size()); @@ -618,10 +621,10 @@ TEST_F(BluetoothGattChromeOSTest, GattCharacteristicValue) { fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress); + adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress); ASSERT_TRUE(device); TestBluetoothAdapterObserver observer(adapter_); @@ -629,7 +632,7 @@ // Expose the fake Heart Rate service. This will asynchronously expose // characteristics. fake_bluetooth_gatt_service_client_->ExposeHeartRateService( - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); ASSERT_EQ(1, observer.gatt_service_added_count()); BluetoothGattService* service = @@ -833,10 +836,10 @@ TEST_F(BluetoothGattChromeOSTest, GattCharacteristicProperties) { fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress); + adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress); ASSERT_TRUE(device); TestBluetoothAdapterObserver observer(adapter_); @@ -844,7 +847,7 @@ // Expose the fake Heart Rate service. This will asynchronously expose // characteristics. fake_bluetooth_gatt_service_client_->ExposeHeartRateService( - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); BluetoothGattService* service = device->GetGattService(observer.last_gatt_service_id()); @@ -875,10 +878,10 @@ TEST_F(BluetoothGattChromeOSTest, GattDescriptorValue) { fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress); + adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress); ASSERT_TRUE(device); TestBluetoothAdapterObserver observer(adapter_); @@ -886,7 +889,7 @@ // Expose the fake Heart Rate service. This will asynchronously expose // characteristics. fake_bluetooth_gatt_service_client_->ExposeHeartRateService( - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); ASSERT_EQ(1, observer.gatt_service_added_count()); BluetoothGattService* service = @@ -998,10 +1001,10 @@ TEST_F(BluetoothGattChromeOSTest, NotifySessions) { fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress); + adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress); ASSERT_TRUE(device); TestBluetoothAdapterObserver observer(adapter_); @@ -1009,7 +1012,7 @@ // Expose the fake Heart Rate service. This will asynchronously expose // characteristics. fake_bluetooth_gatt_service_client_->ExposeHeartRateService( - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); ASSERT_EQ(1, observer.gatt_service_added_count()); BluetoothGattService* service = @@ -1147,10 +1150,10 @@ TEST_F(BluetoothGattChromeOSTest, NotifySessionsMadeInactive) { fake_bluetooth_device_client_->CreateDevice( - dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress); + adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress); ASSERT_TRUE(device); TestBluetoothAdapterObserver observer(adapter_); @@ -1158,7 +1161,7 @@ // Expose the fake Heart Rate service. This will asynchronously expose // characteristics. fake_bluetooth_gatt_service_client_->ExposeHeartRateService( - dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath)); ASSERT_EQ(1, observer.gatt_service_added_count()); BluetoothGattService* service =
diff --git a/device/bluetooth/bluetooth_gatt_connection_chromeos.cc b/device/bluetooth/bluetooth_gatt_connection_chromeos.cc index 6c16db8..57aaa4d3 100644 --- a/device/bluetooth/bluetooth_gatt_connection_chromeos.cc +++ b/device/bluetooth/bluetooth_gatt_connection_chromeos.cc
@@ -6,9 +6,9 @@ #include "base/bind.h" #include "base/logging.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_device.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" namespace chromeos { @@ -23,11 +23,12 @@ DCHECK(!device_address_.empty()); DCHECK(object_path_.IsValid()); - DBusThreadManager::Get()->GetBluetoothDeviceClient()->AddObserver(this); + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->AddObserver(this); } BluetoothGattConnectionChromeOS::~BluetoothGattConnectionChromeOS() { - DBusThreadManager::Get()->GetBluetoothDeviceClient()->RemoveObserver(this); + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->RemoveObserver( + this); Disconnect(); } @@ -40,8 +41,8 @@ if (!connected_) return false; - BluetoothDeviceClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothDeviceClient()->GetProperties( + bluez::BluetoothDeviceClient::Properties* properties = + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties( object_path_); if (!properties || !properties->connected.value()) connected_ = false; @@ -82,8 +83,8 @@ if (!connected_) return; - BluetoothDeviceClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothDeviceClient()->GetProperties( + bluez::BluetoothDeviceClient::Properties* properties = + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties( object_path_); if (!properties) {
diff --git a/device/bluetooth/bluetooth_gatt_connection_chromeos.h b/device/bluetooth/bluetooth_gatt_connection_chromeos.h index 66c1a1a04..6e40283b 100644 --- a/device/bluetooth/bluetooth_gatt_connection_chromeos.h +++ b/device/bluetooth/bluetooth_gatt_connection_chromeos.h
@@ -9,9 +9,9 @@ #include "base/callback.h" #include "base/memory/weak_ptr.h" -#include "chromeos/dbus/bluetooth_device_client.h" #include "dbus/object_path.h" #include "device/bluetooth/bluetooth_gatt_connection.h" +#include "device/bluetooth/dbus/bluetooth_device_client.h" namespace device { @@ -23,8 +23,9 @@ // BluetoothGattConnectionChromeOS implements BluetoothGattConnection for the // Chrome OS platform. -class BluetoothGattConnectionChromeOS : public device::BluetoothGattConnection, - public BluetoothDeviceClient::Observer { +class BluetoothGattConnectionChromeOS + : public device::BluetoothGattConnection, + public bluez::BluetoothDeviceClient::Observer { public: explicit BluetoothGattConnectionChromeOS( scoped_refptr<device::BluetoothAdapter> adapter, @@ -37,7 +38,7 @@ void Disconnect() override; private: - // chromeos::BluetoothDeviceClient::Observer overrides. + // bluez::Bluetooth$1Client::Observer overrides. void DeviceRemoved(const dbus::ObjectPath& object_path) override; void DevicePropertyChanged(const dbus::ObjectPath& object_path, const std::string& property_name) override;
diff --git a/device/bluetooth/bluetooth_gatt_notify_session_chromeos.cc b/device/bluetooth/bluetooth_gatt_notify_session_chromeos.cc index ba7b843..02f7ed8b 100644 --- a/device/bluetooth/bluetooth_gatt_notify_session_chromeos.cc +++ b/device/bluetooth/bluetooth_gatt_notify_session_chromeos.cc
@@ -6,11 +6,11 @@ #include "base/bind.h" #include "base/logging.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_device.h" #include "device/bluetooth/bluetooth_gatt_service.h" #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" namespace chromeos { @@ -32,12 +32,13 @@ DCHECK(!characteristic_id_.empty()); DCHECK(object_path_.IsValid()); - DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->AddObserver( - this); + bluez::BluezDBusManager::Get() + ->GetBluetoothGattCharacteristicClient() + ->AddObserver(this); } BluetoothGattNotifySessionChromeOS::~BluetoothGattNotifySessionChromeOS() { - DBusThreadManager::Get() + bluez::BluezDBusManager::Get() ->GetBluetoothGattCharacteristicClient() ->RemoveObserver(this); Stop(base::Bind(&base::DoNothing)); @@ -58,11 +59,12 @@ // actually active, since the characteristic might have stopped sending // notifications yet this method was called before we processed the // observer event (e.g. because somebody else called this method in their - // BluetoothGattCharacteristicClient::Observer implementation, which was + // bluez::BluetoothGattCharacteristicClient::Observer implementation, which + // was // called before ours). Check the client to see if notifications are still // being sent. - BluetoothGattCharacteristicClient::Properties* properties = - DBusThreadManager::Get() + bluez::BluetoothGattCharacteristicClient::Properties* properties = + bluez::BluezDBusManager::Get() ->GetBluetoothGattCharacteristicClient() ->GetProperties(object_path_); if (!properties || !properties->notifying.value()) @@ -115,8 +117,8 @@ if (!active_) return; - BluetoothGattCharacteristicClient::Properties* properties = - DBusThreadManager::Get() + bluez::BluetoothGattCharacteristicClient::Properties* properties = + bluez::BluezDBusManager::Get() ->GetBluetoothGattCharacteristicClient() ->GetProperties(object_path_); if (!properties) {
diff --git a/device/bluetooth/bluetooth_gatt_notify_session_chromeos.h b/device/bluetooth/bluetooth_gatt_notify_session_chromeos.h index 245a72f..ef6e8da4 100644 --- a/device/bluetooth/bluetooth_gatt_notify_session_chromeos.h +++ b/device/bluetooth/bluetooth_gatt_notify_session_chromeos.h
@@ -8,8 +8,8 @@ #include <string> #include "base/callback.h" -#include "chromeos/dbus/bluetooth_gatt_characteristic_client.h" #include "device/bluetooth/bluetooth_gatt_notify_session.h" +#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h" namespace device { @@ -25,7 +25,7 @@ // BluetoothGattNotifySession for the Chrome OS platform. class BluetoothGattNotifySessionChromeOS : public device::BluetoothGattNotifySession, - public BluetoothGattCharacteristicClient::Observer { + public bluez::BluetoothGattCharacteristicClient::Observer { public: ~BluetoothGattNotifySessionChromeOS() override; @@ -44,7 +44,7 @@ const std::string& characteristic_identifier, const dbus::ObjectPath& characteristic_path); - // BluetoothGattCharacteristicClient::Observer overrides. + // bluez::BluetoothGattCharacteristicClient::Observer overrides. void GattCharacteristicRemoved(const dbus::ObjectPath& object_path) override; void GattCharacteristicPropertyChanged( const dbus::ObjectPath& object_path,
diff --git a/device/bluetooth/bluetooth_pairing_chromeos.cc b/device/bluetooth/bluetooth_pairing_chromeos.cc index 2bc67cb..4541fb38 100644 --- a/device/bluetooth/bluetooth_pairing_chromeos.cc +++ b/device/bluetooth/bluetooth_pairing_chromeos.cc
@@ -55,25 +55,26 @@ } if (!pincode_callback_.is_null()) { - pincode_callback_.Run(BluetoothAgentServiceProvider::Delegate::CANCELLED, - ""); + pincode_callback_.Run( + bluez::BluetoothAgentServiceProvider::Delegate::CANCELLED, ""); } if (!passkey_callback_.is_null()) { - passkey_callback_.Run(BluetoothAgentServiceProvider::Delegate::CANCELLED, - 0); + passkey_callback_.Run( + bluez::BluetoothAgentServiceProvider::Delegate::CANCELLED, 0); } if (!confirmation_callback_.is_null()) { confirmation_callback_.Run( - BluetoothAgentServiceProvider::Delegate::CANCELLED); + bluez::BluetoothAgentServiceProvider::Delegate::CANCELLED); } pairing_delegate_ = NULL; } void BluetoothPairingChromeOS::RequestPinCode( - const BluetoothAgentServiceProvider::Delegate::PinCodeCallback& callback) { + const bluez::BluetoothAgentServiceProvider::Delegate::PinCodeCallback& + callback) { UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod", UMA_PAIRING_METHOD_REQUEST_PINCODE, UMA_PAIRING_METHOD_COUNT); @@ -92,7 +93,7 @@ if (pincode_callback_.is_null()) return; - pincode_callback_.Run(BluetoothAgentServiceProvider::Delegate::SUCCESS, + pincode_callback_.Run(bluez::BluetoothAgentServiceProvider::Delegate::SUCCESS, pincode); pincode_callback_.Reset(); @@ -120,7 +121,8 @@ } void BluetoothPairingChromeOS::RequestPasskey( - const BluetoothAgentServiceProvider::Delegate::PasskeyCallback& callback) { + const bluez::BluetoothAgentServiceProvider::Delegate::PasskeyCallback& + callback) { UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod", UMA_PAIRING_METHOD_REQUEST_PASSKEY, UMA_PAIRING_METHOD_COUNT); @@ -139,7 +141,7 @@ if (passkey_callback_.is_null()) return; - passkey_callback_.Run(BluetoothAgentServiceProvider::Delegate::SUCCESS, + passkey_callback_.Run(bluez::BluetoothAgentServiceProvider::Delegate::SUCCESS, passkey); passkey_callback_.Reset(); @@ -158,7 +160,6 @@ ResetCallbacks(); pairing_delegate_used_ = true; pairing_delegate_->DisplayPasskey(device_, passkey); - } void BluetoothPairingChromeOS::KeysEntered(uint16 entered) { @@ -174,7 +175,7 @@ void BluetoothPairingChromeOS::RequestConfirmation( uint32 passkey, - const BluetoothAgentServiceProvider::Delegate::ConfirmationCallback& + const bluez::BluetoothAgentServiceProvider::Delegate::ConfirmationCallback& callback) { UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod", UMA_PAIRING_METHOD_CONFIRM_PASSKEY, @@ -187,7 +188,7 @@ } void BluetoothPairingChromeOS::RequestAuthorization( - const BluetoothAgentServiceProvider::Delegate::ConfirmationCallback& + const bluez::BluetoothAgentServiceProvider::Delegate::ConfirmationCallback& callback) { UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod", UMA_PAIRING_METHOD_NONE, @@ -207,7 +208,8 @@ if (confirmation_callback_.is_null()) return; - confirmation_callback_.Run(BluetoothAgentServiceProvider::Delegate::SUCCESS); + confirmation_callback_.Run( + bluez::BluetoothAgentServiceProvider::Delegate::SUCCESS); confirmation_callback_.Reset(); // If this is not an outgoing connection to the device, clean up the pairing @@ -218,12 +220,13 @@ } bool BluetoothPairingChromeOS::RejectPairing() { - return RunPairingCallbacks(BluetoothAgentServiceProvider::Delegate::REJECTED); + return RunPairingCallbacks( + bluez::BluetoothAgentServiceProvider::Delegate::REJECTED); } bool BluetoothPairingChromeOS::CancelPairing() { return RunPairingCallbacks( - BluetoothAgentServiceProvider::Delegate::CANCELLED); + bluez::BluetoothAgentServiceProvider::Delegate::CANCELLED); } BluetoothDevice::PairingDelegate* @@ -238,7 +241,7 @@ } bool BluetoothPairingChromeOS::RunPairingCallbacks( - BluetoothAgentServiceProvider::Delegate::Status status) { + bluez::BluetoothAgentServiceProvider::Delegate::Status status) { pairing_delegate_used_ = true; bool callback_run = false;
diff --git a/device/bluetooth/bluetooth_pairing_chromeos.h b/device/bluetooth/bluetooth_pairing_chromeos.h index b50a328e..0a4ddb6 100644 --- a/device/bluetooth/bluetooth_pairing_chromeos.h +++ b/device/bluetooth/bluetooth_pairing_chromeos.h
@@ -5,8 +5,8 @@ #ifndef DEVICE_BLUETOOTH_BLUETOOTH_PAIRING_CHROMEOS_H_ #define DEVICE_BLUETOOTH_BLUETOOTH_PAIRING_CHROMEOS_H_ -#include "chromeos/dbus/bluetooth_agent_service_provider.h" #include "device/bluetooth/bluetooth_device.h" +#include "device/bluetooth/dbus/bluetooth_agent_service_provider.h" namespace chromeos { @@ -36,7 +36,8 @@ // calls on this object are translated into the appropriate response to // |callback|. void RequestPinCode( - const BluetoothAgentServiceProvider::Delegate::PinCodeCallback& callback); + const bluez::BluetoothAgentServiceProvider::Delegate::PinCodeCallback& + callback); // Indicates whether the device is currently pairing and expecting a // PIN Code to be returned. @@ -57,7 +58,8 @@ // calls on this object are translated into the appropriate response to // |callback|. void RequestPasskey( - const BluetoothAgentServiceProvider::Delegate::PasskeyCallback& callback); + const bluez::BluetoothAgentServiceProvider::Delegate::PasskeyCallback& + callback); // Sends the Passkey |passkey| to the remote device during pairing. // @@ -79,18 +81,16 @@ // from the current pairing delegate. The ConfirmPairing(), RejectPairing() // and CancelPairing() method calls on this object are translated into the // appropriate response to |callback|. - void RequestConfirmation( - uint32 passkey, - const BluetoothAgentServiceProvider::Delegate::ConfirmationCallback& - callback); + void RequestConfirmation(uint32 passkey, + const bluez::BluetoothAgentServiceProvider:: + Delegate::ConfirmationCallback& callback); // Requests authorization that the current device be allowed to pair with // this device from the current pairing delegate. The ConfirmPairing(), // RejectPairing() and CancelPairing() method calls on this object are // translated into the appropriate response to |callback|. - void RequestAuthorization( - const BluetoothAgentServiceProvider::Delegate::ConfirmationCallback& - callback); + void RequestAuthorization(const bluez::BluetoothAgentServiceProvider:: + Delegate::ConfirmationCallback& callback); // Confirms to the remote device during pairing that a passkey provided by // the ConfirmPasskey() delegate call is displayed on both devices. @@ -115,7 +115,7 @@ // Internal method to respond to the relevant callback for a RejectPairing // or CancelPairing call. bool RunPairingCallbacks( - BluetoothAgentServiceProvider::Delegate::Status status); + bluez::BluetoothAgentServiceProvider::Delegate::Status status); // The underlying BluetoothDeviceChromeOS that owns this pairing context. BluetoothDeviceChromeOS* device_; @@ -131,11 +131,13 @@ // During pairing these callbacks are set to those provided by method calls // made on the BluetoothAdapterChromeOS instance by its respective - // BluetoothAgentServiceProvider instance, and are called by our own + // bluez::BluetoothAgentServiceProvider instance, and are called by our own // method calls such as SetPinCode() and SetPasskey(). - BluetoothAgentServiceProvider::Delegate::PinCodeCallback pincode_callback_; - BluetoothAgentServiceProvider::Delegate::PasskeyCallback passkey_callback_; - BluetoothAgentServiceProvider::Delegate::ConfirmationCallback + bluez::BluetoothAgentServiceProvider::Delegate::PinCodeCallback + pincode_callback_; + bluez::BluetoothAgentServiceProvider::Delegate::PasskeyCallback + passkey_callback_; + bluez::BluetoothAgentServiceProvider::Delegate::ConfirmationCallback confirmation_callback_; DISALLOW_COPY_AND_ASSIGN(BluetoothPairingChromeOS);
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc index f720474..f0825f6b 100644 --- a/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc +++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc
@@ -5,8 +5,12 @@ #include "device/bluetooth/bluetooth_remote_gatt_characteristic_android.h" #include "base/android/jni_android.h" +#include "base/android/jni_array.h" #include "base/android/jni_string.h" +#include "base/bind.h" #include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "device/bluetooth/bluetooth_remote_gatt_service_android.h" #include "jni/ChromeBluetoothRemoteGattCharacteristic_jni.h" using base::android::AttachCurrentThread; @@ -18,19 +22,25 @@ BluetoothRemoteGattCharacteristicAndroid::Create( const std::string& instanceId, jobject /* BluetoothGattCharacteristicWrapper */ - bluetooth_gatt_characteristic_wrapper) { + bluetooth_gatt_characteristic_wrapper, + jobject /* ChromeBluetoothDevice */ chrome_bluetooth_device) { scoped_ptr<BluetoothRemoteGattCharacteristicAndroid> characteristic( new BluetoothRemoteGattCharacteristicAndroid(instanceId)); characteristic->j_characteristic_.Reset( Java_ChromeBluetoothRemoteGattCharacteristic_create( - AttachCurrentThread(), bluetooth_gatt_characteristic_wrapper)); + AttachCurrentThread(), + reinterpret_cast<intptr_t>(characteristic.get()), + bluetooth_gatt_characteristic_wrapper, chrome_bluetooth_device)); return characteristic; } BluetoothRemoteGattCharacteristicAndroid:: - ~BluetoothRemoteGattCharacteristicAndroid() {} + ~BluetoothRemoteGattCharacteristicAndroid() { + Java_ChromeBluetoothRemoteGattCharacteristic_onBluetoothRemoteGattCharacteristicAndroidDestruction( + AttachCurrentThread(), j_characteristic_.obj()); +} // static bool BluetoothRemoteGattCharacteristicAndroid::RegisterJNI(JNIEnv* env) { @@ -38,6 +48,11 @@ env); // Generated in ChromeBluetoothRemoteGattCharacteristic_jni.h } +base::android::ScopedJavaLocalRef<jobject> +BluetoothRemoteGattCharacteristicAndroid::GetJavaObject() { + return base::android::ScopedJavaLocalRef<jobject>(j_characteristic_); +} + std::string BluetoothRemoteGattCharacteristicAndroid::GetIdentifier() const { return instanceId_; } @@ -54,7 +69,6 @@ const std::vector<uint8>& BluetoothRemoteGattCharacteristicAndroid::GetValue() const { - NOTIMPLEMENTED(); return value_; } @@ -115,14 +129,88 @@ void BluetoothRemoteGattCharacteristicAndroid::ReadRemoteCharacteristic( const ValueCallback& callback, const ErrorCallback& error_callback) { - NOTIMPLEMENTED(); + if (read_pending_ || write_pending_) { + error_callback.Run(BluetoothGattService::GATT_ERROR_IN_PROGRESS); + } + + if (!Java_ChromeBluetoothRemoteGattCharacteristic_readRemoteCharacteristic( + AttachCurrentThread(), j_characteristic_.obj())) { + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(error_callback, + BluetoothRemoteGattServiceAndroid::GATT_ERROR_FAILED)); + return; + } + + read_pending_ = true; + read_callback_ = callback; + read_error_callback_ = error_callback; } void BluetoothRemoteGattCharacteristicAndroid::WriteRemoteCharacteristic( const std::vector<uint8>& new_value, const base::Closure& callback, const ErrorCallback& error_callback) { - NOTIMPLEMENTED(); + if (read_pending_ || write_pending_) { + error_callback.Run(BluetoothGattService::GATT_ERROR_IN_PROGRESS); + } + + JNIEnv* env = AttachCurrentThread(); + if (!Java_ChromeBluetoothRemoteGattCharacteristic_writeRemoteCharacteristic( + env, j_characteristic_.obj(), + base::android::ToJavaByteArray(env, new_value).obj())) { + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(error_callback, + BluetoothRemoteGattServiceAndroid::GATT_ERROR_FAILED)); + return; + } + + write_pending_ = true; + write_callback_ = callback; + write_error_callback_ = error_callback; +} + +void BluetoothRemoteGattCharacteristicAndroid::OnRead(JNIEnv* env, + jobject jcaller, + int32_t status, + jbyteArray value) { + read_pending_ = false; + + // Clear callbacks before calling to avoid reentrancy issues. + ValueCallback read_callback = read_callback_; + ErrorCallback read_error_callback = read_error_callback_; + read_callback_.Reset(); + read_error_callback_.Reset(); + + if (status == 0 // android.bluetooth.BluetoothGatt.GATT_SUCCESS + && !read_callback.is_null()) { + base::android::JavaByteArrayToByteVector(env, value, &value_); + read_callback.Run(value_); + } else if (!read_error_callback.is_null()) { + read_error_callback.Run( + BluetoothRemoteGattServiceAndroid::GetGattErrorCode(status)); + } +} + +void BluetoothRemoteGattCharacteristicAndroid::OnWrite(JNIEnv* env, + jobject jcaller, + int32_t status) { + write_pending_ = false; + + // Clear callbacks before calling to avoid reentrancy issues. + base::Closure write_callback = write_callback_; + ErrorCallback write_error_callback = write_error_callback_; + write_callback_.Reset(); + write_error_callback_.Reset(); + + if (status == 0 // android.bluetooth.BluetoothGatt.GATT_SUCCESS + && !write_callback.is_null()) { + write_callback.Run(); + } else if (!write_error_callback.is_null()) { + write_error_callback.Run( + BluetoothRemoteGattServiceAndroid::GetGattErrorCode(status)); + } } BluetoothRemoteGattCharacteristicAndroid::
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_android.h b/device/bluetooth/bluetooth_remote_gatt_characteristic_android.h index a97160f..b5c85a3 100644 --- a/device/bluetooth/bluetooth_remote_gatt_characteristic_android.h +++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_android.h
@@ -28,13 +28,17 @@ static scoped_ptr<BluetoothRemoteGattCharacteristicAndroid> Create( const std::string& instanceId, jobject /* BluetoothGattCharacteristicWrapper */ - bluetooth_gatt_characteristic_wrapper); + bluetooth_gatt_characteristic_wrapper, + jobject /* ChromeBluetoothDevice */ chrome_bluetooth_device); ~BluetoothRemoteGattCharacteristicAndroid() override; // Register C++ methods exposed to Java using JNI. static bool RegisterJNI(JNIEnv* env); + // Returns the associated ChromeBluetoothRemoteGattCharacteristic Java object. + base::android::ScopedJavaLocalRef<jobject> GetJavaObject(); + // BluetoothGattCharacteristic interface: std::string GetIdentifier() const override; BluetoothUUID GetUUID() const override; @@ -57,6 +61,12 @@ const base::Closure& callback, const ErrorCallback& error_callback) override; + // Callback after Read operation completes. + void OnRead(JNIEnv* env, jobject jcaller, int32_t status, jbyteArray value); + + // Callback after Write operation completes. + void OnWrite(JNIEnv* env, jobject jcaller, int32_t status); + private: BluetoothRemoteGattCharacteristicAndroid(const std::string& instanceId); @@ -67,6 +77,16 @@ // Adapter unique instance ID. std::string instanceId_; + // ReadRemoteCharacteristic callbacks and pending state. + bool read_pending_ = false; + ValueCallback read_callback_; + ErrorCallback read_error_callback_; + + // WriteRemoteCharacteristic callbacks and pending state. + bool write_pending_ = false; + base::Closure write_callback_; + ErrorCallback write_error_callback_; + std::vector<uint8> value_; DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattCharacteristicAndroid);
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.cc index 7a0f5e39..7374f160 100644 --- a/device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.cc +++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.cc
@@ -8,13 +8,13 @@ #include "base/logging.h" #include "base/strings/stringprintf.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "device/bluetooth/bluetooth_adapter_chromeos.h" #include "device/bluetooth/bluetooth_device.h" #include "device/bluetooth/bluetooth_gatt_notify_session_chromeos.h" #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h" #include "device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.h" #include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" #include "third_party/cros_system_api/dbus/service_constants.h" namespace chromeos { @@ -44,12 +44,13 @@ weak_ptr_factory_(this) { VLOG(1) << "Creating remote GATT characteristic with identifier: " << GetIdentifier() << ", UUID: " << GetUUID().canonical_value(); - DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()->AddObserver( - this); + bluez::BluezDBusManager::Get() + ->GetBluetoothGattDescriptorClient() + ->AddObserver(this); // Add all known GATT characteristic descriptors. const std::vector<dbus::ObjectPath>& gatt_descs = - DBusThreadManager::Get() + bluez::BluezDBusManager::Get() ->GetBluetoothGattDescriptorClient() ->GetDescriptors(); for (std::vector<dbus::ObjectPath>::const_iterator iter = gatt_descs.begin(); @@ -59,8 +60,9 @@ BluetoothRemoteGattCharacteristicChromeOS:: ~BluetoothRemoteGattCharacteristicChromeOS() { - DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()->RemoveObserver( - this); + bluez::BluezDBusManager::Get() + ->GetBluetoothGattDescriptorClient() + ->RemoveObserver(this); // Clean up all the descriptors. There isn't much point in notifying service // observers for each descriptor that gets removed, so just delete them. @@ -82,8 +84,8 @@ device::BluetoothUUID BluetoothRemoteGattCharacteristicChromeOS::GetUUID() const { - BluetoothGattCharacteristicClient::Properties* properties = - DBusThreadManager::Get() + bluez::BluetoothGattCharacteristicClient::Properties* properties = + bluez::BluezDBusManager::Get() ->GetBluetoothGattCharacteristicClient() ->GetProperties(object_path_); DCHECK(properties); @@ -96,8 +98,8 @@ const std::vector<uint8>& BluetoothRemoteGattCharacteristicChromeOS::GetValue() const { - BluetoothGattCharacteristicClient::Properties* properties = - DBusThreadManager::Get() + bluez::BluetoothGattCharacteristicClient::Properties* properties = + bluez::BluezDBusManager::Get() ->GetBluetoothGattCharacteristicClient() ->GetProperties(object_path_); @@ -113,8 +115,8 @@ device::BluetoothGattCharacteristic::Properties BluetoothRemoteGattCharacteristicChromeOS::GetProperties() const { - BluetoothGattCharacteristicClient::Properties* properties = - DBusThreadManager::Get() + bluez::BluetoothGattCharacteristicClient::Properties* properties = + bluez::BluezDBusManager::Get() ->GetBluetoothGattCharacteristicClient() ->GetProperties(object_path_); DCHECK(properties); @@ -157,8 +159,8 @@ } bool BluetoothRemoteGattCharacteristicChromeOS::IsNotifying() const { - BluetoothGattCharacteristicClient::Properties* properties = - DBusThreadManager::Get() + bluez::BluetoothGattCharacteristicClient::Properties* properties = + bluez::BluezDBusManager::Get() ->GetBluetoothGattCharacteristicClient() ->GetProperties(object_path_); DCHECK(properties); @@ -204,10 +206,12 @@ << GetIdentifier() << ", UUID: " << GetUUID().canonical_value() << "."; - DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->ReadValue( - object_path_, callback, - base::Bind(&BluetoothRemoteGattCharacteristicChromeOS::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); + bluez::BluezDBusManager::Get() + ->GetBluetoothGattCharacteristicClient() + ->ReadValue( + object_path_, callback, + base::Bind(&BluetoothRemoteGattCharacteristicChromeOS::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); } void BluetoothRemoteGattCharacteristicChromeOS::WriteRemoteCharacteristic( @@ -218,10 +222,12 @@ << GetIdentifier() << ", UUID: " << GetUUID().canonical_value() << ", with value: " << new_value << "."; - DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->WriteValue( - object_path_, new_value, callback, - base::Bind(&BluetoothRemoteGattCharacteristicChromeOS::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); + bluez::BluezDBusManager::Get() + ->GetBluetoothGattCharacteristicClient() + ->WriteValue( + object_path_, new_value, callback, + base::Bind(&BluetoothRemoteGattCharacteristicChromeOS::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); } void BluetoothRemoteGattCharacteristicChromeOS::StartNotifySession( @@ -267,13 +273,16 @@ } notify_call_pending_ = true; - DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->StartNotify( - object_path_, - base::Bind( - &BluetoothRemoteGattCharacteristicChromeOS::OnStartNotifySuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothRemoteGattCharacteristicChromeOS::OnStartNotifyError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); + bluez::BluezDBusManager::Get() + ->GetBluetoothGattCharacteristicClient() + ->StartNotify( + object_path_, + base::Bind( + &BluetoothRemoteGattCharacteristicChromeOS::OnStartNotifySuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind( + &BluetoothRemoteGattCharacteristicChromeOS::OnStartNotifyError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); } void BluetoothRemoteGattCharacteristicChromeOS::RemoveNotifySession( @@ -302,13 +311,16 @@ DCHECK(num_notify_sessions_ == 1); notify_call_pending_ = true; - DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->StopNotify( - object_path_, - base::Bind( - &BluetoothRemoteGattCharacteristicChromeOS::OnStopNotifySuccess, - weak_ptr_factory_.GetWeakPtr(), callback), - base::Bind(&BluetoothRemoteGattCharacteristicChromeOS::OnStopNotifyError, - weak_ptr_factory_.GetWeakPtr(), callback)); + bluez::BluezDBusManager::Get() + ->GetBluetoothGattCharacteristicClient() + ->StopNotify( + object_path_, + base::Bind( + &BluetoothRemoteGattCharacteristicChromeOS::OnStopNotifySuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind( + &BluetoothRemoteGattCharacteristicChromeOS::OnStopNotifyError, + weak_ptr_factory_.GetWeakPtr(), callback)); } void BluetoothRemoteGattCharacteristicChromeOS::GattDescriptorAdded( @@ -319,8 +331,8 @@ return; } - BluetoothGattDescriptorClient::Properties* properties = - DBusThreadManager::Get() + bluez::BluetoothGattDescriptorClient::Properties* properties = + bluez::BluezDBusManager::Get() ->GetBluetoothGattDescriptorClient() ->GetProperties(object_path); DCHECK(properties); @@ -372,8 +384,8 @@ return; } - BluetoothGattDescriptorClient::Properties* properties = - DBusThreadManager::Get() + bluez::BluetoothGattDescriptorClient::Properties* properties = + bluez::BluezDBusManager::Get() ->GetBluetoothGattDescriptorClient() ->GetProperties(object_path);
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h b/device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h index a23a1178..361b3197 100644 --- a/device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h +++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h
@@ -12,10 +12,10 @@ #include <vector> #include "base/memory/weak_ptr.h" -#include "chromeos/dbus/bluetooth_gatt_descriptor_client.h" #include "dbus/object_path.h" #include "device/bluetooth/bluetooth_gatt_characteristic.h" #include "device/bluetooth/bluetooth_uuid.h" +#include "device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h" namespace device { @@ -34,7 +34,7 @@ // platform. class BluetoothRemoteGattCharacteristicChromeOS : public device::BluetoothGattCharacteristic, - public BluetoothGattDescriptorClient::Observer { + public bluez::BluetoothGattDescriptorClient::Observer { public: // device::BluetoothGattCharacteristic overrides. std::string GetIdentifier() const override; @@ -78,7 +78,7 @@ const dbus::ObjectPath& object_path); ~BluetoothRemoteGattCharacteristicChromeOS() override; - // BluetoothGattDescriptorClient::Observer overrides. + // bluez::BluetoothGattDescriptorClient::Observer overrides. void GattDescriptorAdded(const dbus::ObjectPath& object_path) override; void GattDescriptorRemoved(const dbus::ObjectPath& object_path) override; void GattDescriptorPropertyChanged(const dbus::ObjectPath& object_path,
diff --git a/device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.cc b/device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.cc index ab1074f8..f864c3b 100644 --- a/device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.cc +++ b/device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.cc
@@ -7,10 +7,10 @@ #include "base/bind.h" #include "base/logging.h" #include "base/strings/stringprintf.h" -#include "chromeos/dbus/bluetooth_gatt_descriptor_client.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h" #include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h" +#include "device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" namespace chromeos { @@ -47,8 +47,8 @@ } device::BluetoothUUID BluetoothRemoteGattDescriptorChromeOS::GetUUID() const { - BluetoothGattDescriptorClient::Properties* properties = - DBusThreadManager::Get() + bluez::BluetoothGattDescriptorClient::Properties* properties = + bluez::BluezDBusManager::Get() ->GetBluetoothGattDescriptorClient() ->GetProperties(object_path_); DCHECK(properties); @@ -61,8 +61,8 @@ const std::vector<uint8>& BluetoothRemoteGattDescriptorChromeOS::GetValue() const { - BluetoothGattDescriptorClient::Properties* properties = - DBusThreadManager::Get() + bluez::BluetoothGattDescriptorClient::Properties* properties = + bluez::BluezDBusManager::Get() ->GetBluetoothGattDescriptorClient() ->GetProperties(object_path_); @@ -90,7 +90,7 @@ << "descriptor: " << GetIdentifier() << ", UUID: " << GetUUID().canonical_value(); - DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()->ReadValue( + bluez::BluezDBusManager::Get()->GetBluetoothGattDescriptorClient()->ReadValue( object_path_, callback, base::Bind(&BluetoothRemoteGattDescriptorChromeOS::OnError, weak_ptr_factory_.GetWeakPtr(), error_callback)); @@ -105,10 +105,11 @@ << GetUUID().canonical_value() << ", with value: " << new_value << "."; - DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()->WriteValue( - object_path_, new_value, callback, - base::Bind(&BluetoothRemoteGattDescriptorChromeOS::OnError, - weak_ptr_factory_.GetWeakPtr(), error_callback)); + bluez::BluezDBusManager::Get() + ->GetBluetoothGattDescriptorClient() + ->WriteValue(object_path_, new_value, callback, + base::Bind(&BluetoothRemoteGattDescriptorChromeOS::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); } void BluetoothRemoteGattDescriptorChromeOS::OnError(
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_android.cc b/device/bluetooth/bluetooth_remote_gatt_service_android.cc index 01e01a6f..3cb8c65b 100644 --- a/device/bluetooth/bluetooth_remote_gatt_service_android.cc +++ b/device/bluetooth/bluetooth_remote_gatt_service_android.cc
@@ -20,8 +20,9 @@ BluetoothRemoteGattServiceAndroid::Create( BluetoothAdapterAndroid* adapter, BluetoothDeviceAndroid* device, - jobject bluetooth_gatt_service_wrapper, - const std::string& instanceId) { + jobject /* BluetoothGattServiceWrapper */ bluetooth_gatt_service_wrapper, + const std::string& instanceId, + jobject /* ChromeBluetoothDevice */ chrome_bluetooth_device) { scoped_ptr<BluetoothRemoteGattServiceAndroid> service( new BluetoothRemoteGattServiceAndroid(adapter, device, instanceId)); @@ -29,7 +30,8 @@ service->j_service_.Reset(Java_ChromeBluetoothRemoteGattService_create( env, reinterpret_cast<intptr_t>(service.get()), bluetooth_gatt_service_wrapper, - base::android::ConvertUTF8ToJavaString(env, instanceId).obj())); + base::android::ConvertUTF8ToJavaString(env, instanceId).obj(), + chrome_bluetooth_device)); return service; } @@ -50,6 +52,60 @@ return base::android::ScopedJavaLocalRef<jobject>(j_service_); } +// static +BluetoothGattService::GattErrorCode +BluetoothRemoteGattServiceAndroid::GetGattErrorCode(int bluetooth_gatt_code) { + DCHECK(bluetooth_gatt_code != 0) << "Only errors valid. 0 == GATT_SUCCESS."; + + // TODO(scheib) Create new BluetoothGattService::GattErrorCode enums for + // android values not yet represented. http://crbug.com/548498 + switch (bluetooth_gatt_code) { // android.bluetooth.BluetoothGatt values: + case 0x00000101: // GATT_FAILURE + return GATT_ERROR_FAILED; + case 0x0000000d: // GATT_INVALID_ATTRIBUTE_LENGTH + return GATT_ERROR_INVALID_LENGTH; + case 0x00000002: // GATT_READ_NOT_PERMITTED + return GATT_ERROR_NOT_PERMITTED; + case 0x00000006: // GATT_REQUEST_NOT_SUPPORTED + return GATT_ERROR_NOT_SUPPORTED; + case 0x00000003: // GATT_WRITE_NOT_PERMITTED + return GATT_ERROR_NOT_PERMITTED; + default: + VLOG(1) << "Unhandled status: " << bluetooth_gatt_code; + return BluetoothGattService::GATT_ERROR_UNKNOWN; + } +} + +// static +int BluetoothRemoteGattServiceAndroid::GetAndroidErrorCode( + BluetoothGattService::GattErrorCode error_code) { + // TODO(scheib) Create new BluetoothGattService::GattErrorCode enums for + // android values not yet represented. http://crbug.com/548498 + switch (error_code) { // Return values from android.bluetooth.BluetoothGatt: + case GATT_ERROR_UNKNOWN: + return 0x00000101; // GATT_FAILURE. No good match. + case GATT_ERROR_FAILED: + return 0x00000101; // GATT_FAILURE + case GATT_ERROR_IN_PROGRESS: + return 0x00000101; // GATT_FAILURE. No good match. + case GATT_ERROR_INVALID_LENGTH: + return 0x0000000d; // GATT_INVALID_ATTRIBUTE_LENGTH + case GATT_ERROR_NOT_PERMITTED: + // Can't distinguish between: + // 0x00000002: // GATT_READ_NOT_PERMITTED + // 0x00000003: // GATT_WRITE_NOT_PERMITTED + return 0x00000101; // GATT_FAILURE. No good match. + case GATT_ERROR_NOT_AUTHORIZED: + return 0x00000101; // GATT_FAILURE. No good match. + case GATT_ERROR_NOT_PAIRED: + return 0x00000101; // GATT_FAILURE. No good match. + case GATT_ERROR_NOT_SUPPORTED: + return 0x00000006; // GATT_REQUEST_NOT_SUPPORTED + } + VLOG(1) << "Unhandled error_code: " << error_code; + return 0x00000101; // GATT_FAILURE. No good match. +} + std::string BluetoothRemoteGattServiceAndroid::GetIdentifier() const { return instanceId_; } @@ -125,7 +181,8 @@ jobject caller, const jstring& instanceId, jobject /* BluetoothGattCharacteristicWrapper */ - bluetooth_gatt_characteristic_wrapper) { + bluetooth_gatt_characteristic_wrapper, + jobject /* ChromeBluetoothDevice */ chrome_bluetooth_device) { std::string instanceIdString = base::android::ConvertJavaStringToUTF8(env, instanceId); @@ -134,7 +191,8 @@ characteristics_.set( instanceIdString, BluetoothRemoteGattCharacteristicAndroid::Create( - instanceIdString, bluetooth_gatt_characteristic_wrapper)); + instanceIdString, bluetooth_gatt_characteristic_wrapper, + chrome_bluetooth_device)); } BluetoothRemoteGattServiceAndroid::BluetoothRemoteGattServiceAndroid(
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_android.h b/device/bluetooth/bluetooth_remote_gatt_service_android.h index c3fc5c8..9c642b3e 100644 --- a/device/bluetooth/bluetooth_remote_gatt_service_android.h +++ b/device/bluetooth/bluetooth_remote_gatt_service_android.h
@@ -35,9 +35,9 @@ static scoped_ptr<BluetoothRemoteGattServiceAndroid> Create( BluetoothAdapterAndroid* adapter, BluetoothDeviceAndroid* device, - jobject /* BluetoothRemoteGattServiceWrapper */ - bluetooth_gatt_service_wrapper, - const std::string& instanceId); + jobject /* BluetoothGattServiceWrapper */ bluetooth_gatt_service_wrapper, + const std::string& instanceId, + jobject /* ChromeBluetoothDevice */ chrome_bluetooth_device); ~BluetoothRemoteGattServiceAndroid() override; @@ -47,6 +47,16 @@ // Returns the associated ChromeBluetoothRemoteGattService Java object. base::android::ScopedJavaLocalRef<jobject> GetJavaObject(); + // Returns a BluetoothGattService::GattErrorCode from a given + // android.bluetooth.BluetoothGatt error code. + // |bluetooth_gatt_code| must not be 0 == GATT_SUCCESS. + static BluetoothGattService::GattErrorCode GetGattErrorCode( + int bluetooth_gatt_code); + + // Returns an android.bluetooth.BluetoothGatt error code for a given + // BluetoothGattService::GattErrorCode value. + static int GetAndroidErrorCode(BluetoothGattService::GattErrorCode); + // device::BluetoothGattService overrides. std::string GetIdentifier() const override; device::BluetoothUUID GetUUID() const override; @@ -74,7 +84,8 @@ jobject caller, const jstring& instanceId, jobject /* BluetoothGattCharacteristicWrapper */ - bluetooth_gatt_characteristic_wrapper); + bluetooth_gatt_characteristic_wrapper, + jobject /* ChromeBluetoothDevice */ chrome_bluetooth_device); private: BluetoothRemoteGattServiceAndroid(BluetoothAdapterAndroid* adapter,
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_chromeos.cc b/device/bluetooth/bluetooth_remote_gatt_service_chromeos.cc index e8176bd..8a57fa2 100644 --- a/device/bluetooth/bluetooth_remote_gatt_service_chromeos.cc +++ b/device/bluetooth/bluetooth_remote_gatt_service_chromeos.cc
@@ -6,12 +6,12 @@ #include "base/logging.h" #include "base/strings/stringprintf.h" -#include "chromeos/dbus/bluetooth_gatt_service_client.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "device/bluetooth/bluetooth_adapter_chromeos.h" #include "device/bluetooth/bluetooth_device_chromeos.h" #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h" #include "device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.h" +#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" namespace chromeos { @@ -41,13 +41,15 @@ << object_path.value() << ", UUID: " << GetUUID().canonical_value(); DCHECK(adapter_); - DBusThreadManager::Get()->GetBluetoothGattServiceClient()->AddObserver(this); - DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->AddObserver( + bluez::BluezDBusManager::Get()->GetBluetoothGattServiceClient()->AddObserver( this); + bluez::BluezDBusManager::Get() + ->GetBluetoothGattCharacteristicClient() + ->AddObserver(this); // Add all known GATT characteristics. const std::vector<dbus::ObjectPath>& gatt_chars = - DBusThreadManager::Get() + bluez::BluezDBusManager::Get() ->GetBluetoothGattCharacteristicClient() ->GetCharacteristics(); for (std::vector<dbus::ObjectPath>::const_iterator iter = gatt_chars.begin(); @@ -56,9 +58,10 @@ } BluetoothRemoteGattServiceChromeOS::~BluetoothRemoteGattServiceChromeOS() { - DBusThreadManager::Get()->GetBluetoothGattServiceClient()->RemoveObserver( - this); - DBusThreadManager::Get() + bluez::BluezDBusManager::Get() + ->GetBluetoothGattServiceClient() + ->RemoveObserver(this); + bluez::BluezDBusManager::Get() ->GetBluetoothGattCharacteristicClient() ->RemoveObserver(this); @@ -81,9 +84,10 @@ } device::BluetoothUUID BluetoothRemoteGattServiceChromeOS::GetUUID() const { - BluetoothGattServiceClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetProperties( - object_path_); + bluez::BluetoothGattServiceClient::Properties* properties = + bluez::BluezDBusManager::Get() + ->GetBluetoothGattServiceClient() + ->GetProperties(object_path_); DCHECK(properties); return device::BluetoothUUID(properties->uuid.value()); } @@ -93,9 +97,10 @@ } bool BluetoothRemoteGattServiceChromeOS::IsPrimary() const { - BluetoothGattServiceClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetProperties( - object_path_); + bluez::BluetoothGattServiceClient::Properties* properties = + bluez::BluezDBusManager::Get() + ->GetBluetoothGattServiceClient() + ->GetProperties(object_path_); DCHECK(properties); return properties->primary.value(); } @@ -229,9 +234,10 @@ VLOG(1) << "Service property changed: \"" << property_name << "\", " << object_path.value(); - BluetoothGattServiceClient::Properties* properties = - DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetProperties( - object_path); + bluez::BluetoothGattServiceClient::Properties* properties = + bluez::BluezDBusManager::Get() + ->GetBluetoothGattServiceClient() + ->GetProperties(object_path); DCHECK(properties); if (property_name != properties->characteristics.name()) { @@ -257,8 +263,8 @@ return; } - BluetoothGattCharacteristicClient::Properties* properties = - DBusThreadManager::Get() + bluez::BluetoothGattCharacteristicClient::Properties* properties = + bluez::BluezDBusManager::Get() ->GetBluetoothGattCharacteristicClient() ->GetProperties(object_path); DCHECK(properties); @@ -315,8 +321,8 @@ // "Characteristic Extended Properties" descriptor. In this case, kick off // a service changed observer event to let observers refresh the // characteristics. - BluetoothGattCharacteristicClient::Properties* properties = - DBusThreadManager::Get() + bluez::BluetoothGattCharacteristicClient::Properties* properties = + bluez::BluezDBusManager::Get() ->GetBluetoothGattCharacteristicClient() ->GetProperties(object_path);
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_chromeos.h b/device/bluetooth/bluetooth_remote_gatt_service_chromeos.h index 9aa8fdd..bc35cb7 100644 --- a/device/bluetooth/bluetooth_remote_gatt_service_chromeos.h +++ b/device/bluetooth/bluetooth_remote_gatt_service_chromeos.h
@@ -12,11 +12,11 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" -#include "chromeos/dbus/bluetooth_gatt_characteristic_client.h" -#include "chromeos/dbus/bluetooth_gatt_service_client.h" #include "dbus/object_path.h" #include "device/bluetooth/bluetooth_gatt_service.h" #include "device/bluetooth/bluetooth_uuid.h" +#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h" +#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h" namespace device { @@ -36,8 +36,8 @@ // for remote GATT services on the Chrome OS platform. class BluetoothRemoteGattServiceChromeOS : public device::BluetoothGattService, - public BluetoothGattServiceClient::Observer, - public BluetoothGattCharacteristicClient::Observer { + public bluez::BluetoothGattServiceClient::Observer, + public bluez::BluetoothGattCharacteristicClient::Observer { public: // device::BluetoothGattService overrides. std::string GetIdentifier() const override; @@ -104,11 +104,11 @@ const dbus::ObjectPath& object_path); ~BluetoothRemoteGattServiceChromeOS() override; - // BluetoothGattServiceClient::Observer override. + // bluez::BluetoothGattServiceClient::Observer override. void GattServicePropertyChanged(const dbus::ObjectPath& object_path, const std::string& property_name) override; - // BluetoothGattCharacteristicClient::Observer override. + // bluez::BluetoothGattCharacteristicClient::Observer override. void GattCharacteristicAdded(const dbus::ObjectPath& object_path) override; void GattCharacteristicRemoved(const dbus::ObjectPath& object_path) override; void GattCharacteristicPropertyChanged(
diff --git a/device/bluetooth/bluetooth_socket_chromeos.cc b/device/bluetooth/bluetooth_socket_chromeos.cc index da15484..b3e357d0 100644 --- a/device/bluetooth/bluetooth_socket_chromeos.cc +++ b/device/bluetooth/bluetooth_socket_chromeos.cc
@@ -20,10 +20,6 @@ #include "base/task_runner_util.h" #include "base/threading/thread_restrictions.h" #include "base/threading/worker_pool.h" -#include "chromeos/dbus/bluetooth_device_client.h" -#include "chromeos/dbus/bluetooth_profile_manager_client.h" -#include "chromeos/dbus/bluetooth_profile_service_provider.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "dbus/bus.h" #include "dbus/file_descriptor.h" #include "dbus/object_path.h" @@ -35,6 +31,10 @@ #include "device/bluetooth/bluetooth_socket.h" #include "device/bluetooth/bluetooth_socket_net.h" #include "device/bluetooth/bluetooth_socket_thread.h" +#include "device/bluetooth/dbus/bluetooth_device_client.h" +#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h" +#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -107,7 +107,7 @@ device_address_ = device->GetAddress(); device_path_ = device->object_path(); uuid_ = uuid; - options_.reset(new BluetoothProfileManagerClient::Options()); + options_.reset(new bluez::BluetoothProfileManagerClient::Options()); if (security_level == SECURITY_LEVEL_LOW) options_->require_authentication.reset(new bool(false)); @@ -135,7 +135,7 @@ adapter_->AddObserver(this); uuid_ = uuid; - options_.reset(new BluetoothProfileManagerClient::Options()); + options_.reset(new bluez::BluetoothProfileManagerClient::Options()); if (service_options.name) options_->name.reset(new std::string(*service_options.name)); @@ -165,7 +165,7 @@ // In the case below, where an asynchronous task gets posted on the socket // thread in BluetoothSocketNet::Close, a reference will be held to this // socket by the callback. This may cause the BluetoothAdapter to outlive - // DBusThreadManager during shutdown if that callback executes too late. + // BluezDBusManager during shutdown if that callback executes too late. if (adapter_.get()) { adapter_->RemoveObserver(this); adapter_ = nullptr; @@ -264,7 +264,7 @@ VLOG(1) << uuid_.canonical_value() << ": Got profile, connecting to " << device_path_.value(); - DBusThreadManager::Get()->GetBluetoothDeviceClient()->ConnectProfile( + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->ConnectProfile( device_path_, uuid_.canonical_value(), base::Bind(&BluetoothSocketChromeOS::OnConnectProfile, this, success_callback), @@ -355,7 +355,7 @@ void BluetoothSocketChromeOS::NewConnection( const dbus::ObjectPath& device_path, scoped_ptr<dbus::FileDescriptor> fd, - const BluetoothProfileServiceProvider::Delegate::Options& options, + const bluez::BluetoothProfileServiceProvider::Delegate::Options& options, const ConfirmationCallback& callback) { DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); @@ -460,7 +460,7 @@ void BluetoothSocketChromeOS::DoNewConnection( const dbus::ObjectPath& device_path, scoped_ptr<dbus::FileDescriptor> fd, - const BluetoothProfileServiceProvider::Delegate::Options& options, + const bluez::BluetoothProfileServiceProvider::Delegate::Options& options, const ConfirmationCallback& callback) { DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); base::ThreadRestrictions::AssertIOAllowed();
diff --git a/device/bluetooth/bluetooth_socket_chromeos.h b/device/bluetooth/bluetooth_socket_chromeos.h index 98d4d02..a1c76ee2 100644 --- a/device/bluetooth/bluetooth_socket_chromeos.h +++ b/device/bluetooth/bluetooth_socket_chromeos.h
@@ -10,14 +10,14 @@ #include "base/memory/linked_ptr.h" #include "base/memory/scoped_ptr.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/bluetooth_profile_manager_client.h" -#include "chromeos/dbus/bluetooth_profile_service_provider.h" #include "dbus/object_path.h" #include "device/bluetooth/bluetooth_adapter.h" +#include "device/bluetooth/bluetooth_export.h" #include "device/bluetooth/bluetooth_socket.h" #include "device/bluetooth/bluetooth_socket_net.h" #include "device/bluetooth/bluetooth_uuid.h" +#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h" +#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h" namespace dbus { class FileDescriptor; @@ -33,10 +33,10 @@ // Chrome OS platform. // // This class is not thread-safe, but is only called from the UI thread. -class CHROMEOS_EXPORT BluetoothSocketChromeOS +class DEVICE_BLUETOOTH_EXPORT BluetoothSocketChromeOS : public device::BluetoothSocketNet, public device::BluetoothAdapter::Observer, - public BluetoothProfileServiceProvider::Delegate { + public bluez::BluetoothProfileServiceProvider::Delegate { public: enum SecurityLevel { SECURITY_LEVEL_LOW, @@ -112,12 +112,12 @@ void OnInternalRegisterProfile(BluetoothAdapterProfileChromeOS* profile); void OnInternalRegisterProfileError(const std::string& error_message); - // BluetoothProfileServiceProvider::Delegate: + // bluez::BluetoothProfileServiceProvider::Delegate: void Released() override; void NewConnection( const dbus::ObjectPath& device_path, scoped_ptr<dbus::FileDescriptor> fd, - const BluetoothProfileServiceProvider::Delegate::Options& options, + const bluez::BluetoothProfileServiceProvider::Delegate::Options& options, const ConfirmationCallback& callback) override; void RequestDisconnection(const dbus::ObjectPath& device_path, const ConfirmationCallback& callback) override; @@ -131,7 +131,7 @@ void DoNewConnection( const dbus::ObjectPath& device_path, scoped_ptr<dbus::FileDescriptor> fd, - const BluetoothProfileServiceProvider::Delegate::Options& options, + const bluez::BluetoothProfileServiceProvider::Delegate::Options& options, const ConfirmationCallback& callback); // Method run on the UI thread after a new connection has been accepted and @@ -166,7 +166,7 @@ device::BluetoothUUID uuid_; // Copy of the profile options used for registering the profile. - scoped_ptr<BluetoothProfileManagerClient::Options> options_; + scoped_ptr<bluez::BluetoothProfileManagerClient::Options> options_; // The profile registered with the adapter for this socket. BluetoothAdapterProfileChromeOS* profile_; @@ -188,7 +188,7 @@ dbus::ObjectPath device_path; scoped_ptr<dbus::FileDescriptor> fd; - BluetoothProfileServiceProvider::Delegate::Options options; + bluez::BluetoothProfileServiceProvider::Delegate::Options options; ConfirmationCallback callback; bool accepting; bool cancelled;
diff --git a/device/bluetooth/bluetooth_socket_chromeos_unittest.cc b/device/bluetooth/bluetooth_socket_chromeos_unittest.cc index 477f3a7c..b306008b 100644 --- a/device/bluetooth/bluetooth_socket_chromeos_unittest.cc +++ b/device/bluetooth/bluetooth_socket_chromeos_unittest.cc
@@ -5,14 +5,6 @@ #include "base/bind.h" #include "base/memory/ref_counted.h" #include "base/message_loop/message_loop.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_bluetooth_adapter_client.h" -#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" -#include "chromeos/dbus/fake_bluetooth_device_client.h" -#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h" -#include "chromeos/dbus/fake_bluetooth_input_client.h" -#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h" -#include "chromeos/dbus/fake_bluetooth_profile_service_provider.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_adapter_chromeos.h" #include "device/bluetooth/bluetooth_adapter_factory.h" @@ -22,6 +14,14 @@ #include "device/bluetooth/bluetooth_socket_chromeos.h" #include "device/bluetooth/bluetooth_socket_thread.h" #include "device/bluetooth/bluetooth_uuid.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_device_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_input_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "testing/gtest/include/gtest/gtest.h" @@ -51,24 +51,27 @@ last_reason_(BluetoothSocket::kSystemError) {} void SetUp() override { - scoped_ptr<DBusThreadManagerSetter> dbus_setter = - DBusThreadManager::GetSetterForTesting(); + scoped_ptr<bluez::BluezDBusManagerSetter> dbus_setter = + bluez::BluezDBusManager::GetSetterForTesting(); dbus_setter->SetBluetoothAdapterClient( - scoped_ptr<BluetoothAdapterClient>(new FakeBluetoothAdapterClient)); + scoped_ptr<bluez::BluetoothAdapterClient>( + new bluez::FakeBluetoothAdapterClient)); dbus_setter->SetBluetoothAgentManagerClient( - scoped_ptr<BluetoothAgentManagerClient>( - new FakeBluetoothAgentManagerClient)); + scoped_ptr<bluez::BluetoothAgentManagerClient>( + new bluez::FakeBluetoothAgentManagerClient)); dbus_setter->SetBluetoothDeviceClient( - scoped_ptr<BluetoothDeviceClient>(new FakeBluetoothDeviceClient)); + scoped_ptr<bluez::BluetoothDeviceClient>( + new bluez::FakeBluetoothDeviceClient)); dbus_setter->SetBluetoothGattServiceClient( - scoped_ptr<BluetoothGattServiceClient>( - new FakeBluetoothGattServiceClient)); + scoped_ptr<bluez::BluetoothGattServiceClient>( + new bluez::FakeBluetoothGattServiceClient)); dbus_setter->SetBluetoothInputClient( - scoped_ptr<BluetoothInputClient>(new FakeBluetoothInputClient)); + scoped_ptr<bluez::BluetoothInputClient>( + new bluez::FakeBluetoothInputClient)); dbus_setter->SetBluetoothProfileManagerClient( - scoped_ptr<BluetoothProfileManagerClient>( - new FakeBluetoothProfileManagerClient)); + scoped_ptr<bluez::BluetoothProfileManagerClient>( + new bluez::FakeBluetoothProfileManagerClient)); BluetoothSocketThread::Get(); @@ -91,7 +94,7 @@ void TearDown() override { adapter_ = nullptr; BluetoothSocketThread::CleanupForTesting(); - DBusThreadManager::Shutdown(); + bluez::BluezDBusManager::Shutdown(); } void AdapterCallback(scoped_refptr<BluetoothAdapter> adapter) { @@ -182,12 +185,12 @@ }; TEST_F(BluetoothSocketChromeOSTest, Connect) { - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kPairedDeviceAddress); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); ASSERT_TRUE(device != nullptr); device->ConnectToService( - BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid), + BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), base::Bind(&BluetoothSocketChromeOSTest::ConnectToServiceSuccessCallback, base::Unretained(this)), base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback, @@ -294,7 +297,7 @@ TEST_F(BluetoothSocketChromeOSTest, Listen) { adapter_->CreateRfcommService( - BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid), + BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), BluetoothAdapter::ServiceOptions(), base::Bind(&BluetoothSocketChromeOSTest::CreateServiceSuccessCallback, base::Unretained(this)), @@ -319,15 +322,15 @@ // // This is done before the Accept() call to simulate a pending call at the // point that Accept() is called. - FakeBluetoothDeviceClient* fake_bluetooth_device_client = - static_cast<FakeBluetoothDeviceClient*>( - DBusThreadManager::Get()->GetBluetoothDeviceClient()); - BluetoothDevice* device = - adapter_->GetDevice(FakeBluetoothDeviceClient::kPairedDeviceAddress); + bluez::FakeBluetoothDeviceClient* fake_bluetooth_device_client = + static_cast<bluez::FakeBluetoothDeviceClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()); + BluetoothDevice* device = adapter_->GetDevice( + bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress); ASSERT_TRUE(device != nullptr); fake_bluetooth_device_client->ConnectProfile( static_cast<BluetoothDeviceChromeOS*>(device)->object_path(), - FakeBluetoothProfileManagerClient::kRfcommUuid, + bluez::FakeBluetoothProfileManagerClient::kRfcommUuid, base::Bind(&base::DoNothing), base::Bind(&DoNothingDBusErrorCallback)); message_loop_.RunUntilIdle(); @@ -374,7 +377,7 @@ fake_bluetooth_device_client->ConnectProfile( static_cast<BluetoothDeviceChromeOS*>(device)->object_path(), - FakeBluetoothProfileManagerClient::kRfcommUuid, + bluez::FakeBluetoothProfileManagerClient::kRfcommUuid, base::Bind(&base::DoNothing), base::Bind(&DoNothingDBusErrorCallback)); message_loop_.Run(); @@ -414,13 +417,13 @@ TEST_F(BluetoothSocketChromeOSTest, ListenBeforeAdapterStart) { // Start off with an invisible adapter, register the profile, then make // the adapter visible. - FakeBluetoothAdapterClient* fake_bluetooth_adapter_client = - static_cast<FakeBluetoothAdapterClient*>( - DBusThreadManager::Get()->GetBluetoothAdapterClient()); + bluez::FakeBluetoothAdapterClient* fake_bluetooth_adapter_client = + static_cast<bluez::FakeBluetoothAdapterClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()); fake_bluetooth_adapter_client->SetVisible(false); adapter_->CreateRfcommService( - BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid), + BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), BluetoothAdapter::ServiceOptions(), base::Bind(&BluetoothSocketChromeOSTest::CreateServiceSuccessCallback, base::Unretained(this)), @@ -439,12 +442,14 @@ error_callback_count_ = 0; // But there shouldn't be a profile registered yet. - FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = - static_cast<FakeBluetoothProfileManagerClient*>( - DBusThreadManager::Get()->GetBluetoothProfileManagerClient()); - FakeBluetoothProfileServiceProvider* profile_service_provider = + bluez::FakeBluetoothProfileManagerClient* + fake_bluetooth_profile_manager_client = + static_cast<bluez::FakeBluetoothProfileManagerClient*>( + bluez::BluezDBusManager::Get() + ->GetBluetoothProfileManagerClient()); + bluez::FakeBluetoothProfileServiceProvider* profile_service_provider = fake_bluetooth_profile_manager_client->GetProfileServiceProvider( - FakeBluetoothProfileManagerClient::kRfcommUuid); + bluez::FakeBluetoothProfileManagerClient::kRfcommUuid); EXPECT_TRUE(profile_service_provider == nullptr); // Make the adapter visible. This should register a profile. @@ -454,7 +459,7 @@ profile_service_provider = fake_bluetooth_profile_manager_client->GetProfileServiceProvider( - FakeBluetoothProfileManagerClient::kRfcommUuid); + bluez::FakeBluetoothProfileManagerClient::kRfcommUuid); EXPECT_TRUE(profile_service_provider != nullptr); // Cleanup the socket. @@ -469,12 +474,12 @@ TEST_F(BluetoothSocketChromeOSTest, ListenAcrossAdapterRestart) { // The fake adapter starts off visible by default. - FakeBluetoothAdapterClient* fake_bluetooth_adapter_client = - static_cast<FakeBluetoothAdapterClient*>( - DBusThreadManager::Get()->GetBluetoothAdapterClient()); + bluez::FakeBluetoothAdapterClient* fake_bluetooth_adapter_client = + static_cast<bluez::FakeBluetoothAdapterClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()); adapter_->CreateRfcommService( - BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid), + BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), BluetoothAdapter::ServiceOptions(), base::Bind(&BluetoothSocketChromeOSTest::CreateServiceSuccessCallback, base::Unretained(this)), @@ -493,12 +498,14 @@ error_callback_count_ = 0; // Make sure the profile was registered with the daemon. - FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = - static_cast<FakeBluetoothProfileManagerClient*>( - DBusThreadManager::Get()->GetBluetoothProfileManagerClient()); - FakeBluetoothProfileServiceProvider* profile_service_provider = + bluez::FakeBluetoothProfileManagerClient* + fake_bluetooth_profile_manager_client = + static_cast<bluez::FakeBluetoothProfileManagerClient*>( + bluez::BluezDBusManager::Get() + ->GetBluetoothProfileManagerClient()); + bluez::FakeBluetoothProfileServiceProvider* profile_service_provider = fake_bluetooth_profile_manager_client->GetProfileServiceProvider( - FakeBluetoothProfileManagerClient::kRfcommUuid); + bluez::FakeBluetoothProfileManagerClient::kRfcommUuid); EXPECT_TRUE(profile_service_provider != nullptr); // Make the adapter invisible, and fiddle with the profile fake to unregister @@ -514,7 +521,7 @@ profile_service_provider = fake_bluetooth_profile_manager_client->GetProfileServiceProvider( - FakeBluetoothProfileManagerClient::kRfcommUuid); + bluez::FakeBluetoothProfileManagerClient::kRfcommUuid); EXPECT_TRUE(profile_service_provider != nullptr); // Cleanup the socket. @@ -529,11 +536,11 @@ TEST_F(BluetoothSocketChromeOSTest, PairedConnectFails) { BluetoothDevice* device = adapter_->GetDevice( - FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress); + bluez::FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress); ASSERT_TRUE(device != nullptr); device->ConnectToService( - BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid), + BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), base::Bind(&BluetoothSocketChromeOSTest::ConnectToServiceSuccessCallback, base::Unretained(this)), base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback, @@ -545,7 +552,7 @@ EXPECT_TRUE(last_socket_.get() == nullptr); device->ConnectToService( - BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid), + BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), base::Bind(&BluetoothSocketChromeOSTest::ConnectToServiceSuccessCallback, base::Unretained(this)), base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback, @@ -559,7 +566,7 @@ TEST_F(BluetoothSocketChromeOSTest, SocketListenTwice) { adapter_->CreateRfcommService( - BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid), + BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), BluetoothAdapter::ServiceOptions(), base::Bind(&BluetoothSocketChromeOSTest::CreateServiceSuccessCallback, base::Unretained(this)), @@ -592,7 +599,7 @@ EXPECT_EQ(1U, error_callback_count_); adapter_->CreateRfcommService( - BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid), + BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid), BluetoothAdapter::ServiceOptions(), base::Bind(&BluetoothSocketChromeOSTest::CreateServiceSuccessCallback, base::Unretained(this)),
diff --git a/device/bluetooth/dbus/bluetooth_adapter_client.cc b/device/bluetooth/dbus/bluetooth_adapter_client.cc new file mode 100644 index 0000000..26081ea3 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_adapter_client.cc
@@ -0,0 +1,350 @@ +// Copyright 2013 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 "device/bluetooth/dbus/bluetooth_adapter_client.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_manager.h" +#include "dbus/object_proxy.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +BluetoothAdapterClient::DiscoveryFilter::DiscoveryFilter() {} + +BluetoothAdapterClient::DiscoveryFilter::~DiscoveryFilter() {} + +void BluetoothAdapterClient::DiscoveryFilter::CopyFrom( + const DiscoveryFilter& filter) { + if (filter.rssi.get()) + rssi.reset(new int16_t(*filter.rssi)); + else + rssi.reset(); + + if (filter.pathloss.get()) + pathloss.reset(new uint16_t(*filter.pathloss)); + else + pathloss.reset(); + + if (filter.transport.get()) + transport.reset(new std::string(*filter.transport)); + else + transport.reset(); + + if (filter.uuids.get()) + uuids.reset(new std::vector<std::string>(*filter.uuids)); + else + uuids.reset(); +} + +const char BluetoothAdapterClient::kNoResponseError[] = + "org.chromium.Error.NoResponse"; +const char BluetoothAdapterClient::kUnknownAdapterError[] = + "org.chromium.Error.UnknownAdapter"; + +BluetoothAdapterClient::Properties::Properties( + dbus::ObjectProxy* object_proxy, + const std::string& interface_name, + const PropertyChangedCallback& callback) + : dbus::PropertySet(object_proxy, interface_name, callback) { + RegisterProperty(bluetooth_adapter::kAddressProperty, &address); + RegisterProperty(bluetooth_adapter::kNameProperty, &name); + RegisterProperty(bluetooth_adapter::kAliasProperty, &alias); + RegisterProperty(bluetooth_adapter::kClassProperty, &bluetooth_class); + RegisterProperty(bluetooth_adapter::kPoweredProperty, &powered); + RegisterProperty(bluetooth_adapter::kDiscoverableProperty, &discoverable); + RegisterProperty(bluetooth_adapter::kPairableProperty, &pairable); + RegisterProperty(bluetooth_adapter::kPairableTimeoutProperty, + &pairable_timeout); + RegisterProperty(bluetooth_adapter::kDiscoverableTimeoutProperty, + &discoverable_timeout); + RegisterProperty(bluetooth_adapter::kDiscoveringProperty, &discovering); + RegisterProperty(bluetooth_adapter::kUUIDsProperty, &uuids); + RegisterProperty(bluetooth_adapter::kModaliasProperty, &modalias); +} + +BluetoothAdapterClient::Properties::~Properties() {} + +// The BluetoothAdapterClient implementation used in production. +class BluetoothAdapterClientImpl : public BluetoothAdapterClient, + public dbus::ObjectManager::Interface { + public: + BluetoothAdapterClientImpl() + : object_manager_(NULL), weak_ptr_factory_(this) {} + + ~BluetoothAdapterClientImpl() override { + object_manager_->UnregisterInterface( + bluetooth_adapter::kBluetoothAdapterInterface); + } + + // BluetoothAdapterClient override. + void AddObserver(BluetoothAdapterClient::Observer* observer) override { + DCHECK(observer); + observers_.AddObserver(observer); + } + + // BluetoothAdapterClient override. + void RemoveObserver(BluetoothAdapterClient::Observer* observer) override { + DCHECK(observer); + observers_.RemoveObserver(observer); + } + + // Returns the list of adapter object paths known to the system. + std::vector<dbus::ObjectPath> GetAdapters() override { + return object_manager_->GetObjectsWithInterface( + bluetooth_adapter::kBluetoothAdapterInterface); + } + + // dbus::ObjectManager::Interface override. + dbus::PropertySet* CreateProperties( + dbus::ObjectProxy* object_proxy, + const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + Properties* properties = new Properties( + object_proxy, interface_name, + base::Bind(&BluetoothAdapterClientImpl::OnPropertyChanged, + weak_ptr_factory_.GetWeakPtr(), object_path)); + return static_cast<dbus::PropertySet*>(properties); + } + + // BluetoothAdapterClient override. + Properties* GetProperties(const dbus::ObjectPath& object_path) override { + return static_cast<Properties*>(object_manager_->GetProperties( + object_path, bluetooth_adapter::kBluetoothAdapterInterface)); + } + + // BluetoothAdapterClient override. + void StartDiscovery(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call(bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kStartDiscovery); + + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownAdapterError, ""); + return; + } + + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAdapterClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothAdapterClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothAdapterClient override. + void StopDiscovery(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call(bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kStopDiscovery); + + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownAdapterError, ""); + return; + } + + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAdapterClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothAdapterClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothAdapterClient override. + void RemoveDevice(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& device_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call(bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kRemoveDevice); + + dbus::MessageWriter writer(&method_call); + writer.AppendObjectPath(device_path); + + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownAdapterError, ""); + return; + } + + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAdapterClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothAdapterClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothAdapterClient override. + void SetDiscoveryFilter(const dbus::ObjectPath& object_path, + const DiscoveryFilter& discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call(bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kSetDiscoveryFilter); + + dbus::MessageWriter writer(&method_call); + dbus::MessageWriter dict_writer(nullptr); + + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownAdapterError, ""); + return; + } + + writer.OpenArray("{sv}", &dict_writer); + + if (discovery_filter.uuids.get()) { + std::vector<std::string>* uuids = discovery_filter.uuids.get(); + dbus::MessageWriter uuids_entry_writer(nullptr); + dict_writer.OpenDictEntry(&uuids_entry_writer); + uuids_entry_writer.AppendString( + bluetooth_adapter::kDiscoveryFilterParameterUUIDs); + + dbus::MessageWriter uuids_array_variant(nullptr); + uuids_entry_writer.OpenVariant("as", &uuids_array_variant); + dbus::MessageWriter uuids_array(nullptr); + uuids_array_variant.OpenArray("s", &uuids_array); + + for (auto& it : *uuids) + uuids_array.AppendString(it); + + uuids_array_variant.CloseContainer(&uuids_array); + uuids_entry_writer.CloseContainer(&uuids_array_variant); + dict_writer.CloseContainer(&uuids_entry_writer); + } + + if (discovery_filter.rssi.get()) { + dbus::MessageWriter rssi_entry_writer(nullptr); + dict_writer.OpenDictEntry(&rssi_entry_writer); + rssi_entry_writer.AppendString( + bluetooth_adapter::kDiscoveryFilterParameterRSSI); + rssi_entry_writer.AppendVariantOfInt16(*discovery_filter.rssi.get()); + dict_writer.CloseContainer(&rssi_entry_writer); + } + + if (discovery_filter.pathloss.get()) { + dbus::MessageWriter pathloss_entry_writer(nullptr); + dict_writer.OpenDictEntry(&pathloss_entry_writer); + pathloss_entry_writer.AppendString( + bluetooth_adapter::kDiscoveryFilterParameterPathloss); + pathloss_entry_writer.AppendVariantOfUint16( + *discovery_filter.pathloss.get()); + dict_writer.CloseContainer(&pathloss_entry_writer); + } + + if (discovery_filter.transport.get()) { + dbus::MessageWriter transport_entry_writer(nullptr); + dict_writer.OpenDictEntry(&transport_entry_writer); + transport_entry_writer.AppendString( + bluetooth_adapter::kDiscoveryFilterParameterTransport); + transport_entry_writer.AppendVariantOfString( + *discovery_filter.transport.get()); + dict_writer.CloseContainer(&transport_entry_writer); + } + + writer.CloseContainer(&dict_writer); + + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAdapterClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothAdapterClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + protected: + void Init(dbus::Bus* bus) override { + object_manager_ = bus->GetObjectManager( + bluetooth_object_manager::kBluetoothObjectManagerServiceName, + dbus::ObjectPath( + bluetooth_object_manager::kBluetoothObjectManagerServicePath)); + object_manager_->RegisterInterface( + bluetooth_adapter::kBluetoothAdapterInterface, this); + } + + private: + // Called by dbus::ObjectManager when an object with the adapter interface + // is created. Informs observers. + void ObjectAdded(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, + AdapterAdded(object_path)); + } + + // Called by dbus::ObjectManager when an object with the adapter interface + // is removed. Informs observers. + void ObjectRemoved(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, + AdapterRemoved(object_path)); + } + + // Called by dbus::PropertySet when a property value is changed, + // either by result of a signal or response to a GetAll() or Get() + // call. Informs observers. + void OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) { + FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, + AdapterPropertyChanged(object_path, property_name)); + } + + // Called when a response for successful method call is received. + void OnSuccess(const base::Closure& callback, dbus::Response* response) { + DCHECK(response); + callback.Run(); + } + + // Called when a response for a failed method call is received. + void OnError(const ErrorCallback& error_callback, + dbus::ErrorResponse* response) { + // Error response has optional error message argument. + std::string error_name; + std::string error_message; + if (response) { + dbus::MessageReader reader(response); + error_name = response->GetErrorName(); + reader.PopString(&error_message); + } else { + error_name = kNoResponseError; + error_message = ""; + } + error_callback.Run(error_name, error_message); + } + + dbus::ObjectManager* object_manager_; + + // List of observers interested in event notifications from us. + base::ObserverList<BluetoothAdapterClient::Observer> observers_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothAdapterClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterClientImpl); +}; + +BluetoothAdapterClient::BluetoothAdapterClient() {} + +BluetoothAdapterClient::~BluetoothAdapterClient() {} + +BluetoothAdapterClient* BluetoothAdapterClient::Create() { + return new BluetoothAdapterClientImpl; +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_adapter_client.h b/device/bluetooth/dbus/bluetooth_adapter_client.h new file mode 100644 index 0000000..4af6658 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_adapter_client.h
@@ -0,0 +1,186 @@ +// Copyright 2013 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 DEVICE_BLUETOOTH_DBUS_BLUETOOTH_ADAPTER_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_ADAPTER_CLIENT_H_ + +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/observer_list.h" +#include "base/values.h" +#include "dbus/object_path.h" +#include "dbus/property.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluez_dbus_client.h" + +namespace bluez { + +// BluetoothAdapterClient is used to communicate with objects representing +// local Bluetooth Adapters. +class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterClient : public BluezDBusClient { + public: + // A DiscoveryFilter represents a filter passed to the SetDiscoveryFilter + // method. + struct DiscoveryFilter { + DiscoveryFilter(); + ~DiscoveryFilter(); + + // Copy content of |filter| into this filter + void CopyFrom(const DiscoveryFilter& filter); + + scoped_ptr<std::vector<std::string>> uuids; + scoped_ptr<int16_t> rssi; + scoped_ptr<uint16_t> pathloss; + scoped_ptr<std::string> transport; + + private: + DISALLOW_COPY_AND_ASSIGN(DiscoveryFilter); + }; + + // Structure of properties associated with bluetooth adapters. + struct Properties : public dbus::PropertySet { + // The Bluetooth device address of the adapter. Read-only. + dbus::Property<std::string> address; + + // The Bluetooth system name, generally derived from the hostname. + dbus::Property<std::string> name; + + // The Bluetooth friendly name of the adapter, unlike remote devices, + // this property can be changed to change the presentation for when + // the adapter is discoverable. + dbus::Property<std::string> alias; + + // The Bluetooth class of the adapter device. Read-only. + dbus::Property<uint32> bluetooth_class; + + // Whether the adapter radio is powered. + dbus::Property<bool> powered; + + // Whether the adapter is discoverable by other Bluetooth devices. + // |discovering_timeout| is used to automatically disable after a time + // period. + dbus::Property<bool> discoverable; + + // Whether the adapter accepts incoming pairing requests from other + // Bluetooth devices. |pairable_timeout| is used to automatically disable + // after a time period. + dbus::Property<bool> pairable; + + // The timeout in seconds to cease accepting incoming pairing requests + // after |pairable| is set to true. Zero means adapter remains pairable + // forever. + dbus::Property<uint32> pairable_timeout; + + // The timeout in seconds to cease the adapter being discoverable by + // other Bluetooth devices after |discoverable| is set to true. Zero + // means adapter remains discoverable forever. + dbus::Property<uint32> discoverable_timeout; + + // Indicates that the adapter is discovering other Bluetooth Devices. + // Read-only. Use StartDiscovery() to begin discovery. + dbus::Property<bool> discovering; + + // List of 128-bit UUIDs that represent the available local services. + // Read-only. + dbus::Property<std::vector<std::string>> uuids; + + // Local Device ID information in Linux kernel modalias format. Read-only. + dbus::Property<std::string> modalias; + + Properties(dbus::ObjectProxy* object_proxy, + const std::string& interface_name, + const PropertyChangedCallback& callback); + ~Properties() override; + }; + + // Interface for observing changes from a local bluetooth adapter. + class Observer { + public: + virtual ~Observer() {} + + // Called when the adapter with object path |object_path| is added to the + // system. + virtual void AdapterAdded(const dbus::ObjectPath& object_path) {} + + // Called when the adapter with object path |object_path| is removed from + // the system. + virtual void AdapterRemoved(const dbus::ObjectPath& object_path) {} + + // Called when the adapter with object path |object_path| has a + // change in value of the property named |property_name|. + virtual void AdapterPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) {} + }; + + ~BluetoothAdapterClient() override; + + // Adds and removes observers for events on all local bluetooth + // adapters. Check the |object_path| parameter of observer methods to + // determine which adapter is issuing the event. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Returns the list of adapter object paths known to the system. + virtual std::vector<dbus::ObjectPath> GetAdapters() = 0; + + // Obtain the properties for the adapter with object path |object_path|, + // any values should be copied if needed. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; + + // The ErrorCallback is used by adapter methods to indicate failure. + // It receives two arguments: the name of the error in |error_name| and + // an optional message in |error_message|. + typedef base::Callback<void(const std::string& error_name, + const std::string& error_message)> ErrorCallback; + + // Starts a device discovery on the adapter with object path |object_path|. + virtual void StartDiscovery(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Cancels any previous device discovery on the adapter with object path + // |object_path|. + virtual void StopDiscovery(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Removes from the adapter with object path |object_path| the remote + // device with object path |object_path| from the list of known devices + // and discards any pairing information. + virtual void RemoveDevice(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& device_path, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Sets the device discovery filter on the adapter with object path + // |object_path|. When this method is called with no filter parameter, filter + // is removed. + // SetDiscoveryFilter can be called before StartDiscovery. It is useful when + // client will create first discovery session, to ensure that proper scan + // will be started right after call to StartDiscovery. + virtual void SetDiscoveryFilter(const dbus::ObjectPath& object_path, + const DiscoveryFilter& discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Creates the instance. + static BluetoothAdapterClient* Create(); + + // Constants used to indicate exceptional error conditions. + static const char kNoResponseError[]; + static const char kUnknownAdapterError[]; + + protected: + BluetoothAdapterClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_ADAPTER_CLIENT_H_
diff --git a/device/bluetooth/dbus/bluetooth_agent_manager_client.cc b/device/bluetooth/dbus/bluetooth_agent_manager_client.cc new file mode 100644 index 0000000..6caee9b --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_agent_manager_client.cc
@@ -0,0 +1,137 @@ +// Copyright 2013 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 "device/bluetooth/dbus/bluetooth_agent_manager_client.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_proxy.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +const char BluetoothAgentManagerClient::kNoResponseError[] = + "org.chromium.Error.NoResponse"; + +// The BluetoothAgentManagerClient implementation used in production. +class BluetoothAgentManagerClientImpl : public BluetoothAgentManagerClient { + public: + BluetoothAgentManagerClientImpl() : weak_ptr_factory_(this) {} + + ~BluetoothAgentManagerClientImpl() override {} + + // BluetoothAgentManagerClient override. + void RegisterAgent(const dbus::ObjectPath& agent_path, + const std::string& capability, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call( + bluetooth_agent_manager::kBluetoothAgentManagerInterface, + bluetooth_agent_manager::kRegisterAgent); + + dbus::MessageWriter writer(&method_call); + writer.AppendObjectPath(agent_path); + writer.AppendString(capability); + + object_proxy_->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAgentManagerClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothAgentManagerClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothAgentManagerClient override. + void UnregisterAgent(const dbus::ObjectPath& agent_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call( + bluetooth_agent_manager::kBluetoothAgentManagerInterface, + bluetooth_agent_manager::kUnregisterAgent); + + dbus::MessageWriter writer(&method_call); + writer.AppendObjectPath(agent_path); + + object_proxy_->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAgentManagerClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothAgentManagerClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothAgentManagerClient override. + void RequestDefaultAgent(const dbus::ObjectPath& agent_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call( + bluetooth_agent_manager::kBluetoothAgentManagerInterface, + bluetooth_agent_manager::kRequestDefaultAgent); + + dbus::MessageWriter writer(&method_call); + writer.AppendObjectPath(agent_path); + + object_proxy_->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAgentManagerClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothAgentManagerClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + protected: + void Init(dbus::Bus* bus) override { + DCHECK(bus); + object_proxy_ = bus->GetObjectProxy( + bluetooth_agent_manager::kBluetoothAgentManagerServiceName, + dbus::ObjectPath( + bluetooth_agent_manager::kBluetoothAgentManagerServicePath)); + } + + private: + // Called when a response for successful method call is received. + void OnSuccess(const base::Closure& callback, dbus::Response* response) { + DCHECK(response); + callback.Run(); + } + + // Called when a response for a failed method call is received. + void OnError(const ErrorCallback& error_callback, + dbus::ErrorResponse* response) { + // Error response has optional error message argument. + std::string error_name; + std::string error_message; + if (response) { + dbus::MessageReader reader(response); + error_name = response->GetErrorName(); + reader.PopString(&error_message); + } else { + error_name = kNoResponseError; + error_message = ""; + } + error_callback.Run(error_name, error_message); + } + + dbus::ObjectProxy* object_proxy_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothAgentManagerClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothAgentManagerClientImpl); +}; + +BluetoothAgentManagerClient::BluetoothAgentManagerClient() {} + +BluetoothAgentManagerClient::~BluetoothAgentManagerClient() {} + +BluetoothAgentManagerClient* BluetoothAgentManagerClient::Create() { + return new BluetoothAgentManagerClientImpl(); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_agent_manager_client.h b/device/bluetooth/dbus/bluetooth_agent_manager_client.h new file mode 100644 index 0000000..47402dd --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_agent_manager_client.h
@@ -0,0 +1,70 @@ +// Copyright 2013 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 DEVICE_BLUETOOTH_DBUS_BLUETOOTH_AGENT_MANAGER_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_AGENT_MANAGER_CLIENT_H_ + +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/values.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluez_dbus_client.h" + +namespace bluez { + +// BluetoothAgentManagerClient is used to communicate with the agent manager +// object of the Bluetooth daemon. +class DEVICE_BLUETOOTH_EXPORT BluetoothAgentManagerClient + : public BluezDBusClient { + public: + ~BluetoothAgentManagerClient() override; + + // The ErrorCallback is used by agent manager methods to indicate failure. + // It receives two arguments: the name of the error in |error_name| and + // an optional message in |error_message|. + typedef base::Callback<void(const std::string& error_name, + const std::string& error_message)> ErrorCallback; + + // Registers an agent within the local process at the D-bus object path + // |agent_path| with the remote agent manager. The agent is used for pairing + // and for authorization of incoming connection requests. |capability| + // specifies the input and display capabilities of the agent and should be + // one of the constants declared in the bluetooth_agent_manager:: namespace. + virtual void RegisterAgent(const dbus::ObjectPath& agent_path, + const std::string& capability, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Unregisters the agent with the D-Bus object path |agent_path| from the + // remote agent manager. + virtual void UnregisterAgent(const dbus::ObjectPath& agent_path, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Requests that the agent with the D-Bus object path |agent_path| be made + // the default. + virtual void RequestDefaultAgent(const dbus::ObjectPath& agent_path, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Creates the instance. + static BluetoothAgentManagerClient* Create(); + + // Constants used to indicate exceptional error conditions. + static const char kNoResponseError[]; + + protected: + BluetoothAgentManagerClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothAgentManagerClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_AGENT_MANAGER_CLIENT_H_
diff --git a/device/bluetooth/dbus/bluetooth_agent_service_provider.cc b/device/bluetooth/dbus/bluetooth_agent_service_provider.cc new file mode 100644 index 0000000..7392f2b --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_agent_service_provider.cc
@@ -0,0 +1,444 @@ +// Copyright 2013 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 "device/bluetooth/dbus/bluetooth_agent_service_provider.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/threading/platform_thread.h" +#include "dbus/exported_object.h" +#include "dbus/message.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_agent_service_provider.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +// The BluetoothAgentServiceProvider implementation used in production. +class BluetoothAgentServiceProviderImpl : public BluetoothAgentServiceProvider { + public: + BluetoothAgentServiceProviderImpl(dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate) + : origin_thread_id_(base::PlatformThread::CurrentId()), + bus_(bus), + delegate_(delegate), + object_path_(object_path), + weak_ptr_factory_(this) { + VLOG(1) << "Creating Bluetooth Agent: " << object_path_.value(); + + exported_object_ = bus_->GetExportedObject(object_path_); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, bluetooth_agent::kRelease, + base::Bind(&BluetoothAgentServiceProviderImpl::Release, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, + bluetooth_agent::kRequestPinCode, + base::Bind(&BluetoothAgentServiceProviderImpl::RequestPinCode, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, + bluetooth_agent::kDisplayPinCode, + base::Bind(&BluetoothAgentServiceProviderImpl::DisplayPinCode, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, + bluetooth_agent::kRequestPasskey, + base::Bind(&BluetoothAgentServiceProviderImpl::RequestPasskey, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, + bluetooth_agent::kDisplayPasskey, + base::Bind(&BluetoothAgentServiceProviderImpl::DisplayPasskey, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, + bluetooth_agent::kRequestConfirmation, + base::Bind(&BluetoothAgentServiceProviderImpl::RequestConfirmation, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, + bluetooth_agent::kRequestAuthorization, + base::Bind(&BluetoothAgentServiceProviderImpl::RequestAuthorization, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, + bluetooth_agent::kAuthorizeService, + base::Bind(&BluetoothAgentServiceProviderImpl::AuthorizeService, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, bluetooth_agent::kCancel, + base::Bind(&BluetoothAgentServiceProviderImpl::Cancel, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAgentServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + } + + ~BluetoothAgentServiceProviderImpl() override { + VLOG(1) << "Cleaning up Bluetooth Agent: " << object_path_.value(); + + // Unregister the object path so we can reuse with a new agent. + bus_->UnregisterExportedObject(object_path_); + } + + private: + // Returns true if the current thread is on the origin thread. + bool OnOriginThread() { + return base::PlatformThread::CurrentId() == origin_thread_id_; + } + + // Called by dbus:: when the agent is unregistered from the Bluetooth + // daemon, generally at the end of a pairing request. + void Release(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + delegate_->Released(); + + response_sender.Run(dbus::Response::FromMethodCall(method_call)); + } + + // Called by dbus:: when the Bluetooth daemon requires a PIN Code for + // device authentication. + void RequestPinCode(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + dbus::ObjectPath device_path; + if (!reader.PopObjectPath(&device_path)) { + LOG(WARNING) << "RequestPinCode called with incorrect paramters: " + << method_call->ToString(); + return; + } + + Delegate::PinCodeCallback callback = base::Bind( + &BluetoothAgentServiceProviderImpl::OnPinCode, + weak_ptr_factory_.GetWeakPtr(), method_call, response_sender); + + delegate_->RequestPinCode(device_path, callback); + } + + // Called by dbus:: when the Bluetooth daemon requires that the user + // enter a PIN Code into the remote device so that it may be + // authenticated. + void DisplayPinCode(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + dbus::ObjectPath device_path; + std::string pincode; + if (!reader.PopObjectPath(&device_path) || !reader.PopString(&pincode)) { + LOG(WARNING) << "DisplayPinCode called with incorrect paramters: " + << method_call->ToString(); + return; + } + + delegate_->DisplayPinCode(device_path, pincode); + + response_sender.Run(dbus::Response::FromMethodCall(method_call)); + } + + // Called by dbus:: when the Bluetooth daemon requires a Passkey for + // device authentication. + void RequestPasskey(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + dbus::ObjectPath device_path; + if (!reader.PopObjectPath(&device_path)) { + LOG(WARNING) << "RequestPasskey called with incorrect paramters: " + << method_call->ToString(); + return; + } + + Delegate::PasskeyCallback callback = base::Bind( + &BluetoothAgentServiceProviderImpl::OnPasskey, + weak_ptr_factory_.GetWeakPtr(), method_call, response_sender); + + delegate_->RequestPasskey(device_path, callback); + } + + // Called by dbus:: when the Bluetooth daemon requires that the user + // enter a Passkey into the remote device so that it may be + // authenticated. + void DisplayPasskey(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + dbus::ObjectPath device_path; + uint32 passkey; + uint16 entered; + if (!reader.PopObjectPath(&device_path) || !reader.PopUint32(&passkey) || + !reader.PopUint16(&entered)) { + LOG(WARNING) << "DisplayPasskey called with incorrect paramters: " + << method_call->ToString(); + return; + } + + delegate_->DisplayPasskey(device_path, passkey, entered); + + response_sender.Run(dbus::Response::FromMethodCall(method_call)); + } + + // Called by dbus:: when the Bluetooth daemon requires that the user + // confirm that a Passkey is displayed on the screen of the remote + // device so that it may be authenticated. + void RequestConfirmation( + dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + dbus::ObjectPath device_path; + uint32 passkey; + if (!reader.PopObjectPath(&device_path) || !reader.PopUint32(&passkey)) { + LOG(WARNING) << "RequestConfirmation called with incorrect paramters: " + << method_call->ToString(); + return; + } + + Delegate::ConfirmationCallback callback = base::Bind( + &BluetoothAgentServiceProviderImpl::OnConfirmation, + weak_ptr_factory_.GetWeakPtr(), method_call, response_sender); + + delegate_->RequestConfirmation(device_path, passkey, callback); + } + + // Called by dbus:: when the Bluetooth daemon requires that the user + // confirm an incoming just-works pairing. + void RequestAuthorization( + dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + dbus::ObjectPath device_path; + if (!reader.PopObjectPath(&device_path)) { + LOG(WARNING) << "RequestAuthorization called with incorrect paramters: " + << method_call->ToString(); + return; + } + + Delegate::ConfirmationCallback callback = base::Bind( + &BluetoothAgentServiceProviderImpl::OnConfirmation, + weak_ptr_factory_.GetWeakPtr(), method_call, response_sender); + + delegate_->RequestAuthorization(device_path, callback); + } + + // Called by dbus:: when the Bluetooth daemon requires that the user + // confirm that that a remote device is authorized to connect to a service + // UUID. + void AuthorizeService(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + dbus::ObjectPath device_path; + std::string uuid; + if (!reader.PopObjectPath(&device_path) || !reader.PopString(&uuid)) { + LOG(WARNING) << "AuthorizeService called with incorrect paramters: " + << method_call->ToString(); + return; + } + + Delegate::ConfirmationCallback callback = base::Bind( + &BluetoothAgentServiceProviderImpl::OnConfirmation, + weak_ptr_factory_.GetWeakPtr(), method_call, response_sender); + + delegate_->AuthorizeService(device_path, uuid, callback); + } + + // Called by dbus:: when the request failed before a reply was returned + // from the device. + void Cancel(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + delegate_->Cancel(); + + response_sender.Run(dbus::Response::FromMethodCall(method_call)); + } + + // Called by dbus:: when a method is exported. + void OnExported(const std::string& interface_name, + const std::string& method_name, + bool success) { + LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "." + << method_name; + } + + // Called by the Delegate to response to a method requesting a PIN code. + void OnPinCode(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender, + Delegate::Status status, + const std::string& pincode) { + DCHECK(OnOriginThread()); + + switch (status) { + case Delegate::SUCCESS: { + scoped_ptr<dbus::Response> response( + dbus::Response::FromMethodCall(method_call)); + dbus::MessageWriter writer(response.get()); + writer.AppendString(pincode); + response_sender.Run(response.Pass()); + break; + } + case Delegate::REJECTED: { + response_sender.Run(dbus::ErrorResponse::FromMethodCall( + method_call, bluetooth_agent::kErrorRejected, "rejected")); + break; + } + case Delegate::CANCELLED: { + response_sender.Run(dbus::ErrorResponse::FromMethodCall( + method_call, bluetooth_agent::kErrorCanceled, "canceled")); + break; + } + default: + NOTREACHED() << "Unexpected status code from delegate: " << status; + } + } + + // Called by the Delegate to response to a method requesting a Passkey. + void OnPasskey(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender, + Delegate::Status status, + uint32 passkey) { + DCHECK(OnOriginThread()); + + switch (status) { + case Delegate::SUCCESS: { + scoped_ptr<dbus::Response> response( + dbus::Response::FromMethodCall(method_call)); + dbus::MessageWriter writer(response.get()); + writer.AppendUint32(passkey); + response_sender.Run(response.Pass()); + break; + } + case Delegate::REJECTED: { + response_sender.Run(dbus::ErrorResponse::FromMethodCall( + method_call, bluetooth_agent::kErrorRejected, "rejected")); + break; + } + case Delegate::CANCELLED: { + response_sender.Run(dbus::ErrorResponse::FromMethodCall( + method_call, bluetooth_agent::kErrorCanceled, "canceled")); + break; + } + default: + NOTREACHED() << "Unexpected status code from delegate: " << status; + } + } + + // Called by the Delegate in response to a method requiring confirmation. + void OnConfirmation(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender, + Delegate::Status status) { + DCHECK(OnOriginThread()); + + switch (status) { + case Delegate::SUCCESS: { + response_sender.Run(dbus::Response::FromMethodCall(method_call)); + break; + } + case Delegate::REJECTED: { + response_sender.Run(dbus::ErrorResponse::FromMethodCall( + method_call, bluetooth_agent::kErrorRejected, "rejected")); + break; + } + case Delegate::CANCELLED: { + response_sender.Run(dbus::ErrorResponse::FromMethodCall( + method_call, bluetooth_agent::kErrorCanceled, "canceled")); + break; + } + default: + NOTREACHED() << "Unexpected status code from delegate: " << status; + } + } + + // Origin thread (i.e. the UI thread in production). + base::PlatformThreadId origin_thread_id_; + + // D-Bus bus object is exported on, not owned by this object and must + // outlive it. + dbus::Bus* bus_; + + // All incoming method calls are passed on to the Delegate and a callback + // passed to generate the reply. |delegate_| is generally the object that + // owns this one, and must outlive it. + Delegate* delegate_; + + // D-Bus object path of object we are exporting, kept so we can unregister + // again in our destructor. + dbus::ObjectPath object_path_; + + // D-Bus object we are exporting, owned by this object. + scoped_refptr<dbus::ExportedObject> exported_object_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothAgentServiceProviderImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothAgentServiceProviderImpl); +}; + +BluetoothAgentServiceProvider::BluetoothAgentServiceProvider() {} + +BluetoothAgentServiceProvider::~BluetoothAgentServiceProvider() {} + +// static +BluetoothAgentServiceProvider* BluetoothAgentServiceProvider::Create( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate) { + if (!bluez::BluezDBusManager::Get()->IsUsingStub()) { + return new BluetoothAgentServiceProviderImpl(bus, object_path, delegate); + } else { + return new FakeBluetoothAgentServiceProvider(object_path, delegate); + } +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_agent_service_provider.h b/device/bluetooth/dbus/bluetooth_agent_service_provider.h new file mode 100644 index 0000000..e31ef8f9 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_agent_service_provider.h
@@ -0,0 +1,178 @@ +// Copyright 2013 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 DEVICE_BLUETOOTH_DBUS_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "dbus/bus.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" + +namespace bluez { + +// BluetoothAgentServiceProvider is used to provide a D-Bus object that +// the bluetooth daemon can communicate with during a remote device pairing +// request. +// +// Instantiate with a chosen D-Bus object path and delegate object, and pass +// the D-Bus object path as the |agent_path| argument to the +// chromeos::BluetoothAgentManagerClient::RegisterAgent() method. +// +// After initiating the pairing process with a device, using the +// chromeos::BluetoothDeviceClient::Pair() method, the Bluetooth daemon will +// make calls to this agent object and they will be passed on to your Delegate +// object for handling. Responses should be returned using the callbacks +// supplied to those methods. +class DEVICE_BLUETOOTH_EXPORT BluetoothAgentServiceProvider { + public: + // Interface for reacting to agent requests. + class Delegate { + public: + virtual ~Delegate() {} + + // Possible status values that may be returned to callbacks. Success + // indicates that a pincode or passkey has been obtained, or permission + // granted; rejected indicates the user rejected the request or denied + // permission; cancelled indicates the user cancelled the request + // without confirming either way. + enum Status { SUCCESS, REJECTED, CANCELLED }; + + // The PinCodeCallback is used for the RequestPinCode() method, it should + // be called with two arguments, the |status| of the request (success, + // rejected or cancelled) and the |pincode| requested. + typedef base::Callback<void(Status, const std::string&)> PinCodeCallback; + + // The PasskeyCallback is used for the RequestPasskey() method, it should + // be called with two arguments, the |status| of the request (success, + // rejected or cancelled) and the |passkey| requested, a numeric in the + // range 0-999999, + typedef base::Callback<void(Status, uint32)> PasskeyCallback; + + // The ConfirmationCallback is used for methods which request confirmation + // or authorization, it should be called with one argument, the |status| + // of the request (success, rejected or cancelled). + typedef base::Callback<void(Status)> ConfirmationCallback; + + // This method will be called when the agent is unregistered from the + // Bluetooth daemon, generally at the end of a pairing request. It may be + // used to perform cleanup tasks. This corresponds to the + // org.bluez.Agent1.Release method and is renamed to avoid a conflict + // with base::Refcounted<T>. + virtual void Released() = 0; + + // This method will be called when the Bluetooth daemon requires a + // PIN Code for authentication of the device with object path |device_path|, + // the agent should obtain the code from the user and call |callback| + // to provide it, or indicate rejection or cancellation of the request. + // + // PIN Codes are generally required for Bluetooth 2.0 and earlier devices + // for which there is no automatic pairing or special handling. + virtual void RequestPinCode(const dbus::ObjectPath& device_path, + const PinCodeCallback& callback) = 0; + + // This method will be called when the Bluetooth daemon requires that the + // user enter the PIN code |pincode| into the device with object path + // |device_path| so that it may be authenticated. The Cancel() method + // will be called to dismiss the display once pairing is complete or + // cancelled. + // + // This is used for Bluetooth 2.0 and earlier keyboard devices, the + // |pincode| will always be a six-digit numeric in the range 000000-999999 + // for compatibilty with later specifications. + virtual void DisplayPinCode(const dbus::ObjectPath& device_path, + const std::string& pincode) = 0; + + // This method will be called when the Bluetooth daemon requires a + // Passkey for authentication of the device with object path |device_path|, + // the agent should obtain the passkey from the user (a numeric in the + // range 0-999999) and call |callback| to provide it, or indicate + // rejection or cancellation of the request. + // + // Passkeys are generally required for Bluetooth 2.1 and later devices + // which cannot provide input or display on their own, and don't accept + // passkey-less pairing. + virtual void RequestPasskey(const dbus::ObjectPath& device_path, + const PasskeyCallback& callback) = 0; + + // This method will be called when the Bluetooth daemon requires that the + // user enter the Passkey |passkey| into the device with object path + // |device_path| so that it may be authenticated. The Cancel() method + // will be called to dismiss the display once pairing is complete or + // cancelled. + // + // This is used for Bluetooth 2.1 and later devices that support input + // but not display, such as keyboards. The Passkey is a numeric in the + // range 0-999999 and should be always presented zero-padded to six + // digits. + // + // As the user enters the passkey onto the device, |entered| will be + // updated to reflect the number of digits entered so far. + virtual void DisplayPasskey(const dbus::ObjectPath& device_path, + uint32 passkey, + uint16 entered) = 0; + + // This method will be called when the Bluetooth daemon requires that the + // user confirm that the Passkey |passkey| is displayed on the screen + // of the device with object path |object_path| so that it may be + // authenticated. The agent should display to the user and ask for + // confirmation, then call |callback| to provide their response (success, + // rejected or cancelled). + // + // This is used for Bluetooth 2.1 and later devices that support display, + // such as other computers or phones. The Passkey is a numeric in the + // range 0-999999 and should be always present zero-padded to six + // digits. + virtual void RequestConfirmation(const dbus::ObjectPath& device_path, + uint32 passkey, + const ConfirmationCallback& callback) = 0; + + // This method will be called when the Bluetooth daemon requires + // authorization of an incoming pairing attempt from the device with object + // path |device_path| that would have otherwised triggered the just-works + // pairing model. + // + // The agent should confirm the incoming pairing with the user and call + // |callback| to provide their response (success, rejected or cancelled). + virtual void RequestAuthorization(const dbus::ObjectPath& device_path, + const ConfirmationCallback& callback) = 0; + + // This method will be called when the Bluetooth daemon requires that the + // user confirm that the device with object path |object_path| is + // authorized to connect to the service with UUID |uuid|. The agent should + // confirm with the user and call |callback| to provide their response + // (success, rejected or cancelled). + virtual void AuthorizeService(const dbus::ObjectPath& device_path, + const std::string& uuid, + const ConfirmationCallback& callback) = 0; + + // This method will be called by the Bluetooth daemon to indicate that + // the request failed before a reply was returned from the device. + virtual void Cancel() = 0; + }; + + virtual ~BluetoothAgentServiceProvider(); + + // Creates the instance where |bus| is the D-Bus bus connection to export + // the object onto, |object_path| is the object path that it should have + // and |delegate| is the object to which all method calls will be passed + // and responses generated from. + static BluetoothAgentServiceProvider* Create( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate); + + protected: + BluetoothAgentServiceProvider(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothAgentServiceProvider); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_
diff --git a/device/bluetooth/dbus/bluetooth_dbus_client_bundle.cc b/device/bluetooth/dbus/bluetooth_dbus_client_bundle.cc new file mode 100644 index 0000000..29a4ce8 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_dbus_client_bundle.cc
@@ -0,0 +1,84 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/bluetooth_dbus_client_bundle.h" + +#include <vector> + +#include "base/command_line.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "chromeos/chromeos_switches.h" +#include "device/bluetooth/dbus/bluetooth_adapter_client.h" +#include "device/bluetooth/dbus/bluetooth_agent_manager_client.h" +#include "device/bluetooth/dbus/bluetooth_device_client.h" +#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h" +#include "device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h" +#include "device/bluetooth/dbus/bluetooth_gatt_manager_client.h" +#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h" +#include "device/bluetooth/dbus/bluetooth_input_client.h" +#include "device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h" +#include "device/bluetooth/dbus/bluetooth_media_client.h" +#include "device/bluetooth/dbus/bluetooth_media_transport_client.h" +#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_device_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_input_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_media_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_media_transport_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h" + +namespace bluez { + +BluetoothDBusClientBundle::BluetoothDBusClientBundle(bool use_stubs) + : use_stubs_(use_stubs) { + if (!use_stubs) { + bluetooth_adapter_client_.reset(BluetoothAdapterClient::Create()); + bluetooth_le_advertising_manager_client_.reset( + BluetoothLEAdvertisingManagerClient::Create()); + bluetooth_agent_manager_client_.reset( + BluetoothAgentManagerClient::Create()); + bluetooth_device_client_.reset(BluetoothDeviceClient::Create()); + bluetooth_input_client_.reset(BluetoothInputClient::Create()); + bluetooth_media_client_.reset(BluetoothMediaClient::Create()); + bluetooth_media_transport_client_.reset( + BluetoothMediaTransportClient::Create()); + bluetooth_profile_manager_client_.reset( + BluetoothProfileManagerClient::Create()); + bluetooth_gatt_characteristic_client_.reset( + BluetoothGattCharacteristicClient::Create()); + bluetooth_gatt_descriptor_client_.reset( + BluetoothGattDescriptorClient::Create()); + bluetooth_gatt_manager_client_.reset(BluetoothGattManagerClient::Create()); + bluetooth_gatt_service_client_.reset(BluetoothGattServiceClient::Create()); + } else { + bluetooth_adapter_client_.reset(new FakeBluetoothAdapterClient); + bluetooth_le_advertising_manager_client_.reset( + new FakeBluetoothLEAdvertisingManagerClient); + bluetooth_agent_manager_client_.reset(new FakeBluetoothAgentManagerClient); + bluetooth_device_client_.reset(new FakeBluetoothDeviceClient); + bluetooth_input_client_.reset(new FakeBluetoothInputClient); + bluetooth_media_client_.reset(new FakeBluetoothMediaClient); + bluetooth_media_transport_client_.reset( + new FakeBluetoothMediaTransportClient); + bluetooth_profile_manager_client_.reset( + new FakeBluetoothProfileManagerClient); + bluetooth_gatt_characteristic_client_.reset( + new FakeBluetoothGattCharacteristicClient); + bluetooth_gatt_descriptor_client_.reset( + new FakeBluetoothGattDescriptorClient); + bluetooth_gatt_manager_client_.reset(new FakeBluetoothGattManagerClient); + bluetooth_gatt_service_client_.reset(new FakeBluetoothGattServiceClient); + } +} + +BluetoothDBusClientBundle::~BluetoothDBusClientBundle() {} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_dbus_client_bundle.h b/device/bluetooth/dbus/bluetooth_dbus_client_bundle.h new file mode 100644 index 0000000..3beef619 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_dbus_client_bundle.h
@@ -0,0 +1,114 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_DBUS_CLIENT_BUNDLE_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_DBUS_CLIENT_BUNDLE_H_ + +#include <string> + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "device/bluetooth/bluetooth_export.h" + +namespace bluez { + +class BluetoothAdapterClient; +class BluetoothAgentManagerClient; +class BluetoothDeviceClient; +class BluetoothGattCharacteristicClient; +class BluetoothGattDescriptorClient; +class BluetoothGattManagerClient; +class BluetoothGattServiceClient; +class BluetoothInputClient; +class BluetoothLEAdvertisingManagerClient; +class BluetoothMediaClient; +class BluetoothMediaTransportClient; +class BluetoothProfileManagerClient; + +// The bundle of all D-Bus clients used in DBusThreadManager. The bundle +// is used to delete them at once in the right order before shutting down the +// system bus. See also the comment in the destructor of DBusThreadManager. +class DEVICE_BLUETOOTH_EXPORT BluetoothDBusClientBundle { + public: + explicit BluetoothDBusClientBundle(bool use_stubs); + ~BluetoothDBusClientBundle(); + + // Returns true if |client| is stubbed. + bool IsUsingStub() { return use_stubs_; } + + BluetoothAdapterClient* bluetooth_adapter_client() { + return bluetooth_adapter_client_.get(); + } + + BluetoothLEAdvertisingManagerClient* + bluetooth_le_advertising_manager_client() { + return bluetooth_le_advertising_manager_client_.get(); + } + + BluetoothAgentManagerClient* bluetooth_agent_manager_client() { + return bluetooth_agent_manager_client_.get(); + } + + BluetoothDeviceClient* bluetooth_device_client() { + return bluetooth_device_client_.get(); + } + + BluetoothGattCharacteristicClient* bluetooth_gatt_characteristic_client() { + return bluetooth_gatt_characteristic_client_.get(); + } + + BluetoothGattDescriptorClient* bluetooth_gatt_descriptor_client() { + return bluetooth_gatt_descriptor_client_.get(); + } + + BluetoothGattManagerClient* bluetooth_gatt_manager_client() { + return bluetooth_gatt_manager_client_.get(); + } + + BluetoothGattServiceClient* bluetooth_gatt_service_client() { + return bluetooth_gatt_service_client_.get(); + } + + BluetoothInputClient* bluetooth_input_client() { + return bluetooth_input_client_.get(); + } + + BluetoothMediaClient* bluetooth_media_client() { + return bluetooth_media_client_.get(); + } + + BluetoothMediaTransportClient* bluetooth_media_transport_client() { + return bluetooth_media_transport_client_.get(); + } + + BluetoothProfileManagerClient* bluetooth_profile_manager_client() { + return bluetooth_profile_manager_client_.get(); + } + + private: + friend class BluezDBusManagerSetter; + + bool use_stubs_; + + scoped_ptr<BluetoothAdapterClient> bluetooth_adapter_client_; + scoped_ptr<BluetoothLEAdvertisingManagerClient> + bluetooth_le_advertising_manager_client_; + scoped_ptr<BluetoothAgentManagerClient> bluetooth_agent_manager_client_; + scoped_ptr<BluetoothDeviceClient> bluetooth_device_client_; + scoped_ptr<BluetoothGattCharacteristicClient> + bluetooth_gatt_characteristic_client_; + scoped_ptr<BluetoothGattDescriptorClient> bluetooth_gatt_descriptor_client_; + scoped_ptr<BluetoothGattManagerClient> bluetooth_gatt_manager_client_; + scoped_ptr<BluetoothGattServiceClient> bluetooth_gatt_service_client_; + scoped_ptr<BluetoothInputClient> bluetooth_input_client_; + scoped_ptr<BluetoothMediaClient> bluetooth_media_client_; + scoped_ptr<BluetoothMediaTransportClient> bluetooth_media_transport_client_; + scoped_ptr<BluetoothProfileManagerClient> bluetooth_profile_manager_client_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothDBusClientBundle); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_DBUS_CLIENT_BUNDLE_H_
diff --git a/device/bluetooth/dbus/bluetooth_device_client.cc b/device/bluetooth/dbus/bluetooth_device_client.cc new file mode 100644 index 0000000..7aaafa2 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_device_client.cc
@@ -0,0 +1,379 @@ +// Copyright 2013 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 "device/bluetooth/dbus/bluetooth_device_client.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/stl_util.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_manager.h" +#include "dbus/object_proxy.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +namespace { + +// Value returned for the the RSSI or TX power if it cannot be read. +const int kUnknownPower = 127; + +} // namespace + +const char BluetoothDeviceClient::kNoResponseError[] = + "org.chromium.Error.NoResponse"; +const char BluetoothDeviceClient::kUnknownDeviceError[] = + "org.chromium.Error.UnknownDevice"; + +BluetoothDeviceClient::Properties::Properties( + dbus::ObjectProxy* object_proxy, + const std::string& interface_name, + const PropertyChangedCallback& callback) + : dbus::PropertySet(object_proxy, interface_name, callback) { + RegisterProperty(bluetooth_device::kAddressProperty, &address); + RegisterProperty(bluetooth_device::kNameProperty, &name); + RegisterProperty(bluetooth_device::kIconProperty, &icon); + RegisterProperty(bluetooth_device::kClassProperty, &bluetooth_class); + RegisterProperty(bluetooth_device::kAppearanceProperty, &appearance); + RegisterProperty(bluetooth_device::kUUIDsProperty, &uuids); + RegisterProperty(bluetooth_device::kPairedProperty, &paired); + RegisterProperty(bluetooth_device::kConnectedProperty, &connected); + RegisterProperty(bluetooth_device::kTrustedProperty, &trusted); + RegisterProperty(bluetooth_device::kBlockedProperty, &blocked); + RegisterProperty(bluetooth_device::kAliasProperty, &alias); + RegisterProperty(bluetooth_device::kAdapterProperty, &adapter); + RegisterProperty(bluetooth_device::kLegacyPairingProperty, &legacy_pairing); + RegisterProperty(bluetooth_device::kModaliasProperty, &modalias); + RegisterProperty(bluetooth_device::kRSSIProperty, &rssi); + RegisterProperty(bluetooth_device::kTxPowerProperty, &tx_power); + RegisterProperty(bluetooth_device::kGattServicesProperty, &gatt_services); +} + +BluetoothDeviceClient::Properties::~Properties() {} + +// The BluetoothDeviceClient implementation used in production. +class BluetoothDeviceClientImpl : public BluetoothDeviceClient, + public dbus::ObjectManager::Interface { + public: + BluetoothDeviceClientImpl() + : object_manager_(NULL), weak_ptr_factory_(this) {} + + ~BluetoothDeviceClientImpl() override { + object_manager_->UnregisterInterface( + bluetooth_device::kBluetoothDeviceInterface); + } + + // BluetoothDeviceClient override. + void AddObserver(BluetoothDeviceClient::Observer* observer) override { + DCHECK(observer); + observers_.AddObserver(observer); + } + + // BluetoothDeviceClient override. + void RemoveObserver(BluetoothDeviceClient::Observer* observer) override { + DCHECK(observer); + observers_.RemoveObserver(observer); + } + + // dbus::ObjectManager::Interface override. + dbus::PropertySet* CreateProperties( + dbus::ObjectProxy* object_proxy, + const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + Properties* properties = + new Properties(object_proxy, interface_name, + base::Bind(&BluetoothDeviceClientImpl::OnPropertyChanged, + weak_ptr_factory_.GetWeakPtr(), object_path)); + return static_cast<dbus::PropertySet*>(properties); + } + + // BluetoothDeviceClient override. + std::vector<dbus::ObjectPath> GetDevicesForAdapter( + const dbus::ObjectPath& adapter_path) override { + std::vector<dbus::ObjectPath> object_paths, device_paths; + device_paths = object_manager_->GetObjectsWithInterface( + bluetooth_device::kBluetoothDeviceInterface); + for (std::vector<dbus::ObjectPath>::iterator iter = device_paths.begin(); + iter != device_paths.end(); ++iter) { + Properties* properties = GetProperties(*iter); + if (properties->adapter.value() == adapter_path) + object_paths.push_back(*iter); + } + return object_paths; + } + + // BluetoothDeviceClient override. + Properties* GetProperties(const dbus::ObjectPath& object_path) override { + return static_cast<Properties*>(object_manager_->GetProperties( + object_path, bluetooth_device::kBluetoothDeviceInterface)); + } + + // BluetoothDeviceClient override. + void Connect(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface, + bluetooth_device::kConnect); + + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownDeviceError, ""); + return; + } + + // Connect may take an arbitrary length of time, so use no timeout. + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_INFINITE, + base::Bind(&BluetoothDeviceClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothDeviceClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothDeviceClient override. + void Disconnect(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface, + bluetooth_device::kDisconnect); + + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownDeviceError, ""); + return; + } + + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothDeviceClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothDeviceClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothDeviceClient override. + void ConnectProfile(const dbus::ObjectPath& object_path, + const std::string& uuid, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface, + bluetooth_device::kConnectProfile); + + dbus::MessageWriter writer(&method_call); + writer.AppendString(uuid); + + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownDeviceError, ""); + return; + } + + // Connect may take an arbitrary length of time, so use no timeout. + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_INFINITE, + base::Bind(&BluetoothDeviceClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothDeviceClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothDeviceClient override. + void DisconnectProfile(const dbus::ObjectPath& object_path, + const std::string& uuid, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface, + bluetooth_device::kDisconnectProfile); + + dbus::MessageWriter writer(&method_call); + writer.AppendString(uuid); + + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownDeviceError, ""); + return; + } + + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothDeviceClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothDeviceClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothDeviceClient override. + void Pair(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface, + bluetooth_device::kPair); + + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownDeviceError, ""); + return; + } + + // Pairing may take an arbitrary length of time, so use no timeout. + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_INFINITE, + base::Bind(&BluetoothDeviceClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothDeviceClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothDeviceClient override. + void CancelPairing(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface, + bluetooth_device::kCancelPairing); + + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownDeviceError, ""); + return; + } + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothDeviceClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothDeviceClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothDeviceClient override. + void GetConnInfo(const dbus::ObjectPath& object_path, + const ConnInfoCallback& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call( + bluetooth_plugin_device::kBluetoothPluginInterface, + bluetooth_plugin_device::kGetConnInfo); + + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownDeviceError, ""); + return; + } + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothDeviceClientImpl::OnGetConnInfoSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothDeviceClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + protected: + void Init(dbus::Bus* bus) override { + object_manager_ = bus->GetObjectManager( + bluetooth_object_manager::kBluetoothObjectManagerServiceName, + dbus::ObjectPath( + bluetooth_object_manager::kBluetoothObjectManagerServicePath)); + object_manager_->RegisterInterface( + bluetooth_device::kBluetoothDeviceInterface, this); + } + + private: + // Called by dbus::ObjectManager when an object with the device interface + // is created. Informs observers. + void ObjectAdded(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, + DeviceAdded(object_path)); + } + + // Called by dbus::ObjectManager when an object with the device interface + // is removed. Informs observers. + void ObjectRemoved(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, + DeviceRemoved(object_path)); + } + + // Called by BluetoothPropertySet when a property value is changed, + // either by result of a signal or response to a GetAll() or Get() + // call. Informs observers. + void OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) { + FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, + DevicePropertyChanged(object_path, property_name)); + } + + // Called when a response for successful method call is received. + void OnSuccess(const base::Closure& callback, dbus::Response* response) { + DCHECK(response); + callback.Run(); + } + + // Called when a response for the GetConnInfo method is received. + void OnGetConnInfoSuccess(const ConnInfoCallback& callback, + dbus::Response* response) { + int16 rssi = kUnknownPower; + int16 transmit_power = kUnknownPower; + int16 max_transmit_power = kUnknownPower; + + if (!response) { + LOG(ERROR) << "GetConnInfo succeeded, but no response received."; + callback.Run(rssi, transmit_power, max_transmit_power); + return; + } + + dbus::MessageReader reader(response); + if (!reader.PopInt16(&rssi) || !reader.PopInt16(&transmit_power) || + !reader.PopInt16(&max_transmit_power)) { + LOG(ERROR) << "Arguments for GetConnInfo invalid."; + } + callback.Run(rssi, transmit_power, max_transmit_power); + } + + // Called when a response for a failed method call is received. + void OnError(const ErrorCallback& error_callback, + dbus::ErrorResponse* response) { + // Error response has optional error message argument. + std::string error_name; + std::string error_message; + if (response) { + dbus::MessageReader reader(response); + error_name = response->GetErrorName(); + reader.PopString(&error_message); + } else { + error_name = kNoResponseError; + error_message = ""; + } + error_callback.Run(error_name, error_message); + } + + dbus::ObjectManager* object_manager_; + + // List of observers interested in event notifications from us. + base::ObserverList<BluetoothDeviceClient::Observer> observers_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothDeviceClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceClientImpl); +}; + +BluetoothDeviceClient::BluetoothDeviceClient() {} + +BluetoothDeviceClient::~BluetoothDeviceClient() {} + +BluetoothDeviceClient* BluetoothDeviceClient::Create() { + return new BluetoothDeviceClientImpl(); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_device_client.h b/device/bluetooth/dbus/bluetooth_device_client.h new file mode 100644 index 0000000..33b3f5d --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_device_client.h
@@ -0,0 +1,213 @@ +// Copyright 2013 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 DEVICE_BLUETOOTH_DBUS_BLUETOOTH_DEVICE_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_DEVICE_CLIENT_H_ + +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/observer_list.h" +#include "base/values.h" +#include "dbus/object_path.h" +#include "dbus/property.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluez_dbus_client.h" + +namespace bluez { + +// BluetoothDeviceClient is used to communicate with objects representing +// remote Bluetooth Devices. +class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceClient : public BluezDBusClient { + public: + // Structure of properties associated with bluetooth devices. + struct Properties : public dbus::PropertySet { + // The Bluetooth device address of the device. Read-only. + dbus::Property<std::string> address; + + // The Bluetooth friendly name of the device. Read-only, to give a + // different local name, use the |alias| property. + dbus::Property<std::string> name; + + // Proposed icon name for the device according to the freedesktop.org + // icon naming specification. Read-only. + dbus::Property<std::string> icon; + + // The Bluetooth class of the device. Read-only. + dbus::Property<uint32> bluetooth_class; + + // The GAP external appearance of the device. Read-only. + dbus::Property<uint16> appearance; + + // Unique numeric identifier for the vendor of the device. Read-only. + dbus::Property<uint16> vendor; + + // List of 128-bit UUIDs that represent the available remote services. + // Read-only. + dbus::Property<std::vector<std::string>> uuids; + + // Transmitted power level. This field is avaliable only for LE devices + // that include this field in AD. Read-only. + dbus::Property<int16> tx_power; + + // Indicates that the device is currently paired. Read-only. + dbus::Property<bool> paired; + + // Indicates that the device is currently connected. Read-only. + dbus::Property<bool> connected; + + // Whether the device is trusted, and connections should be always + // accepted and attempted when the device is visible. + dbus::Property<bool> trusted; + + // Whether the device is blocked, connections will be always rejected + // and the device will not be visible. + dbus::Property<bool> blocked; + + // Local alias for the device, if not set, is equal to |name|. + dbus::Property<std::string> alias; + + // Object path of the adapter the device belongs to. Read-only. + dbus::Property<dbus::ObjectPath> adapter; + + // Indicates whether the device is likely to only support pre-2.1 + // PIN Code pairing rather than 2.1 Secure Simple Pairing, this can + // give false positives. Read-only. + dbus::Property<bool> legacy_pairing; + + // Remote Device ID information in Linux kernel modalias format. Read-only. + dbus::Property<std::string> modalias; + + // Received signal strength indicator that is set when the device is + // discovered during inquiry. Read-only. + dbus::Property<int16> rssi; + + // List of GATT service object paths. Each referenced object exports the + // org.bluez.GattService1 interface and represents a remote GATT service. + // This property will be updated once all remote GATT services of this + // device have been discovered and exported over D-Bus. Read-only. + dbus::Property<std::vector<dbus::ObjectPath>> gatt_services; + + Properties(dbus::ObjectProxy* object_proxy, + const std::string& interface_name, + const PropertyChangedCallback& callback); + ~Properties() override; + }; + + // Interface for observing changes from a remote bluetooth device. + class Observer { + public: + virtual ~Observer() {} + + // Called when the remote device with object path |object_path| is added + // to the set of known devices. + virtual void DeviceAdded(const dbus::ObjectPath& object_path) {} + + // Called when the remote device with object path |object_path| is removed + // from the set of known devices. + virtual void DeviceRemoved(const dbus::ObjectPath& object_path) {} + + // Called when the device with object path |object_path| has a + // change in value of the property named |property_name|. + virtual void DevicePropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) {} + }; + + ~BluetoothDeviceClient() override; + + // Adds and removes observers for events on all remote bluetooth + // devices. Check the |object_path| parameter of observer methods to + // determine which device is issuing the event. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Returns the list of device object paths associated with the given adapter + // identified by the D-Bus object path |adapter_path|. + virtual std::vector<dbus::ObjectPath> GetDevicesForAdapter( + const dbus::ObjectPath& adapter_path) = 0; + + // Obtain the properties for the device with object path |object_path|, + // any values should be copied if needed. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; + + // The ErrorCallback is used by device methods to indicate failure. + // It receives two arguments: the name of the error in |error_name| and + // an optional message in |error_message|. + typedef base::Callback<void(const std::string& error_name, + const std::string& error_message)> ErrorCallback; + + // Connects to the device with object path |object_path|, connecting any + // profiles that can be connected to and have been flagged as auto-connected; + // may be used to connect additional profiles for an already connected device, + // and succeeds if at least one profile is connected. + virtual void Connect(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Disconnects the device with object path |object_path|, terminating + // the low-level ACL connection and any profiles using it. + virtual void Disconnect(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Connects to the profile |uuid| on the device with object path + // |object_path|, provided that the profile has been registered with a + // handler on the local device. + virtual void ConnectProfile(const dbus::ObjectPath& object_path, + const std::string& uuid, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Disconnects from the profile |uuid| on the device with object path + // |object_path|. + virtual void DisconnectProfile(const dbus::ObjectPath& object_path, + const std::string& uuid, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Initiates pairing with the device with object path |object_path| and + // retrieves all SDP records or GATT primary services. An agent must be + // registered to handle the pairing request. + virtual void Pair(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Cancels an in-progress pairing with the device with object path + // |object_path| initiated by Pair(). + virtual void CancelPairing(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // The callback invoked for a successful GetConnInfo API call with the + // RSSI, TX power, and maximum TX power of the current connection. + typedef base::Callback<void(int16 rssi, + int16 transmit_power, + int16 max_transmit_power)> ConnInfoCallback; + + // Returns the RSSI, TX power, and maximum TX power of a connection to the + // device with object path |object_path|. If the device is not connected, then + // an error will be returned. + virtual void GetConnInfo(const dbus::ObjectPath& object_path, + const ConnInfoCallback& callback, + const ErrorCallback& error_callback) = 0; + + // Creates the instance. + static BluetoothDeviceClient* Create(); + + // Constants used to indicate exceptional error conditions. + static const char kNoResponseError[]; + static const char kUnknownDeviceError[]; + + protected: + BluetoothDeviceClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_DEVICE_CLIENT_H_
diff --git a/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc b/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc new file mode 100644 index 0000000..6000a52 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc
@@ -0,0 +1,303 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h" + +#include "base/bind.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "dbus/bus.h" +#include "dbus/object_manager.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +namespace { + +// TODO(armansito): Move this constant to cros_system_api. +const char kValueProperty[] = "Value"; + +} // namespace + +// static +const char BluetoothGattCharacteristicClient::kNoResponseError[] = + "org.chromium.Error.NoResponse"; +// static +const char BluetoothGattCharacteristicClient::kUnknownCharacteristicError[] = + "org.chromium.Error.UnknownCharacteristic"; + +BluetoothGattCharacteristicClient::Properties::Properties( + dbus::ObjectProxy* object_proxy, + const std::string& interface_name, + const PropertyChangedCallback& callback) + : dbus::PropertySet(object_proxy, interface_name, callback) { + RegisterProperty(bluetooth_gatt_characteristic::kUUIDProperty, &uuid); + RegisterProperty(bluetooth_gatt_characteristic::kServiceProperty, &service); + RegisterProperty(kValueProperty, &value); + RegisterProperty(bluetooth_gatt_characteristic::kNotifyingProperty, + ¬ifying); + RegisterProperty(bluetooth_gatt_characteristic::kFlagsProperty, &flags); + RegisterProperty(bluetooth_gatt_characteristic::kDescriptorsProperty, + &descriptors); +} + +BluetoothGattCharacteristicClient::Properties::~Properties() {} + +// The BluetoothGattCharacteristicClient implementation used in production. +class BluetoothGattCharacteristicClientImpl + : public BluetoothGattCharacteristicClient, + public dbus::ObjectManager::Interface { + public: + BluetoothGattCharacteristicClientImpl() + : object_manager_(NULL), weak_ptr_factory_(this) {} + + ~BluetoothGattCharacteristicClientImpl() override { + object_manager_->UnregisterInterface( + bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface); + } + + // BluetoothGattCharacteristicClient override. + void AddObserver( + BluetoothGattCharacteristicClient::Observer* observer) override { + DCHECK(observer); + observers_.AddObserver(observer); + } + + // BluetoothGattCharacteristicClient override. + void RemoveObserver( + BluetoothGattCharacteristicClient::Observer* observer) override { + DCHECK(observer); + observers_.RemoveObserver(observer); + } + + // BluetoothGattCharacteristicClient override. + std::vector<dbus::ObjectPath> GetCharacteristics() override { + DCHECK(object_manager_); + return object_manager_->GetObjectsWithInterface( + bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface); + } + + // BluetoothGattCharacteristicClient override. + Properties* GetProperties(const dbus::ObjectPath& object_path) override { + DCHECK(object_manager_); + return static_cast<Properties*>(object_manager_->GetProperties( + object_path, + bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface)); + } + + // BluetoothGattCharacteristicClient override. + void ReadValue(const dbus::ObjectPath& object_path, + const ValueCallback& callback, + const ErrorCallback& error_callback) override { + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownCharacteristicError, ""); + return; + } + + dbus::MethodCall method_call( + bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, + bluetooth_gatt_characteristic::kReadValue); + + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothGattCharacteristicClientImpl::OnValueSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothGattCharacteristicClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothGattCharacteristicClient override. + void WriteValue(const dbus::ObjectPath& object_path, + const std::vector<uint8>& value, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownCharacteristicError, ""); + return; + } + + dbus::MethodCall method_call( + bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, + bluetooth_gatt_characteristic::kWriteValue); + dbus::MessageWriter writer(&method_call); + writer.AppendArrayOfBytes(value.data(), value.size()); + + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothGattCharacteristicClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothGattCharacteristicClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothGattCharacteristicClient override. + void StartNotify(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownCharacteristicError, ""); + return; + } + + dbus::MethodCall method_call( + bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, + bluetooth_gatt_characteristic::kStartNotify); + + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothGattCharacteristicClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothGattCharacteristicClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothGattCharacteristicClient override. + void StopNotify(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownCharacteristicError, ""); + return; + } + + dbus::MethodCall method_call( + bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, + bluetooth_gatt_characteristic::kStopNotify); + + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothGattCharacteristicClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothGattCharacteristicClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // dbus::ObjectManager::Interface override. + dbus::PropertySet* CreateProperties( + dbus::ObjectProxy* object_proxy, + const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + Properties* properties = new Properties( + object_proxy, interface_name, + base::Bind(&BluetoothGattCharacteristicClientImpl::OnPropertyChanged, + weak_ptr_factory_.GetWeakPtr(), object_path)); + return static_cast<dbus::PropertySet*>(properties); + } + + // dbus::ObjectManager::Interface override. + void ObjectAdded(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + VLOG(2) << "Remote GATT characteristic added: " << object_path.value(); + FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, + GattCharacteristicAdded(object_path)); + } + + // dbus::ObjectManager::Interface override. + void ObjectRemoved(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + VLOG(2) << "Remote GATT characteristic removed: " << object_path.value(); + FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, + GattCharacteristicRemoved(object_path)); + } + + protected: + // chromeos::DBusClient override. + void Init(dbus::Bus* bus) override { + object_manager_ = bus->GetObjectManager( + bluetooth_object_manager::kBluetoothObjectManagerServiceName, + dbus::ObjectPath( + bluetooth_object_manager::kBluetoothObjectManagerServicePath)); + object_manager_->RegisterInterface( + bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, + this); + } + + private: + // Called by dbus::PropertySet when a property value is changed, either by + // result of a signal or response to a GetAll() or Get() call. Informs + // observers. + virtual void OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) { + VLOG(2) << "Remote GATT characteristic property changed: " + << object_path.value() << ": " << property_name; + FOR_EACH_OBSERVER( + BluetoothGattCharacteristicClient::Observer, observers_, + GattCharacteristicPropertyChanged(object_path, property_name)); + } + + // Called when a response for successful method call is received. + void OnSuccess(const base::Closure& callback, dbus::Response* response) { + DCHECK(response); + callback.Run(); + } + + // Called when a characteristic value response for a successful method call + // is received. + void OnValueSuccess(const ValueCallback& callback, dbus::Response* response) { + DCHECK(response); + dbus::MessageReader reader(response); + + const uint8* bytes = NULL; + size_t length = 0; + + if (!reader.PopArrayOfBytes(&bytes, &length)) + VLOG(2) << "Error reading array of bytes in ValueCallback"; + + std::vector<uint8> value; + + if (bytes) + value.assign(bytes, bytes + length); + + callback.Run(value); + } + + // Called when a response for a failed method call is received. + void OnError(const ErrorCallback& error_callback, + dbus::ErrorResponse* response) { + // Error response has optional error message argument. + std::string error_name; + std::string error_message; + if (response) { + dbus::MessageReader reader(response); + error_name = response->GetErrorName(); + reader.PopString(&error_message); + } else { + error_name = kNoResponseError; + error_message = ""; + } + error_callback.Run(error_name, error_message); + } + + dbus::ObjectManager* object_manager_; + + // List of observers interested in event notifications from us. + base::ObserverList<BluetoothGattCharacteristicClient::Observer> observers_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothGattCharacteristicClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothGattCharacteristicClientImpl); +}; + +BluetoothGattCharacteristicClient::BluetoothGattCharacteristicClient() {} + +BluetoothGattCharacteristicClient::~BluetoothGattCharacteristicClient() {} + +// static +BluetoothGattCharacteristicClient* BluetoothGattCharacteristicClient::Create() { + return new BluetoothGattCharacteristicClientImpl(); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h b/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h new file mode 100644 index 0000000..3c476eb --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h
@@ -0,0 +1,144 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "dbus/object_path.h" +#include "dbus/property.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluez_dbus_client.h" + +namespace bluez { + +// BluetoothGattCharacteristicClient is used to communicate with remote GATT +// characteristic objects exposed by the Bluetooth daemon. +class DEVICE_BLUETOOTH_EXPORT BluetoothGattCharacteristicClient + : public BluezDBusClient { + public: + // Structure of properties associated with GATT characteristics. + struct Properties : public dbus::PropertySet { + // The 128-bit characteristic UUID. [read-only] + dbus::Property<std::string> uuid; + + // Object path of the GATT service the characteristic belongs to. + // [read-only] + dbus::Property<dbus::ObjectPath> service; + + // The cached value of the characteristic. This property gets updated only + // after a successful read request and when a notification or indication is + // received. [read-only] + dbus::Property<std::vector<uint8_t>> value; + + // Whether or not this characteristic is currently sending ValueUpdated + // signals. [read-only] + dbus::Property<bool> notifying; + + // List of flags representing the GATT "Characteristic Properties bit field" + // and properties read from the GATT "Characteristic Extended Properties" + // descriptor bit field. [read-only, optional] + dbus::Property<std::vector<std::string>> flags; + + // Array of object paths representing the descriptors of this + // characteristic. [read-only] + dbus::Property<std::vector<dbus::ObjectPath>> descriptors; + + Properties(dbus::ObjectProxy* object_proxy, + const std::string& interface_name, + const PropertyChangedCallback& callback); + ~Properties() override; + }; + + // Interface for observing changes from a remote GATT characteristic. + class Observer { + public: + virtual ~Observer() {} + + // Called when the GATT characteristic with object path |object_path| is + // added to the system. + virtual void GattCharacteristicAdded(const dbus::ObjectPath& object_path) {} + + // Called when the GATT characteristic with object path |object_path| is + // removed from the system. + virtual void GattCharacteristicRemoved( + const dbus::ObjectPath& object_path) {} + + // Called when the GATT characteristic with object path |object_path| has a + // change in the value of the property named |property_name|. + virtual void GattCharacteristicPropertyChanged( + const dbus::ObjectPath& object_path, + const std::string& property_name) {} + }; + + // Callbacks used to report the result of asynchronous methods. + typedef base::Callback<void(const std::string& error_name, + const std::string& error_message)> ErrorCallback; + typedef base::Callback<void(const std::vector<uint8>& value)> ValueCallback; + + ~BluetoothGattCharacteristicClient() override; + + // Adds and removes observers for events on all remote GATT characteristics. + // Check the |object_path| parameter of observer methods to determine which + // GATT characteristic is issuing the event. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Returns the list of GATT characteristic object paths known to the system. + virtual std::vector<dbus::ObjectPath> GetCharacteristics() = 0; + + // Obtain the properties for the GATT characteristic with object path + // |object_path|. Values should be copied if needed. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; + + // Issues a request to read the value of GATT characteristic with object path + // |object_path| and returns the value in |callback| on success. On error, + // invokes |error_callback|. + virtual void ReadValue(const dbus::ObjectPath& object_path, + const ValueCallback& callback, + const ErrorCallback& error_callback) = 0; + + // Issues a request to write the value of GATT characteristic with object path + // |object_path| with value |value|. Invokes |callback| on success and + // |error_callback| on failure. + virtual void WriteValue(const dbus::ObjectPath& object_path, + const std::vector<uint8>& value, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Starts a notification session from this characteristic with object path + // |object_path| if it supports value notifications or indications. Invokes + // |callback| on success and |error_callback| on failure. + virtual void StartNotify(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Cancels any previous StartNotify transaction for characteristic with + // object path |object_path|. Invokes |callback| on success and + // |error_callback| on failure. + virtual void StopNotify(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Creates the instance. + static BluetoothGattCharacteristicClient* Create(); + + // Constants used to indicate exceptional error conditions. + static const char kNoResponseError[]; + static const char kUnknownCharacteristicError[]; + + protected: + BluetoothGattCharacteristicClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothGattCharacteristicClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_
diff --git a/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.cc b/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.cc new file mode 100644 index 0000000..4decdf0 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.cc
@@ -0,0 +1,464 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/memory/weak_ptr.h" +#include "base/strings/string_util.h" +#include "base/threading/platform_thread.h" +#include "dbus/exported_object.h" +#include "dbus/message.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { +namespace { +const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs"; +const char kErrorPropertyReadOnly[] = + "org.freedesktop.DBus.Error.PropertyReadOnly"; +const char kErrorFailed[] = "org.freedesktop.DBus.Error.Failed"; +} // namespace + +// The BluetoothGattCharacteristicServiceProvider implementation used in +// production. +class BluetoothGattCharacteristicServiceProviderImpl + : public BluetoothGattCharacteristicServiceProvider { + public: + BluetoothGattCharacteristicServiceProviderImpl( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate, + const std::string& uuid, + const std::vector<std::string>& flags, + const std::vector<std::string>& permissions, + const dbus::ObjectPath& service_path) + : origin_thread_id_(base::PlatformThread::CurrentId()), + uuid_(uuid), + bus_(bus), + delegate_(delegate), + object_path_(object_path), + service_path_(service_path), + weak_ptr_factory_(this) { + VLOG(1) << "Created Bluetooth GATT characteristic: " << object_path.value() + << " UUID: " << uuid; + DCHECK(bus_); + DCHECK(delegate_); + DCHECK(!uuid_.empty()); + DCHECK(object_path_.IsValid()); + DCHECK(service_path_.IsValid()); + DCHECK(base::StartsWith(object_path_.value(), service_path_.value() + "/", + base::CompareCase::SENSITIVE)); + + exported_object_ = bus_->GetExportedObject(object_path_); + + exported_object_->ExportMethod( + dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet, + base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::Get, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesSet, + base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::Set, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll, + base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::GetAll, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + } + + ~BluetoothGattCharacteristicServiceProviderImpl() override { + VLOG(1) << "Cleaning up Bluetooth GATT characteristic: " + << object_path_.value(); + bus_->UnregisterExportedObject(object_path_); + } + + // BluetoothGattCharacteristicServiceProvider override. + void SendValueChanged(const std::vector<uint8>& value) override { + VLOG(2) << "Emitting a PropertiesChanged signal for characteristic value."; + dbus::Signal signal(dbus::kDBusPropertiesInterface, + dbus::kDBusPropertiesChangedSignal); + dbus::MessageWriter writer(&signal); + dbus::MessageWriter array_writer(NULL); + dbus::MessageWriter dict_entry_writer(NULL); + dbus::MessageWriter variant_writer(NULL); + + // interface_name + writer.AppendString( + bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface); + + // changed_properties + writer.OpenArray("{sv}", &array_writer); + array_writer.OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString( + bluetooth_gatt_characteristic::kValueProperty); + dict_entry_writer.OpenVariant("ay", &variant_writer); + variant_writer.AppendArrayOfBytes(value.data(), value.size()); + dict_entry_writer.CloseContainer(&variant_writer); + array_writer.CloseContainer(&dict_entry_writer); + writer.CloseContainer(&array_writer); + + // invalidated_properties. + writer.OpenArray("s", &array_writer); + writer.CloseContainer(&array_writer); + + exported_object_->SendSignal(&signal); + } + + private: + // Returns true if the current thread is on the origin thread. + bool OnOriginThread() { + return base::PlatformThread::CurrentId() == origin_thread_id_; + } + + // Called by dbus:: when the Bluetooth daemon fetches a single property of + // the characteristic. + void Get(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(2) << "BluetoothGattCharacteristicServiceProvider::Get: " + << object_path_.value(); + DCHECK(OnOriginThread()); + + dbus::MessageReader reader(method_call); + + std::string interface_name; + std::string property_name; + if (!reader.PopString(&interface_name) || + !reader.PopString(&property_name) || reader.HasMoreData()) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, + "Expected 'ss'."); + response_sender.Run(error_response.Pass()); + return; + } + + // Only the GATT characteristic interface is supported. + if (interface_name != + bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidArgs, + "No such interface: '" + interface_name + "'."); + response_sender.Run(error_response.Pass()); + return; + } + + // If getting the "Value" property, obtain the value from the delegate. + if (property_name == bluetooth_gatt_characteristic::kValueProperty) { + DCHECK(delegate_); + delegate_->GetCharacteristicValue( + base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnGet, + weak_ptr_factory_.GetWeakPtr(), method_call, + response_sender), + base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure, + weak_ptr_factory_.GetWeakPtr(), method_call, + response_sender)); + return; + } + + scoped_ptr<dbus::Response> response = + dbus::Response::FromMethodCall(method_call); + dbus::MessageWriter writer(response.get()); + dbus::MessageWriter variant_writer(NULL); + + // TODO(armansito): Process the "Flags" and "Permissions" properties below. + if (property_name == bluetooth_gatt_characteristic::kUUIDProperty) { + writer.OpenVariant("s", &variant_writer); + variant_writer.AppendString(uuid_); + writer.CloseContainer(&variant_writer); + } else if (property_name == + bluetooth_gatt_characteristic::kServiceProperty) { + writer.OpenVariant("o", &variant_writer); + variant_writer.AppendObjectPath(service_path_); + writer.CloseContainer(&variant_writer); + } else { + response = dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidArgs, + "No such property: '" + property_name + "'."); + } + + response_sender.Run(response.Pass()); + } + + // Called by dbus:: when the Bluetooth daemon sets a single property of the + // characteristic. + void Set(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(2) << "BluetoothGattCharacteristicServiceProvider::Set: " + << object_path_.value(); + DCHECK(OnOriginThread()); + + dbus::MessageReader reader(method_call); + + std::string interface_name; + std::string property_name; + dbus::MessageReader variant_reader(NULL); + if (!reader.PopString(&interface_name) || + !reader.PopString(&property_name) || + !reader.PopVariant(&variant_reader) || reader.HasMoreData()) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, + "Expected 'ssv'."); + response_sender.Run(error_response.Pass()); + return; + } + + // Only the GATT characteristic interface is allowed. + if (interface_name != + bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidArgs, + "No such interface: '" + interface_name + "'."); + response_sender.Run(error_response.Pass()); + return; + } + + // Only the "Value" property is writeable. + if (property_name != bluetooth_gatt_characteristic::kValueProperty) { + std::string error_name; + std::string error_message; + if (property_name == bluetooth_gatt_characteristic::kUUIDProperty || + property_name == bluetooth_gatt_characteristic::kServiceProperty) { + error_name = kErrorPropertyReadOnly; + error_message = "Read-only property: '" + property_name + "'."; + } else { + error_name = kErrorInvalidArgs; + error_message = "No such property: '" + property_name + "'."; + } + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall(method_call, error_name, + error_message); + response_sender.Run(error_response.Pass()); + return; + } + + // Obtain the value. + const uint8* bytes = NULL; + size_t length = 0; + if (!variant_reader.PopArrayOfBytes(&bytes, &length)) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidArgs, + "Property '" + property_name + "' has type 'ay'."); + response_sender.Run(error_response.Pass()); + return; + } + + // Pass the set request onto the delegate. + std::vector<uint8> value(bytes, bytes + length); + DCHECK(delegate_); + delegate_->SetCharacteristicValue( + value, + base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnSet, + weak_ptr_factory_.GetWeakPtr(), method_call, + response_sender), + base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure, + weak_ptr_factory_.GetWeakPtr(), method_call, + response_sender)); + } + + // Called by dbus:: when the Bluetooth daemon fetches all properties of the + // characteristic. + void GetAll(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(2) << "BluetoothGattCharacteristicServiceProvider::GetAll: " + << object_path_.value(); + DCHECK(OnOriginThread()); + + dbus::MessageReader reader(method_call); + + std::string interface_name; + if (!reader.PopString(&interface_name) || reader.HasMoreData()) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, + "Expected 's'."); + response_sender.Run(error_response.Pass()); + return; + } + + // Only the GATT characteristic interface is supported. + if (interface_name != + bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidArgs, + "No such interface: '" + interface_name + "'."); + response_sender.Run(error_response.Pass()); + return; + } + + // Try to obtain the value from the delegate. We will construct the + // response in the success callback. + DCHECK(delegate_); + delegate_->GetCharacteristicValue( + base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnGetAll, + weak_ptr_factory_.GetWeakPtr(), method_call, + response_sender), + base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure, + weak_ptr_factory_.GetWeakPtr(), method_call, + response_sender)); + } + + // Called by dbus:: when a method is exported. + void OnExported(const std::string& interface_name, + const std::string& method_name, + bool success) { + LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "." + << method_name; + } + + // Called by the Delegate in response to a method to call to get all + // properties, in which the delegate has successfully returned the + // characteristic value. + void OnGetAll(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender, + const std::vector<uint8>& value) { + VLOG(2) << "Characteristic value obtained from delegate. Responding to " + << "GetAll."; + + scoped_ptr<dbus::Response> response = + dbus::Response::FromMethodCall(method_call); + dbus::MessageWriter writer(response.get()); + dbus::MessageWriter array_writer(NULL); + dbus::MessageWriter dict_entry_writer(NULL); + dbus::MessageWriter variant_writer(NULL); + + writer.OpenArray("{sv}", &array_writer); + + array_writer.OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString( + bluetooth_gatt_characteristic::kUUIDProperty); + dict_entry_writer.AppendVariantOfString(uuid_); + array_writer.CloseContainer(&dict_entry_writer); + + array_writer.OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString( + bluetooth_gatt_characteristic::kServiceProperty); + dict_entry_writer.AppendVariantOfObjectPath(service_path_); + array_writer.CloseContainer(&dict_entry_writer); + + array_writer.OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString( + bluetooth_gatt_characteristic::kValueProperty); + dict_entry_writer.OpenVariant("ay", &variant_writer); + variant_writer.AppendArrayOfBytes(value.data(), value.size()); + dict_entry_writer.CloseContainer(&variant_writer); + array_writer.CloseContainer(&dict_entry_writer); + + // TODO(armansito): Process Flags & Permissions properties. + + writer.CloseContainer(&array_writer); + + response_sender.Run(response.Pass()); + } + + // Called by the Delegate in response to a successful method call to get the + // characteristic value. + void OnGet(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender, + const std::vector<uint8>& value) { + VLOG(2) << "Returning characteristic value obtained from delegate."; + scoped_ptr<dbus::Response> response = + dbus::Response::FromMethodCall(method_call); + dbus::MessageWriter writer(response.get()); + dbus::MessageWriter variant_writer(NULL); + + writer.OpenVariant("ay", &variant_writer); + variant_writer.AppendArrayOfBytes(value.data(), value.size()); + writer.CloseContainer(&variant_writer); + + response_sender.Run(response.Pass()); + } + + // Called by the Delegate in response to a successful method call to set the + // characteristic value. + void OnSet(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(2) << "Successfully set characteristic value. Return success."; + response_sender.Run(dbus::Response::FromMethodCall(method_call)); + } + + // Called by the Delegate in response to a failed method call to get or set + // the characteristic value. + void OnFailure(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(2) << "Failed to get/set characteristic value. Report error."; + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall( + method_call, kErrorFailed, + "Failed to get/set characteristic value."); + response_sender.Run(error_response.Pass()); + } + + // Origin thread (i.e. the UI thread in production). + base::PlatformThreadId origin_thread_id_; + + // 128-bit characteristic UUID of this object. + std::string uuid_; + + // D-Bus bus object is exported on, not owned by this object and must + // outlive it. + dbus::Bus* bus_; + + // Incoming methods to get and set the "Value" property are passed on to the + // delegate and callbacks passed to generate a reply. |delegate_| is generally + // the object that owns this one and must outlive it. + Delegate* delegate_; + + // D-Bus object path of object we are exporting, kept so we can unregister + // again in our destructor. + dbus::ObjectPath object_path_; + + // Object path of the GATT service that the exported characteristic belongs + // to. + dbus::ObjectPath service_path_; + + // D-Bus object we are exporting, owned by this object. + scoped_refptr<dbus::ExportedObject> exported_object_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothGattCharacteristicServiceProviderImpl> + weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothGattCharacteristicServiceProviderImpl); +}; + +BluetoothGattCharacteristicServiceProvider:: + BluetoothGattCharacteristicServiceProvider() {} + +BluetoothGattCharacteristicServiceProvider:: + ~BluetoothGattCharacteristicServiceProvider() {} + +// static +BluetoothGattCharacteristicServiceProvider* +BluetoothGattCharacteristicServiceProvider::Create( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate, + const std::string& uuid, + const std::vector<std::string>& flags, + const std::vector<std::string>& permissions, + const dbus::ObjectPath& service_path) { + if (!bluez::BluezDBusManager::Get()->IsUsingStub()) { + return new BluetoothGattCharacteristicServiceProviderImpl( + bus, object_path, delegate, uuid, flags, permissions, service_path); + } + return new FakeBluetoothGattCharacteristicServiceProvider( + object_path, delegate, uuid, flags, permissions, service_path); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.h b/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.h new file mode 100644 index 0000000..ad5d999f --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.h
@@ -0,0 +1,113 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "dbus/bus.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" + +namespace bluez { + +// BluetoothGattCharacteristicServiceProvider is used to provide a D-Bus object +// that represents a local GATT characteristic that the Bluetooth daemon can +// communicate with. +// +// Instantiate with a chosen D-Bus object path, delegate, and other fields. +// The Bluetooth daemon communicates with a GATT characteristic using the +// standard DBus.Properties interface. While most properties of the GATT +// characteristic interface are read-only and don't change throughout the +// life-time of the object, the "Value" property is both writeable and its +// value can change. Both Get and Set operations performed on the "Value" +// property are delegated to the Delegate object, an instance of which is +// mandatory during initialization. In addition, a "SendValueChanged" method is +// provided, which emits a DBus.Properties.PropertyChanged signal for the +// "Value" property. +class DEVICE_BLUETOOTH_EXPORT BluetoothGattCharacteristicServiceProvider { + public: + // Interface for reacting to GATT characteristic value requests. + class Delegate { + public: + virtual ~Delegate() {} + + // ValueCallback is used for methods that require a characteristic value + // to be returned. + typedef base::Callback<void(const std::vector<uint8>&)> ValueCallback; + + // ErrorCallback is used by methods to report failure. + typedef base::Closure ErrorCallback; + + // This method will be called when a remote device requests to read the + // value of the exported GATT characteristic. Invoke |callback| with a value + // to return that value to the requester. Invoke |error_callback| to report + // a failure to read the value. This can happen, for example, if the + // characteristic has no read permission set. Either callback should be + // invoked after a reasonable amount of time, since the request will time + // out if left pending for too long. + virtual void GetCharacteristicValue( + const ValueCallback& callback, + const ErrorCallback& error_callback) = 0; + + // This method will be called, when a remote device requests to write the + // value of the exported GATT characteristic. Invoke |callback| to report + // that the value was successfully written. Invoke |error_callback| to + // report a failure to write the value. This can happen, for example, if the + // characteristic has no write permission set. Either callback should be + // invoked after a reasonable amount of time, since the request will time + // out if left pending for too long. + // + // The delegate should use this method to perform any side-effects that may + // occur based on the set value and potentially send a property changed + // signal to notify the Bluetooth daemon that the value has changed. + virtual void SetCharacteristicValue( + const std::vector<uint8>& value, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + }; + + virtual ~BluetoothGattCharacteristicServiceProvider(); + + // Send a PropertyChanged signal to notify the Bluetooth daemon that the value + // of the "Value" property has changed to |value|. + virtual void SendValueChanged(const std::vector<uint8>& value) = 0; + + // Creates the instance, where |bus| is the D-Bus bus connection to export + // the object onto, |uuid| is the 128-bit GATT characteristic UUID, + // |flags| is the list of GATT characteristic properties, |permissions| is the + // list of attribute permissions, |service_path| is the object path of the + // exported GATT service the characteristic belongs to, |object_path| is the + // object path that the characteristic should have, and |delegate| is the + // object that "Value" Get/Set requests will be passed to and responses + // generated from. + // + // Object paths of GATT characteristics must be hierarchical to the path of + // the GATT service they belong to. Hence, |object_path| must have + // |service_path| as its prefix. Ownership of |delegate| is not taken, thus + // the delegate should outlive this instance. A delegate should handle only + // a single exported characteristic and own it. + static BluetoothGattCharacteristicServiceProvider* Create( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate, + const std::string& uuid, + const std::vector<std::string>& flags, + const std::vector<std::string>& permissions, + const dbus::ObjectPath& service_path); + + protected: + BluetoothGattCharacteristicServiceProvider(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothGattCharacteristicServiceProvider); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_
diff --git a/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.cc b/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.cc new file mode 100644 index 0000000..f3ba343c --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.cc
@@ -0,0 +1,251 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h" + +#include "base/bind.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "dbus/bus.h" +#include "dbus/object_manager.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +namespace { + +// TODO(armansito): Move this constant to cros_system_api. +const char kValueProperty[] = "Value"; + +} // namespace + +// static +const char BluetoothGattDescriptorClient::kNoResponseError[] = + "org.chromium.Error.NoResponse"; +// static +const char BluetoothGattDescriptorClient::kUnknownDescriptorError[] = + "org.chromium.Error.UnknownDescriptor"; + +BluetoothGattDescriptorClient::Properties::Properties( + dbus::ObjectProxy* object_proxy, + const std::string& interface_name, + const PropertyChangedCallback& callback) + : dbus::PropertySet(object_proxy, interface_name, callback) { + RegisterProperty(bluetooth_gatt_descriptor::kUUIDProperty, &uuid); + RegisterProperty(bluetooth_gatt_descriptor::kCharacteristicProperty, + &characteristic); + RegisterProperty(kValueProperty, &value); +} + +BluetoothGattDescriptorClient::Properties::~Properties() {} + +// The BluetoothGattDescriptorClient implementation used in production. +class BluetoothGattDescriptorClientImpl + : public BluetoothGattDescriptorClient, + public dbus::ObjectManager::Interface { + public: + BluetoothGattDescriptorClientImpl() + : object_manager_(NULL), weak_ptr_factory_(this) {} + + ~BluetoothGattDescriptorClientImpl() override { + object_manager_->UnregisterInterface( + bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface); + } + + // BluetoothGattDescriptorClientImpl override. + void AddObserver(BluetoothGattDescriptorClient::Observer* observer) override { + DCHECK(observer); + observers_.AddObserver(observer); + } + + // BluetoothGattDescriptorClientImpl override. + void RemoveObserver( + BluetoothGattDescriptorClient::Observer* observer) override { + DCHECK(observer); + observers_.RemoveObserver(observer); + } + + // BluetoothGattDescriptorClientImpl override. + std::vector<dbus::ObjectPath> GetDescriptors() override { + DCHECK(object_manager_); + return object_manager_->GetObjectsWithInterface( + bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface); + } + + // BluetoothGattDescriptorClientImpl override. + Properties* GetProperties(const dbus::ObjectPath& object_path) override { + DCHECK(object_manager_); + return static_cast<Properties*>(object_manager_->GetProperties( + object_path, + bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface)); + } + + // BluetoothGattDescriptorClientImpl override. + void ReadValue(const dbus::ObjectPath& object_path, + const ValueCallback& callback, + const ErrorCallback& error_callback) override { + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownDescriptorError, ""); + return; + } + + dbus::MethodCall method_call( + bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface, + bluetooth_gatt_descriptor::kReadValue); + + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothGattDescriptorClientImpl::OnValueSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothGattDescriptorClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothGattDescriptorClientImpl override. + void WriteValue(const dbus::ObjectPath& object_path, + const std::vector<uint8>& value, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownDescriptorError, ""); + return; + } + + dbus::MethodCall method_call( + bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface, + bluetooth_gatt_descriptor::kWriteValue); + dbus::MessageWriter writer(&method_call); + writer.AppendArrayOfBytes(value.data(), value.size()); + + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothGattDescriptorClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothGattDescriptorClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // dbus::ObjectManager::Interface override. + dbus::PropertySet* CreateProperties( + dbus::ObjectProxy* object_proxy, + const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + Properties* properties = new Properties( + object_proxy, interface_name, + base::Bind(&BluetoothGattDescriptorClientImpl::OnPropertyChanged, + weak_ptr_factory_.GetWeakPtr(), object_path)); + return static_cast<dbus::PropertySet*>(properties); + } + + // dbus::ObjectManager::Interface override. + void ObjectAdded(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + VLOG(2) << "Remote GATT descriptor added: " << object_path.value(); + FOR_EACH_OBSERVER(BluetoothGattDescriptorClient::Observer, observers_, + GattDescriptorAdded(object_path)); + } + + // dbus::ObjectManager::Interface override. + void ObjectRemoved(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + VLOG(2) << "Remote GATT descriptor removed: " << object_path.value(); + FOR_EACH_OBSERVER(BluetoothGattDescriptorClient::Observer, observers_, + GattDescriptorRemoved(object_path)); + } + + protected: + // chromeos::DBusClient override. + void Init(dbus::Bus* bus) override { + object_manager_ = bus->GetObjectManager( + bluetooth_object_manager::kBluetoothObjectManagerServiceName, + dbus::ObjectPath( + bluetooth_object_manager::kBluetoothObjectManagerServicePath)); + object_manager_->RegisterInterface( + bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface, this); + } + + private: + // Called by dbus::PropertySet when a property value is changed, either by + // result of a signal or response to a GetAll() or Get() call. Informs + // observers. + virtual void OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) { + VLOG(2) << "Remote GATT descriptor property changed: " + << object_path.value() << ": " << property_name; + FOR_EACH_OBSERVER( + BluetoothGattDescriptorClient::Observer, observers_, + GattDescriptorPropertyChanged(object_path, property_name)); + } + + // Called when a response for a successful method call is received. + void OnSuccess(const base::Closure& callback, dbus::Response* response) { + DCHECK(response); + callback.Run(); + } + + // Called when a descriptor value response for a successful method call is + // received. + void OnValueSuccess(const ValueCallback& callback, dbus::Response* response) { + DCHECK(response); + dbus::MessageReader reader(response); + + const uint8* bytes = NULL; + size_t length = 0; + + if (!reader.PopArrayOfBytes(&bytes, &length)) + VLOG(2) << "Error reading array of bytes in ValueCallback"; + + std::vector<uint8> value; + + if (bytes) + value.assign(bytes, bytes + length); + + callback.Run(value); + } + + // Called when a response for a failed method call is received. + void OnError(const ErrorCallback& error_callback, + dbus::ErrorResponse* response) { + // Error response has optional error message argument. + std::string error_name; + std::string error_message; + if (response) { + dbus::MessageReader reader(response); + error_name = response->GetErrorName(); + reader.PopString(&error_message); + } else { + error_name = kNoResponseError; + error_message = ""; + } + error_callback.Run(error_name, error_message); + } + + dbus::ObjectManager* object_manager_; + + // List of observers interested in event notifications from us. + base::ObserverList<BluetoothGattDescriptorClient::Observer> observers_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothGattDescriptorClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothGattDescriptorClientImpl); +}; + +BluetoothGattDescriptorClient::BluetoothGattDescriptorClient() {} + +BluetoothGattDescriptorClient::~BluetoothGattDescriptorClient() {} + +// static +BluetoothGattDescriptorClient* BluetoothGattDescriptorClient::Create() { + return new BluetoothGattDescriptorClientImpl(); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h b/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h new file mode 100644 index 0000000..364331e5 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h
@@ -0,0 +1,116 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "dbus/object_path.h" +#include "dbus/property.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluez_dbus_client.h" + +namespace bluez { + +// BluetoothGattDescriptorClient is used to communicate with remote GATT +// characteristic descriptor objects exposed by the Bluetooth daemon. +class DEVICE_BLUETOOTH_EXPORT BluetoothGattDescriptorClient + : public BluezDBusClient { + public: + // Structure of properties associated with GATT descriptors. + struct Properties : public dbus::PropertySet { + // The 128-bit characteristic descriptor UUID. [read-only] + dbus::Property<std::string> uuid; + + // Object path of the GATT characteristic the descriptor belongs to. + // [read-only] + dbus::Property<dbus::ObjectPath> characteristic; + + // The cached value of the descriptor. This property gets updated only after + // a successful read request. [read-only] + dbus::Property<std::vector<uint8_t>> value; + + Properties(dbus::ObjectProxy* object_proxy, + const std::string& interface_name, + const PropertyChangedCallback& callback); + ~Properties() override; + }; + + // Interface for observing changes from a remote GATT characteristic + // descriptor. + class Observer { + public: + virtual ~Observer() {} + + // Called when the GATT descriptor with object path |object_path| is added + // to the system. + virtual void GattDescriptorAdded(const dbus::ObjectPath& object_path) {} + + // Called when the GATT descriptor with object path |object_path| is removed + // from the system. + virtual void GattDescriptorRemoved(const dbus::ObjectPath& object_path) {} + + // Called when the GATT descriptor with object path |object_path| has a + // change in the value of the property named |property_name|. + virtual void GattDescriptorPropertyChanged( + const dbus::ObjectPath& object_path, + const std::string& property_name) {} + }; + + // Callbacks used to report the result of asynchronous methods. + typedef base::Callback<void(const std::string& error_name, + const std::string& error_message)> ErrorCallback; + typedef base::Callback<void(const std::vector<uint8>& value)> ValueCallback; + + ~BluetoothGattDescriptorClient() override; + + // Adds and removes observers for events on all remote GATT descriptors. Check + // the |object_path| parameter of observer methods to determine which GATT + // descriptor is issuing the event. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Returns the list of GATT descriptor object paths known to the system. + virtual std::vector<dbus::ObjectPath> GetDescriptors() = 0; + + // Obtain the properties for the GATT descriptor with object path + // |object_path|. Values should be copied if needed. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; + + // Issues a request to read the value of GATT descriptor with object path + // |object_path| and returns the value in |callback| on success. On error, + // invokes |error_callback|. + virtual void ReadValue(const dbus::ObjectPath& object_path, + const ValueCallback& callback, + const ErrorCallback& error_callback) = 0; + + // Issues a request to write the value of GATT descriptor with object path + // |object_path| with value |value|. Invokes |callback| on success and + // |error_callback| on failure. + virtual void WriteValue(const dbus::ObjectPath& object_path, + const std::vector<uint8>& value, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Creates the instance. + static BluetoothGattDescriptorClient* Create(); + + // Constants used to indicate exceptional error conditions. + static const char kNoResponseError[]; + static const char kUnknownDescriptorError[]; + + protected: + BluetoothGattDescriptorClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothGattDescriptorClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_
diff --git a/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.cc b/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.cc new file mode 100644 index 0000000..e4aa2454 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.cc
@@ -0,0 +1,457 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/memory/weak_ptr.h" +#include "base/strings/string_util.h" +#include "base/threading/platform_thread.h" +#include "dbus/exported_object.h" +#include "dbus/message.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { +namespace { +const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs"; +const char kErrorPropertyReadOnly[] = + "org.freedesktop.DBus.Error.PropertyReadOnly"; +const char kErrorFailed[] = "org.freedesktop.DBus.Error.Failed"; +} // namespace + +// The BluetoothGattDescriptorServiceProvider implementation used in production. +class BluetoothGattDescriptorServiceProviderImpl + : public BluetoothGattDescriptorServiceProvider { + public: + BluetoothGattDescriptorServiceProviderImpl( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate, + const std::string& uuid, + const std::vector<std::string>& permissions, + const dbus::ObjectPath& characteristic_path) + : origin_thread_id_(base::PlatformThread::CurrentId()), + uuid_(uuid), + bus_(bus), + delegate_(delegate), + object_path_(object_path), + characteristic_path_(characteristic_path), + weak_ptr_factory_(this) { + VLOG(1) << "Created Bluetooth GATT characteristic descriptor: " + << object_path.value() << " UUID: " << uuid; + DCHECK(bus_); + DCHECK(delegate_); + DCHECK(!uuid_.empty()); + DCHECK(object_path_.IsValid()); + DCHECK(characteristic_path_.IsValid()); + DCHECK(base::StartsWith(object_path_.value(), + characteristic_path_.value() + "/", + base::CompareCase::SENSITIVE)); + + exported_object_ = bus_->GetExportedObject(object_path_); + + exported_object_->ExportMethod( + dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet, + base::Bind(&BluetoothGattDescriptorServiceProviderImpl::Get, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesSet, + base::Bind(&BluetoothGattDescriptorServiceProviderImpl::Set, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll, + base::Bind(&BluetoothGattDescriptorServiceProviderImpl::GetAll, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + } + + ~BluetoothGattDescriptorServiceProviderImpl() override { + VLOG(1) << "Cleaning up Bluetooth GATT characteristic descriptor: " + << object_path_.value(); + bus_->UnregisterExportedObject(object_path_); + } + + // BluetoothGattDescriptorServiceProvider override. + void SendValueChanged(const std::vector<uint8>& value) override { + VLOG(2) << "Emitting a PropertiesChanged signal for descriptor value."; + dbus::Signal signal(dbus::kDBusPropertiesInterface, + dbus::kDBusPropertiesChangedSignal); + dbus::MessageWriter writer(&signal); + dbus::MessageWriter array_writer(NULL); + dbus::MessageWriter dict_entry_writer(NULL); + dbus::MessageWriter variant_writer(NULL); + + // interface_name + writer.AppendString( + bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface); + + // changed_properties + writer.OpenArray("{sv}", &array_writer); + array_writer.OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString(bluetooth_gatt_descriptor::kValueProperty); + dict_entry_writer.OpenVariant("ay", &variant_writer); + variant_writer.AppendArrayOfBytes(value.data(), value.size()); + dict_entry_writer.CloseContainer(&variant_writer); + array_writer.CloseContainer(&dict_entry_writer); + writer.CloseContainer(&array_writer); + + // invalidated_properties. + writer.OpenArray("s", &array_writer); + writer.CloseContainer(&array_writer); + + exported_object_->SendSignal(&signal); + } + + private: + // Returns true if the current thread is on the origin thread. + bool OnOriginThread() { + return base::PlatformThread::CurrentId() == origin_thread_id_; + } + + // Called by dbus:: when the Bluetooth daemon fetches a single property of + // the descriptor. + void Get(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(2) << "BluetoothGattDescriptorServiceProvider::Get: " + << object_path_.value(); + DCHECK(OnOriginThread()); + + dbus::MessageReader reader(method_call); + + std::string interface_name; + std::string property_name; + if (!reader.PopString(&interface_name) || + !reader.PopString(&property_name) || reader.HasMoreData()) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, + "Expected 'ss'."); + response_sender.Run(error_response.Pass()); + return; + } + + // Only the GATT descriptor interface is supported. + if (interface_name != + bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidArgs, + "No such interface: '" + interface_name + "'."); + response_sender.Run(error_response.Pass()); + return; + } + + // If getting the "Value" property, obtain the value from the delegate. + if (property_name == bluetooth_gatt_descriptor::kValueProperty) { + DCHECK(delegate_); + delegate_->GetDescriptorValue( + base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnGet, + weak_ptr_factory_.GetWeakPtr(), method_call, + response_sender), + base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnFailure, + weak_ptr_factory_.GetWeakPtr(), method_call, + response_sender)); + return; + } + + scoped_ptr<dbus::Response> response = + dbus::Response::FromMethodCall(method_call); + dbus::MessageWriter writer(response.get()); + dbus::MessageWriter variant_writer(NULL); + + // TODO(armansito): Process the "Permissions" property below. + if (property_name == bluetooth_gatt_descriptor::kUUIDProperty) { + writer.OpenVariant("s", &variant_writer); + variant_writer.AppendString(uuid_); + writer.CloseContainer(&variant_writer); + } else if (property_name == + bluetooth_gatt_descriptor::kCharacteristicProperty) { + writer.OpenVariant("o", &variant_writer); + variant_writer.AppendObjectPath(characteristic_path_); + writer.CloseContainer(&variant_writer); + } else { + response = dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidArgs, + "No such property: '" + property_name + "'."); + } + + response_sender.Run(response.Pass()); + } + + // Called by dbus:: when the Bluetooth daemon sets a single property of the + // descriptor. + void Set(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(2) << "BluetoothGattDescriptorServiceProvider::Set: " + << object_path_.value(); + DCHECK(OnOriginThread()); + + dbus::MessageReader reader(method_call); + + std::string interface_name; + std::string property_name; + dbus::MessageReader variant_reader(NULL); + if (!reader.PopString(&interface_name) || + !reader.PopString(&property_name) || + !reader.PopVariant(&variant_reader) || reader.HasMoreData()) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, + "Expected 'ssv'."); + response_sender.Run(error_response.Pass()); + return; + } + + // Only the GATT descriptor interface is allowed. + if (interface_name != + bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidArgs, + "No such interface: '" + interface_name + "'."); + response_sender.Run(error_response.Pass()); + return; + } + + // Only the "Value" property is writeable. + if (property_name != bluetooth_gatt_descriptor::kValueProperty) { + std::string error_name; + std::string error_message; + if (property_name == bluetooth_gatt_descriptor::kUUIDProperty || + property_name == bluetooth_gatt_descriptor::kCharacteristicProperty) { + error_name = kErrorPropertyReadOnly; + error_message = "Read-only property: '" + property_name + "'."; + } else { + error_name = kErrorInvalidArgs; + error_message = "No such property: '" + property_name + "'."; + } + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall(method_call, error_name, + error_message); + response_sender.Run(error_response.Pass()); + return; + } + + // Obtain the value. + const uint8* bytes = NULL; + size_t length = 0; + if (!variant_reader.PopArrayOfBytes(&bytes, &length)) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidArgs, + "Property '" + property_name + "' has type 'ay'."); + response_sender.Run(error_response.Pass()); + return; + } + + // Pass the set request onto the delegate. + std::vector<uint8> value(bytes, bytes + length); + DCHECK(delegate_); + delegate_->SetDescriptorValue( + value, base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnSet, + weak_ptr_factory_.GetWeakPtr(), method_call, + response_sender), + base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnFailure, + weak_ptr_factory_.GetWeakPtr(), method_call, + response_sender)); + } + + // Called by dbus:: when the Bluetooth daemon fetches all properties of the + // descriptor. + void GetAll(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(2) << "BluetoothGattDescriptorServiceProvider::GetAll: " + << object_path_.value(); + DCHECK(OnOriginThread()); + + dbus::MessageReader reader(method_call); + + std::string interface_name; + if (!reader.PopString(&interface_name) || reader.HasMoreData()) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, + "Expected 's'."); + response_sender.Run(error_response.Pass()); + return; + } + + // Only the GATT descriptor interface is supported. + if (interface_name != + bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidArgs, + "No such interface: '" + interface_name + "'."); + response_sender.Run(error_response.Pass()); + return; + } + + // Try to obtain the value from the delegate. We will construct the + // response in the success callback. + DCHECK(delegate_); + delegate_->GetDescriptorValue( + base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnGetAll, + weak_ptr_factory_.GetWeakPtr(), method_call, + response_sender), + base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnFailure, + weak_ptr_factory_.GetWeakPtr(), method_call, + response_sender)); + } + + // Called by dbus:: when a method is exported. + void OnExported(const std::string& interface_name, + const std::string& method_name, + bool success) { + LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "." + << method_name; + } + + // Called by the Delegate in response to a method to call to get all + // properties, in which the delegate has successfully returned the + // descriptor value. + void OnGetAll(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender, + const std::vector<uint8>& value) { + VLOG(2) << "Descriptor value obtained from delegate. Responding to " + << "GetAll."; + + scoped_ptr<dbus::Response> response = + dbus::Response::FromMethodCall(method_call); + dbus::MessageWriter writer(response.get()); + dbus::MessageWriter array_writer(NULL); + dbus::MessageWriter dict_entry_writer(NULL); + dbus::MessageWriter variant_writer(NULL); + + writer.OpenArray("{sv}", &array_writer); + + array_writer.OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString(bluetooth_gatt_descriptor::kUUIDProperty); + dict_entry_writer.AppendVariantOfString(uuid_); + array_writer.CloseContainer(&dict_entry_writer); + + array_writer.OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString( + bluetooth_gatt_descriptor::kCharacteristicProperty); + dict_entry_writer.AppendVariantOfObjectPath(characteristic_path_); + array_writer.CloseContainer(&dict_entry_writer); + + array_writer.OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString(bluetooth_gatt_descriptor::kValueProperty); + dict_entry_writer.OpenVariant("ay", &variant_writer); + variant_writer.AppendArrayOfBytes(value.data(), value.size()); + dict_entry_writer.CloseContainer(&variant_writer); + array_writer.CloseContainer(&dict_entry_writer); + + // TODO(armansito): Process "Permissions" property. + + writer.CloseContainer(&array_writer); + + response_sender.Run(response.Pass()); + } + + // Called by the Delegate in response to a successful method call to get the + // descriptor value. + void OnGet(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender, + const std::vector<uint8>& value) { + VLOG(2) << "Returning descriptor value obtained from delegate."; + scoped_ptr<dbus::Response> response = + dbus::Response::FromMethodCall(method_call); + dbus::MessageWriter writer(response.get()); + dbus::MessageWriter variant_writer(NULL); + + writer.OpenVariant("ay", &variant_writer); + variant_writer.AppendArrayOfBytes(value.data(), value.size()); + writer.CloseContainer(&variant_writer); + + response_sender.Run(response.Pass()); + } + + // Called by the Delegate in response to a successful method call to set the + // descriptor value. + void OnSet(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(2) << "Successfully set descriptor value. Return success."; + response_sender.Run(dbus::Response::FromMethodCall(method_call)); + } + + // Called by the Delegate in response to a failed method call to get or set + // the descriptor value. + void OnFailure(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(2) << "Failed to get/set descriptor value. Report error."; + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall( + method_call, kErrorFailed, "Failed to get/set descriptor value."); + response_sender.Run(error_response.Pass()); + } + + // Origin thread (i.e. the UI thread in production). + base::PlatformThreadId origin_thread_id_; + + // 128-bit descriptor UUID of this object. + std::string uuid_; + + // D-Bus bus object is exported on, not owned by this object and must + // outlive it. + dbus::Bus* bus_; + + // Incoming methods to get and set the "Value" property are passed on to the + // delegate and callbacks passed to generate a reply. |delegate_| is generally + // the object that owns this one and must outlive it. + Delegate* delegate_; + + // D-Bus object path of object we are exporting, kept so we can unregister + // again in our destructor. + dbus::ObjectPath object_path_; + + // Object path of the GATT characteristic that the exported descriptor belongs + // to. + dbus::ObjectPath characteristic_path_; + + // D-Bus object we are exporting, owned by this object. + scoped_refptr<dbus::ExportedObject> exported_object_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothGattDescriptorServiceProviderImpl> + weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothGattDescriptorServiceProviderImpl); +}; + +BluetoothGattDescriptorServiceProvider:: + BluetoothGattDescriptorServiceProvider() {} + +BluetoothGattDescriptorServiceProvider:: + ~BluetoothGattDescriptorServiceProvider() {} + +// static +BluetoothGattDescriptorServiceProvider* +BluetoothGattDescriptorServiceProvider::Create( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate, + const std::string& uuid, + const std::vector<std::string>& permissions, + const dbus::ObjectPath& characteristic_path) { + if (!bluez::BluezDBusManager::Get()->IsUsingStub()) { + return new BluetoothGattDescriptorServiceProviderImpl( + bus, object_path, delegate, uuid, permissions, characteristic_path); + } + return new FakeBluetoothGattDescriptorServiceProvider( + object_path, delegate, uuid, permissions, characteristic_path); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.h b/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.h new file mode 100644 index 0000000..e4925fff --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.h
@@ -0,0 +1,109 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "dbus/bus.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" + +namespace bluez { + +// BluetoothGattDescriptorServiceProvider is used to provide a D-Bus object that +// represents a local GATT characteristic descriptor that the Bluetooth daemon +// can communicate with. +// +// Instantiate with a chosen D-Bus object path, delegate, and other fields. +// The Bluetooth daemon communicates with a GATT descriptor using the +// standard DBus.Properties interface. While most properties of the GATT +// descriptor interface are read-only and don't change throughout the +// life-time of the object, the "Value" property is both writeable and its +// value can change. Both Get and Set operations performed on the "Value" +// property are delegated to the Delegate object, an instance of which is +// mandatory during initialization. In addition, a "SendValueChanged" method is +// provided, which emits a DBus.Properties.PropertyChanged signal for the +// "Value" property. +class DEVICE_BLUETOOTH_EXPORT BluetoothGattDescriptorServiceProvider { + public: + // Interface for reacting to GATT characteristic descriptor value requests. + class Delegate { + public: + virtual ~Delegate() {} + + // ValueCallback is used for methods that require a descriptor value + // to be returned. + typedef base::Callback<void(const std::vector<uint8>&)> ValueCallback; + + // ErrorCallback is used by methods to report failure. + typedef base::Closure ErrorCallback; + + // This method will be called when a remote device requests to read the + // value of the exported GATT descriptor. Invoke |callback| with a value + // to return that value to the requester. Invoke |error_callback| to report + // a failure to read the value. This can happen, for example, if the + // descriptor has no read permission set. Either callback should be + // invoked after a reasonable amount of time, since the request will time + // out if left pending for too long. + virtual void GetDescriptorValue(const ValueCallback& callback, + const ErrorCallback& error_callback) = 0; + + // This method will be called, when a remote device requests to write the + // value of the exported GATT descriptor. Invoke |callback| to report + // that the value was successfully written. Invoke |error_callback| to + // report a failure to write the value. This can happen, for example, if the + // descriptor has no write permission set. Either callback should be + // invoked after a reasonable amount of time, since the request will time + // out if left pending for too long. + // + // The delegate should use this method to perform any side-effects that may + // occur based on the set value and potentially send a property changed + // signal to notify the Bluetooth daemon that the value has changed. + virtual void SetDescriptorValue(const std::vector<uint8>& value, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + }; + + virtual ~BluetoothGattDescriptorServiceProvider(); + + // Send a PropertyChanged signal to notify the Bluetooth daemon that the value + // of the "Value" property has changed to |value|. + virtual void SendValueChanged(const std::vector<uint8>& value) = 0; + + // Creates the instance, where |bus| is the D-Bus bus connection to export + // the object onto, |uuid| is the 128-bit GATT descriptor UUID, |permissions| + // is the list of attribute permissions, |characteristic_path| is the object + // path of the exported GATT characteristic the descriptor belongs to, + // |object_path| is the object path that the descriptor should have, and + // |delegate| is the object that value Get/Set requests will be passed to and + // responses generated from. + // + // Object paths of GATT descriptors must be hierarchical to the path of the + // GATT characteristic they belong to. Hence, |object_path| must have + // |characteristic_path| as its prefix. Ownership of |delegate| is not taken, + // thus the delegate should outlive this instance. A delegate should handle + // only a single exported descriptor and own it. + static BluetoothGattDescriptorServiceProvider* Create( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate, + const std::string& uuid, + const std::vector<std::string>& permissions, + const dbus::ObjectPath& characteristic_path); + + protected: + BluetoothGattDescriptorServiceProvider(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothGattDescriptorServiceProvider); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_
diff --git a/device/bluetooth/dbus/bluetooth_gatt_manager_client.cc b/device/bluetooth/dbus/bluetooth_gatt_manager_client.cc new file mode 100644 index 0000000..7e471a5c --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_gatt_manager_client.cc
@@ -0,0 +1,129 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/bluetooth_gatt_manager_client.h" + +#include "base/bind.h" +#include "base/memory/weak_ptr.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_proxy.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +const char BluetoothGattManagerClient::kNoResponseError[] = + "org.chromium.Error.NoResponse"; + +// The BluetoothGattManagerClient implementation used in production. +class BluetoothGattManagerClientImpl : public BluetoothGattManagerClient { + public: + BluetoothGattManagerClientImpl() + : object_proxy_(NULL), weak_ptr_factory_(this) {} + + ~BluetoothGattManagerClientImpl() override {} + + // BluetoothGattManagerClient override. + void RegisterService(const dbus::ObjectPath& service_path, + const Options& options, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call( + bluetooth_gatt_manager::kBluetoothGattManagerInterface, + bluetooth_gatt_manager::kRegisterService); + + dbus::MessageWriter writer(&method_call); + writer.AppendObjectPath(service_path); + + // TODO(armansito): The parameters of the Options dictionary are undefined + // but the method signature still requires a value dictionary. Pass an + // empty dictionary and fill in the contents later once this is defined. + dbus::MessageWriter array_writer(NULL); + writer.OpenArray("{sv}", &array_writer); + writer.CloseContainer(&array_writer); + + DCHECK(object_proxy_); + object_proxy_->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothGattManagerClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothGattManagerClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothGattManagerClient override. + void UnregisterService(const dbus::ObjectPath& service_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call( + bluetooth_gatt_manager::kBluetoothGattManagerInterface, + bluetooth_gatt_manager::kUnregisterService); + + dbus::MessageWriter writer(&method_call); + writer.AppendObjectPath(service_path); + + DCHECK(object_proxy_); + object_proxy_->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothGattManagerClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothGattManagerClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + protected: + // chromeos::DBusClient override. + void Init(dbus::Bus* bus) override { + DCHECK(bus); + object_proxy_ = bus->GetObjectProxy( + bluetooth_gatt_manager::kBluetoothGattManagerServiceName, + dbus::ObjectPath( + bluetooth_gatt_manager::kBluetoothGattManagerInterface)); + } + + private: + // Called when a response for a successful method call is received. + void OnSuccess(const base::Closure& callback, dbus::Response* response) { + DCHECK(response); + callback.Run(); + } + + // Called when a response for a failed method call is received. + void OnError(const ErrorCallback& error_callback, + dbus::ErrorResponse* response) { + // Error response has optional error message argument. + std::string error_name; + std::string error_message; + if (response) { + dbus::MessageReader reader(response); + error_name = response->GetErrorName(); + reader.PopString(&error_message); + } else { + error_name = kNoResponseError; + } + error_callback.Run(error_name, error_message); + } + + // The proxy to the remote GATT manager object. + dbus::ObjectProxy* object_proxy_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothGattManagerClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothGattManagerClientImpl); +}; + +BluetoothGattManagerClient::BluetoothGattManagerClient() {} + +BluetoothGattManagerClient::~BluetoothGattManagerClient() {} + +// static +BluetoothGattManagerClient* BluetoothGattManagerClient::Create() { + return new BluetoothGattManagerClientImpl(); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_gatt_manager_client.h b/device/bluetooth/dbus/bluetooth_gatt_manager_client.h new file mode 100644 index 0000000..b735f77 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_gatt_manager_client.h
@@ -0,0 +1,74 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_MANAGER_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_MANAGER_CLIENT_H_ + +#include <string> + +#include "base/callback.h" +#include "base/macros.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluez_dbus_client.h" + +namespace bluez { + +// BluetoothGattManagerClient is used to communicate with the GATT Service +// manager object of the Bluetooth daemon. +class DEVICE_BLUETOOTH_EXPORT BluetoothGattManagerClient + : public BluezDBusClient { + public: + // Options used to register a GATT service hierarchy. + struct DEVICE_BLUETOOTH_EXPORT Options { + // TODO(armansito): This parameter is not yet clearly defined. Add fields + // later as we know more about how this will be used. + }; + + ~BluetoothGattManagerClient() override; + + // The ErrorCallback is used by GATT manager methods to indicate failure. It + // receives two arguments: the name of the error in |error_name| and an + // optional message in |error_message|. + typedef base::Callback<void(const std::string& error_name, + const std::string& error_message)> ErrorCallback; + + // Registers a GATT service implementation within the local process at the + // D-Bus object path |service_path| with the remote GATT manager. The local + // service must implement the GattService1 interface. Characteristic objects + // must be hierarchical to their service and must use the interface + // GattCharacteristic1. Similarly, characteristic descriptor objects must + // implement the GattDescriptor1 interface and must be hierarchical to their + // characteristic. In a successful invocation of RegisterService, the + // Bluetooth daemon will discover all objects in the registered hierarchy by + // using D-Bus Object Manager. Hence, the object paths and the interfaces in + // the registered hierarchy must comply with the BlueZ GATT D-Bus + // specification. + virtual void RegisterService(const dbus::ObjectPath& service_path, + const Options& options, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Unregisters the GATT service with the D-Bus object path |service_path| from + // the remote GATT manager. + virtual void UnregisterService(const dbus::ObjectPath& service_path, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Creates the instance. + static BluetoothGattManagerClient* Create(); + + // Constants used to indicate exceptional error conditions. + static const char kNoResponseError[]; + + protected: + BluetoothGattManagerClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothGattManagerClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_MANAGER_CLIENT_H_
diff --git a/device/bluetooth/dbus/bluetooth_gatt_service_client.cc b/device/bluetooth/dbus/bluetooth_gatt_service_client.cc new file mode 100644 index 0000000..dc3ef5a --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_gatt_service_client.cc
@@ -0,0 +1,143 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h" + +#include "base/bind.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "dbus/bus.h" +#include "dbus/object_manager.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +BluetoothGattServiceClient::Properties::Properties( + dbus::ObjectProxy* object_proxy, + const std::string& interface_name, + const PropertyChangedCallback& callback) + : dbus::PropertySet(object_proxy, interface_name, callback) { + RegisterProperty(bluetooth_gatt_service::kUUIDProperty, &uuid); + RegisterProperty(bluetooth_gatt_service::kIncludesProperty, &includes); + RegisterProperty(bluetooth_gatt_service::kDeviceProperty, &device); + RegisterProperty(bluetooth_gatt_service::kPrimaryProperty, &primary); + RegisterProperty(bluetooth_gatt_service::kCharacteristicsProperty, + &characteristics); +} + +BluetoothGattServiceClient::Properties::~Properties() {} + +// The BluetoothGattServiceClient implementation used in production. +class BluetoothGattServiceClientImpl : public BluetoothGattServiceClient, + public dbus::ObjectManager::Interface { + public: + BluetoothGattServiceClientImpl() + : object_manager_(NULL), weak_ptr_factory_(this) {} + + ~BluetoothGattServiceClientImpl() override { + object_manager_->UnregisterInterface( + bluetooth_gatt_service::kBluetoothGattServiceInterface); + } + + // BluetoothGattServiceClientImpl override. + void AddObserver(BluetoothGattServiceClient::Observer* observer) override { + DCHECK(observer); + observers_.AddObserver(observer); + } + + // BluetoothGattServiceClientImpl override. + void RemoveObserver(BluetoothGattServiceClient::Observer* observer) override { + DCHECK(observer); + observers_.RemoveObserver(observer); + } + + // BluetoothGattServiceClientImpl override. + std::vector<dbus::ObjectPath> GetServices() override { + DCHECK(object_manager_); + return object_manager_->GetObjectsWithInterface( + bluetooth_gatt_service::kBluetoothGattServiceInterface); + } + + // BluetoothGattServiceClientImpl override. + Properties* GetProperties(const dbus::ObjectPath& object_path) override { + DCHECK(object_manager_); + return static_cast<Properties*>(object_manager_->GetProperties( + object_path, bluetooth_gatt_service::kBluetoothGattServiceInterface)); + } + + // dbus::ObjectManager::Interface override. + dbus::PropertySet* CreateProperties( + dbus::ObjectProxy* object_proxy, + const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + Properties* properties = new Properties( + object_proxy, interface_name, + base::Bind(&BluetoothGattServiceClientImpl::OnPropertyChanged, + weak_ptr_factory_.GetWeakPtr(), object_path)); + return static_cast<dbus::PropertySet*>(properties); + } + + // dbus::ObjectManager::Interface override. + void ObjectAdded(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + VLOG(2) << "Remote GATT service added: " << object_path.value(); + FOR_EACH_OBSERVER(BluetoothGattServiceClient::Observer, observers_, + GattServiceAdded(object_path)); + } + + // dbus::ObjectManager::Interface override. + void ObjectRemoved(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + VLOG(2) << "Remote GATT service removed: " << object_path.value(); + FOR_EACH_OBSERVER(BluetoothGattServiceClient::Observer, observers_, + GattServiceRemoved(object_path)); + } + + protected: + // chromeos::DBusClient override. + void Init(dbus::Bus* bus) override { + object_manager_ = bus->GetObjectManager( + bluetooth_object_manager::kBluetoothObjectManagerServiceName, + dbus::ObjectPath( + bluetooth_object_manager::kBluetoothObjectManagerServicePath)); + object_manager_->RegisterInterface( + bluetooth_gatt_service::kBluetoothGattServiceInterface, this); + } + + private: + // Called by dbus::PropertySet when a property value is changed, either by + // result of a signal or response to a GetAll() or Get() call. Informs + // observers. + virtual void OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) { + VLOG(2) << "Remote GATT service property changed: " << object_path.value() + << ": " << property_name; + FOR_EACH_OBSERVER(BluetoothGattServiceClient::Observer, observers_, + GattServicePropertyChanged(object_path, property_name)); + } + + dbus::ObjectManager* object_manager_; + + // List of observers interested in event notifications from us. + base::ObserverList<BluetoothGattServiceClient::Observer> observers_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothGattServiceClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothGattServiceClientImpl); +}; + +BluetoothGattServiceClient::BluetoothGattServiceClient() {} + +BluetoothGattServiceClient::~BluetoothGattServiceClient() {} + +// static +BluetoothGattServiceClient* BluetoothGattServiceClient::Create() { + return new BluetoothGattServiceClientImpl(); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_gatt_service_client.h b/device/bluetooth/dbus/bluetooth_gatt_service_client.h new file mode 100644 index 0000000..641f505 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_gatt_service_client.h
@@ -0,0 +1,95 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_SERVICE_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_SERVICE_CLIENT_H_ + +#include <string> +#include <vector> + +#include "base/macros.h" +#include "dbus/object_path.h" +#include "dbus/property.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluez_dbus_client.h" + +namespace bluez { + +// BluetoothGattServiceClient is used to communicate with remote GATT service +// objects exposed by the Bluetooth daemon. +class DEVICE_BLUETOOTH_EXPORT BluetoothGattServiceClient + : public BluezDBusClient { + public: + // Structure of properties associated with GATT services. + struct Properties : public dbus::PropertySet { + // The 128-bit service UUID. [read-only] + dbus::Property<std::string> uuid; + + // Object path of the Bluetooth device that the GATT service belongs to. + dbus::Property<dbus::ObjectPath> device; + + // Whether or not this service is a primary service. + dbus::Property<bool> primary; + + // Array of object paths representing the characteristics of this service. + // [read-only] + dbus::Property<std::vector<dbus::ObjectPath>> characteristics; + + // Array of object paths representing the included services of this service. + // [read-only] + dbus::Property<std::vector<dbus::ObjectPath>> includes; + + Properties(dbus::ObjectProxy* object_proxy, + const std::string& interface_name, + const PropertyChangedCallback& callback); + ~Properties() override; + }; + + // Interface for observing changes from a remote GATT service. + class Observer { + public: + virtual ~Observer() {} + + // Called when the GATT service with object path |object_path| is added to + // the system. + virtual void GattServiceAdded(const dbus::ObjectPath& object_path) {} + + // Called when the GATT service with object path |object_path| is removed + // from the system. + virtual void GattServiceRemoved(const dbus::ObjectPath& object_path) {} + + // Called when the GATT service with object path |object_path| has a change + // in the value of the property named |property_name|. + virtual void GattServicePropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) {} + }; + + ~BluetoothGattServiceClient() override; + + // Adds and removes observers for events on all remote GATT services. Check + // the |object_path| parameter of observer methods to determine which GATT + // service is issuing the event. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Returns the list of GATT service object paths known to the system. + virtual std::vector<dbus::ObjectPath> GetServices() = 0; + + // Obtain the properties for the GATT service with object path |object_path|. + // Values should be copied if needed. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; + + // Creates the instance. + static BluetoothGattServiceClient* Create(); + + protected: + BluetoothGattServiceClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothGattServiceClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_SERVICE_CLIENT_H_
diff --git a/device/bluetooth/dbus/bluetooth_gatt_service_service_provider.cc b/device/bluetooth/dbus/bluetooth_gatt_service_service_provider.cc new file mode 100644 index 0000000..06b6827f --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_gatt_service_service_provider.cc
@@ -0,0 +1,272 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/bluetooth_gatt_service_service_provider.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/threading/platform_thread.h" +#include "dbus/exported_object.h" +#include "dbus/message.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { +namespace { +const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs"; +const char kErrorPropertyReadOnly[] = + "org.freedesktop.DBus.Error.PropertyReadOnly"; +} // namespace + +// The BluetoothGattServiceServiceProvider implementation used in production. +class BluetoothGattServiceServiceProviderImpl + : public BluetoothGattServiceServiceProvider { + public: + BluetoothGattServiceServiceProviderImpl( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + const std::string& uuid, + const std::vector<dbus::ObjectPath>& includes) + : origin_thread_id_(base::PlatformThread::CurrentId()), + uuid_(uuid), + includes_(includes), + bus_(bus), + object_path_(object_path), + weak_ptr_factory_(this) { + VLOG(1) << "Creating Bluetooth GATT service: " << object_path_.value() + << " UUID: " << uuid; + DCHECK(!uuid_.empty()); + DCHECK(object_path_.IsValid()); + DCHECK(bus_); + + exported_object_ = bus_->GetExportedObject(object_path_); + + exported_object_->ExportMethod( + dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet, + base::Bind(&BluetoothGattServiceServiceProviderImpl::Get, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesSet, + base::Bind(&BluetoothGattServiceServiceProviderImpl::Set, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll, + base::Bind(&BluetoothGattServiceServiceProviderImpl::GetAll, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + } + + ~BluetoothGattServiceServiceProviderImpl() override { + VLOG(1) << "Cleaning up Bluetooth GATT service: " << object_path_.value(); + bus_->UnregisterExportedObject(object_path_); + } + + private: + // Returns true if the current thread is on the origin thread. + bool OnOriginThread() { + return base::PlatformThread::CurrentId() == origin_thread_id_; + } + + // Called by dbus:: when the Bluetooth daemon fetches a single property of + // the service. + void Get(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(2) << "BluetoothGattServiceServiceProvider::Get: " + << object_path_.value(); + DCHECK(OnOriginThread()); + + dbus::MessageReader reader(method_call); + + std::string interface_name; + std::string property_name; + if (!reader.PopString(&interface_name) || + !reader.PopString(&property_name) || reader.HasMoreData()) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, + "Expected 'ss'."); + response_sender.Run(error_response.Pass()); + return; + } + + // Only the GATT service interface is allowed. + if (interface_name != + bluetooth_gatt_service::kBluetoothGattServiceInterface) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidArgs, + "No such interface: '" + interface_name + "'."); + response_sender.Run(error_response.Pass()); + return; + } + + // Return error if |property_name| is unknown. + if (property_name != bluetooth_gatt_service::kUUIDProperty && + property_name != bluetooth_gatt_service::kIncludesProperty) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidArgs, + "No such property: '" + property_name + "'."); + response_sender.Run(error_response.Pass()); + return; + } + + scoped_ptr<dbus::Response> response = + dbus::Response::FromMethodCall(method_call); + dbus::MessageWriter writer(response.get()); + dbus::MessageWriter variant_writer(NULL); + + if (property_name == bluetooth_gatt_service::kUUIDProperty) { + writer.OpenVariant("s", &variant_writer); + variant_writer.AppendString(uuid_); + writer.CloseContainer(&variant_writer); + } else { + writer.OpenVariant("ao", &variant_writer); + variant_writer.AppendArrayOfObjectPaths(includes_); + writer.CloseContainer(&variant_writer); + } + + response_sender.Run(response.Pass()); + } + + // Called by dbus:: when the Bluetooth daemon sets a single property of the + // service. + void Set(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(2) << "BluetoothGattServiceServiceProvider::Set: " + << object_path_.value(); + DCHECK(OnOriginThread()); + + // All of the properties on this interface are read-only, so just return + // error. + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall(method_call, kErrorPropertyReadOnly, + "All properties are read-only."); + response_sender.Run(error_response.Pass()); + } + + // Called by dbus:: when the Bluetooth daemon fetches all properties of the + // service. + void GetAll(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(2) << "BluetoothGattServiceServiceProvider::GetAll: " + << object_path_.value(); + DCHECK(OnOriginThread()); + + dbus::MessageReader reader(method_call); + + std::string interface_name; + if (!reader.PopString(&interface_name) || reader.HasMoreData()) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, + "Expected 's'."); + response_sender.Run(error_response.Pass()); + return; + } + + // Only the GATT service interface is allowed. + if (interface_name != + bluetooth_gatt_service::kBluetoothGattServiceInterface) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidArgs, + "No such interface: '" + interface_name + "'."); + response_sender.Run(error_response.Pass()); + return; + } + + scoped_ptr<dbus::Response> response = + dbus::Response::FromMethodCall(method_call); + dbus::MessageWriter writer(response.get()); + dbus::MessageWriter array_writer(NULL); + dbus::MessageWriter dict_entry_writer(NULL); + dbus::MessageWriter variant_writer(NULL); + + writer.OpenArray("{sv}", &array_writer); + + array_writer.OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString(bluetooth_gatt_service::kUUIDProperty); + dict_entry_writer.AppendVariantOfString(uuid_); + array_writer.CloseContainer(&dict_entry_writer); + + array_writer.OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString(bluetooth_gatt_service::kIncludesProperty); + dict_entry_writer.OpenVariant("ao", &variant_writer); + variant_writer.AppendArrayOfObjectPaths(includes_); + dict_entry_writer.CloseContainer(&variant_writer); + array_writer.CloseContainer(&dict_entry_writer); + + writer.CloseContainer(&array_writer); + + response_sender.Run(response.Pass()); + } + + // Called by dbus:: when a method is exported. + void OnExported(const std::string& interface_name, + const std::string& method_name, + bool success) { + LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "." + << method_name; + } + + // Origin thread (i.e. the UI thread in production). + base::PlatformThreadId origin_thread_id_; + + // 128-bit service UUID of this object. + std::string uuid_; + + // List of object paths that represent other exported GATT services that are + // included from this service. + std::vector<dbus::ObjectPath> includes_; + + // D-Bus bus object is exported on, not owned by this object and must + // outlive it. + dbus::Bus* bus_; + + // D-Bus object path of object we are exporting, kept so we can unregister + // again in our destructor. + dbus::ObjectPath object_path_; + + // D-Bus object we are exporting, owned by this object. + scoped_refptr<dbus::ExportedObject> exported_object_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothGattServiceServiceProviderImpl> + weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothGattServiceServiceProviderImpl); +}; + +BluetoothGattServiceServiceProvider::BluetoothGattServiceServiceProvider() {} + +BluetoothGattServiceServiceProvider::~BluetoothGattServiceServiceProvider() {} + +// static +BluetoothGattServiceServiceProvider* +BluetoothGattServiceServiceProvider::Create( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + const std::string& uuid, + const std::vector<dbus::ObjectPath>& includes) { + if (!bluez::BluezDBusManager::Get()->IsUsingStub()) { + return new BluetoothGattServiceServiceProviderImpl(bus, object_path, uuid, + includes); + } + return new FakeBluetoothGattServiceServiceProvider(object_path, uuid, + includes); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_gatt_service_service_provider.h b/device/bluetooth/dbus/bluetooth_gatt_service_service_provider.h new file mode 100644 index 0000000..cedec1e1 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_gatt_service_service_provider.h
@@ -0,0 +1,53 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_ + +#include <string> +#include <vector> + +#include "base/macros.h" +#include "dbus/bus.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" + +namespace bluez { + +// BluetoothGattServiceServiceProvider is used to provide a D-Bus object that +// the Bluetooth daemon can communicate with to register GATT service +// hierarchies. +// +// Instantiate with a chosen D-Bus object path (that conforms to the BlueZ GATT +// service specification), service UUID, and the list of included services, and +// pass the D-Bus object path as the |service_path| argument to the +// chromeos::BluetoothGattManagerClient::RegisterService method. Make sure to +// create characteristic and descriptor objects using the appropriate service +// providers before registering a GATT service with the Bluetooth daemon. +class DEVICE_BLUETOOTH_EXPORT BluetoothGattServiceServiceProvider { + public: + virtual ~BluetoothGattServiceServiceProvider(); + + // Creates the instance where |bus| is the D-Bus bus connection to export the + // object onto, |object_path| is the object path that it should have, |uuid| + // is the 128-bit GATT service UUID, and |includes| are a list of object paths + // belonging to other exported GATT services that are included by the GATT + // service being created. Make sure that all included services have been + // exported before registering a GATT services with the GATT manager. + static BluetoothGattServiceServiceProvider* Create( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + const std::string& uuid, + const std::vector<dbus::ObjectPath>& includes); + + protected: + BluetoothGattServiceServiceProvider(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothGattServiceServiceProvider); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_
diff --git a/device/bluetooth/dbus/bluetooth_input_client.cc b/device/bluetooth/dbus/bluetooth_input_client.cc new file mode 100644 index 0000000..42542a8 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_input_client.cc
@@ -0,0 +1,128 @@ +// Copyright 2013 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 "device/bluetooth/dbus/bluetooth_input_client.h" + +#include <map> + +#include "base/logging.h" +#include "base/stl_util.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_manager.h" +#include "dbus/object_proxy.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +BluetoothInputClient::Properties::Properties( + dbus::ObjectProxy* object_proxy, + const std::string& interface_name, + const PropertyChangedCallback& callback) + : dbus::PropertySet(object_proxy, interface_name, callback) { + RegisterProperty(bluetooth_input::kReconnectModeProperty, &reconnect_mode); +} + +BluetoothInputClient::Properties::~Properties() {} + +// The BluetoothInputClient implementation used in production. +class BluetoothInputClientImpl : public BluetoothInputClient, + public dbus::ObjectManager::Interface { + public: + BluetoothInputClientImpl() : object_manager_(NULL), weak_ptr_factory_(this) {} + + ~BluetoothInputClientImpl() override { + object_manager_->UnregisterInterface( + bluetooth_input::kBluetoothInputInterface); + } + + // BluetoothInputClient override. + void AddObserver(BluetoothInputClient::Observer* observer) override { + DCHECK(observer); + observers_.AddObserver(observer); + } + + // BluetoothInputClient override. + void RemoveObserver(BluetoothInputClient::Observer* observer) override { + DCHECK(observer); + observers_.RemoveObserver(observer); + } + + // dbus::ObjectManager::Interface override. + dbus::PropertySet* CreateProperties( + dbus::ObjectProxy* object_proxy, + const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + Properties* properties = + new Properties(object_proxy, interface_name, + base::Bind(&BluetoothInputClientImpl::OnPropertyChanged, + weak_ptr_factory_.GetWeakPtr(), object_path)); + return static_cast<dbus::PropertySet*>(properties); + } + + // BluetoothInputClient override. + Properties* GetProperties(const dbus::ObjectPath& object_path) override { + return static_cast<Properties*>(object_manager_->GetProperties( + object_path, bluetooth_input::kBluetoothInputInterface)); + } + + protected: + void Init(dbus::Bus* bus) override { + object_manager_ = bus->GetObjectManager( + bluetooth_object_manager::kBluetoothObjectManagerServiceName, + dbus::ObjectPath( + bluetooth_object_manager::kBluetoothObjectManagerServicePath)); + object_manager_->RegisterInterface( + bluetooth_input::kBluetoothInputInterface, this); + } + + private: + // Called by dbus::ObjectManager when an object with the input interface + // is created. Informs observers. + void ObjectAdded(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + FOR_EACH_OBSERVER(BluetoothInputClient::Observer, observers_, + InputAdded(object_path)); + } + + // Called by dbus::ObjectManager when an object with the input interface + // is removed. Informs observers. + void ObjectRemoved(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + FOR_EACH_OBSERVER(BluetoothInputClient::Observer, observers_, + InputRemoved(object_path)); + } + + // Called by BluetoothPropertySet when a property value is changed, + // either by result of a signal or response to a GetAll() or Get() + // call. Informs observers. + void OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) { + FOR_EACH_OBSERVER(BluetoothInputClient::Observer, observers_, + InputPropertyChanged(object_path, property_name)); + } + + dbus::ObjectManager* object_manager_; + + // List of observers interested in event notifications from us. + base::ObserverList<BluetoothInputClient::Observer> observers_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothInputClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothInputClientImpl); +}; + +BluetoothInputClient::BluetoothInputClient() {} + +BluetoothInputClient::~BluetoothInputClient() {} + +BluetoothInputClient* BluetoothInputClient::Create() { + return new BluetoothInputClientImpl(); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_input_client.h b/device/bluetooth/dbus/bluetooth_input_client.h new file mode 100644 index 0000000..829e94ca --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_input_client.h
@@ -0,0 +1,82 @@ +// Copyright 2013 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 DEVICE_BLUETOOTH_DBUS_BLUETOOTH_INPUT_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_INPUT_CLIENT_H_ + +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/observer_list.h" +#include "dbus/object_path.h" +#include "dbus/property.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluez_dbus_client.h" + +namespace bluez { + +// BluetoothInputClient is used to communicate with objects representing +// Bluetooth Input (HID) devices. +class DEVICE_BLUETOOTH_EXPORT BluetoothInputClient : public BluezDBusClient { + public: + // Structure of properties associated with bluetooth input devices. + struct Properties : public dbus::PropertySet { + // The Bluetooth input device reconnect mode. Read-only. + dbus::Property<std::string> reconnect_mode; + + Properties(dbus::ObjectProxy* object_proxy, + const std::string& interface_name, + const PropertyChangedCallback& callback); + ~Properties() override; + }; + + // Interface for observing changes from a remote bluetooth input device. + class Observer { + public: + virtual ~Observer() {} + + // Called when the remote device with object path |object_path| implementing + // the Input interface is added to the set of known devices or an already + // known device implements the Input interface. + virtual void InputAdded(const dbus::ObjectPath& object_path) {} + + // Called when the remote device with object path |object_path| is removed + // from the set of known devices or does not implement the Input interface + // anymore. + virtual void InputRemoved(const dbus::ObjectPath& object_path) {} + + // Called when the device with object path |object_path| has a + // change in value of the property named |property_name| of its Input + // interface. + virtual void InputPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) {} + }; + + ~BluetoothInputClient() override; + + // Adds and removes observers for events on all remote bluetooth input + // devices. Check the |object_path| parameter of observer methods to + // determine which device is issuing the event. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Obtain the properties for the device with object path |object_path|, + // any values should be copied if needed. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; + + // Creates the instance. + static BluetoothInputClient* Create(); + + protected: + BluetoothInputClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothInputClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_INPUT_CLIENT_H_
diff --git a/device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.cc b/device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.cc new file mode 100644 index 0000000..e981124 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.cc
@@ -0,0 +1,426 @@ +// Copyright 2015 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 "device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/stl_util.h" +#include "base/threading/platform_thread.h" +#include "dbus/exported_object.h" +#include "dbus/message.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +namespace { +const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs"; +} // namespace + +// The BluetoothAdvertisementServiceProvider implementation used in production. +class BluetoothAdvertisementServiceProviderImpl + : public BluetoothLEAdvertisementServiceProvider { + public: + BluetoothAdvertisementServiceProviderImpl( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate, + AdvertisementType type, + scoped_ptr<UUIDList> service_uuids, + scoped_ptr<ManufacturerData> manufacturer_data, + scoped_ptr<UUIDList> solicit_uuids, + scoped_ptr<ServiceData> service_data) + : origin_thread_id_(base::PlatformThread::CurrentId()), + bus_(bus), + delegate_(delegate), + type_(type), + service_uuids_(service_uuids.Pass()), + manufacturer_data_(manufacturer_data.Pass()), + solicit_uuids_(solicit_uuids.Pass()), + service_data_(service_data.Pass()), + weak_ptr_factory_(this) { + DCHECK(bus); + DCHECK(delegate); + + VLOG(1) << "Creating Bluetooth Advertisement: " << object_path_.value(); + + object_path_ = object_path; + exported_object_ = bus_->GetExportedObject(object_path_); + + // Export Bluetooth Advertisement interface methods. + exported_object_->ExportMethod( + bluetooth_advertisement::kBluetoothAdvertisementInterface, + bluetooth_advertisement::kRelease, + base::Bind(&BluetoothAdvertisementServiceProviderImpl::Release, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAdvertisementServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + // Export dbus property methods. + exported_object_->ExportMethod( + dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet, + base::Bind(&BluetoothAdvertisementServiceProviderImpl::Get, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAdvertisementServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll, + base::Bind(&BluetoothAdvertisementServiceProviderImpl::GetAll, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAdvertisementServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + } + + ~BluetoothAdvertisementServiceProviderImpl() override { + VLOG(1) << "Cleaning up Bluetooth Advertisement: " << object_path_.value(); + + // Unregister the object path so we can reuse with a new agent. + bus_->UnregisterExportedObject(object_path_); + } + + private: + // Returns true if the current thread is on the origin thread. + bool OnOriginThread() { + return base::PlatformThread::CurrentId() == origin_thread_id_; + } + + // Called by dbus:: when this advertisement is unregistered from the Bluetooth + // daemon, generally by our request. + void Release(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + delegate_->Released(); + } + + // Called by dbus:: when the Bluetooth daemon fetches a single property of + // the descriptor. + void Get(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(2) << "BluetoothAdvertisementServiceProvider::Get: " + << object_path_.value(); + DCHECK(OnOriginThread()); + + dbus::MessageReader reader(method_call); + + std::string interface_name; + std::string property_name; + if (!reader.PopString(&interface_name) || + !reader.PopString(&property_name) || reader.HasMoreData()) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, + "Expected 'ss'."); + response_sender.Run(error_response.Pass()); + return; + } + + // Only the advertisement interface is supported. + if (interface_name != + bluetooth_advertisement::kBluetoothAdvertisementInterface) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidArgs, + "No such interface: '" + interface_name + "'."); + response_sender.Run(error_response.Pass()); + return; + } + + scoped_ptr<dbus::Response> response = + dbus::Response::FromMethodCall(method_call); + dbus::MessageWriter writer(response.get()); + dbus::MessageWriter variant_writer(NULL); + + if (property_name == bluetooth_advertisement::kTypeProperty) { + writer.OpenVariant("s", &variant_writer); + if (type_ == ADVERTISEMENT_TYPE_BROADCAST) { + variant_writer.AppendString("broadcast"); + } else { + variant_writer.AppendString("peripheral"); + } + } else if ((property_name == + bluetooth_advertisement::kServiceUUIDsProperty) && + service_uuids_) { + writer.OpenVariant("as", &variant_writer); + variant_writer.AppendArrayOfStrings(*service_uuids_); + } else if ((property_name == + bluetooth_advertisement::kSolicitUUIDsProperty) && + solicit_uuids_) { + writer.OpenVariant("as", &variant_writer); + variant_writer.AppendArrayOfStrings(*solicit_uuids_); + } else if ((property_name == + bluetooth_advertisement::kManufacturerDataProperty) && + manufacturer_data_) { + writer.OpenVariant("o", &variant_writer); + AppendManufacturerDataVariant(&variant_writer); + } else if ((property_name == + bluetooth_advertisement::kServiceDataProperty) && + service_data_) { + writer.OpenVariant("o", &variant_writer); + AppendServiceDataVariant(&variant_writer); + } else { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidArgs, + "No such property: '" + property_name + "'."); + response_sender.Run(error_response.Pass()); + } + + writer.CloseContainer(&variant_writer); + response_sender.Run(response.Pass()); + } + + // Called by dbus:: when the Bluetooth daemon fetches all properties of the + // descriptor. + void GetAll(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(2) << "BluetoothAdvertisementServiceProvider::GetAll: " + << object_path_.value(); + DCHECK(OnOriginThread()); + + dbus::MessageReader reader(method_call); + + std::string interface_name; + if (!reader.PopString(&interface_name) || reader.HasMoreData()) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs, + "Expected 's'."); + response_sender.Run(error_response.Pass()); + return; + } + + // Only the advertisement interface is supported. + if (interface_name != + bluetooth_advertisement::kBluetoothAdvertisementInterface) { + scoped_ptr<dbus::ErrorResponse> error_response = + dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidArgs, + "No such interface: '" + interface_name + "'."); + response_sender.Run(error_response.Pass()); + return; + } + + response_sender.Run(CreateGetAllResponse(method_call).Pass()); + } + + // Called by dbus:: when a method is exported. + void OnExported(const std::string& interface_name, + const std::string& method_name, + bool success) { + LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "." + << method_name; + } + + // Helper for populating the DBus response with the advertisement data. + scoped_ptr<dbus::Response> CreateGetAllResponse( + dbus::MethodCall* method_call) { + VLOG(2) << "Descriptor value obtained from delegate. Responding to " + << "GetAll."; + + scoped_ptr<dbus::Response> response = + dbus::Response::FromMethodCall(method_call); + + dbus::MessageWriter writer(response.get()); + dbus::MessageWriter array_writer(NULL); + + writer.OpenArray("{sv}", &array_writer); + + AppendType(&array_writer); + AppendServiceUUIDs(&array_writer); + AppendManufacturerData(&array_writer); + AppendSolicitUUIDs(&array_writer); + AppendServiceData(&array_writer); + + writer.CloseContainer(&array_writer); + return response; + } + + // Called by the Delegate in response to a successful method call to get the + // descriptor value. + void OnGet(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender, + const std::vector<uint8>& value) { + VLOG(2) << "Returning descriptor value obtained from delegate."; + scoped_ptr<dbus::Response> response = + dbus::Response::FromMethodCall(method_call); + dbus::MessageWriter writer(response.get()); + dbus::MessageWriter variant_writer(NULL); + + writer.OpenVariant("ay", &variant_writer); + variant_writer.AppendArrayOfBytes(value.data(), value.size()); + writer.CloseContainer(&variant_writer); + + response_sender.Run(response.Pass()); + } + + void AppendArrayVariantOfStrings(dbus::MessageWriter* dict_writer, + const UUIDList& strings) { + dbus::MessageWriter strings_array_variant(nullptr); + dict_writer->OpenVariant("as", &strings_array_variant); + strings_array_variant.AppendArrayOfStrings(strings); + dict_writer->CloseContainer(&strings_array_variant); + } + + void AppendType(dbus::MessageWriter* array_writer) { + dbus::MessageWriter dict_entry_writer(NULL); + array_writer->OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString(bluetooth_advertisement::kTypeProperty); + if (type_ == ADVERTISEMENT_TYPE_BROADCAST) { + dict_entry_writer.AppendVariantOfString("broadcast"); + } else { + dict_entry_writer.AppendVariantOfString("peripheral"); + } + array_writer->CloseContainer(&dict_entry_writer); + } + + void AppendServiceUUIDs(dbus::MessageWriter* array_writer) { + if (!service_uuids_) + return; + dbus::MessageWriter dict_entry_writer(NULL); + array_writer->OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString( + bluetooth_advertisement::kServiceUUIDsProperty); + AppendArrayVariantOfStrings(&dict_entry_writer, *service_uuids_); + array_writer->CloseContainer(&dict_entry_writer); + } + + void AppendManufacturerData(dbus::MessageWriter* array_writer) { + if (!manufacturer_data_) + return; + dbus::MessageWriter dict_entry_writer(NULL); + array_writer->OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString( + bluetooth_advertisement::kManufacturerDataProperty); + dbus::MessageWriter variant_writer(NULL); + dict_entry_writer.OpenVariant("a{qay}", &variant_writer); + AppendManufacturerDataVariant(&variant_writer); + dict_entry_writer.CloseContainer(&variant_writer); + array_writer->CloseContainer(&dict_entry_writer); + } + + void AppendSolicitUUIDs(dbus::MessageWriter* array_writer) { + if (!solicit_uuids_) + return; + dbus::MessageWriter dict_entry_writer(NULL); + array_writer->OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString( + bluetooth_advertisement::kSolicitUUIDsProperty); + AppendArrayVariantOfStrings(&dict_entry_writer, *solicit_uuids_); + array_writer->CloseContainer(&dict_entry_writer); + } + + void AppendServiceData(dbus::MessageWriter* array_writer) { + if (!service_data_) + return; + dbus::MessageWriter dict_entry_writer(NULL); + array_writer->OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString( + bluetooth_advertisement::kServiceDataProperty); + dbus::MessageWriter variant_writer(NULL); + dict_entry_writer.OpenVariant("a{say}", &variant_writer); + AppendServiceDataVariant(&variant_writer); + dict_entry_writer.CloseContainer(&variant_writer); + array_writer->CloseContainer(&dict_entry_writer); + } + + void AppendManufacturerDataVariant(dbus::MessageWriter* writer) { + DCHECK(manufacturer_data_); + dbus::MessageWriter array_writer(NULL); + writer->OpenArray("{qay}", &array_writer); + for (const auto& m : *manufacturer_data_) { + dbus::MessageWriter entry_writer(NULL); + + array_writer.OpenDictEntry(&entry_writer); + + entry_writer.AppendUint32(m.first); + entry_writer.AppendArrayOfBytes(vector_as_array(&m.second), + m.second.size()); + + array_writer.CloseContainer(&entry_writer); + } + writer->CloseContainer(&array_writer); + } + + void AppendServiceDataVariant(dbus::MessageWriter* writer) { + DCHECK(service_data_); + dbus::MessageWriter array_writer(NULL); + writer->OpenArray("{say}", &array_writer); + for (const auto& m : *service_data_) { + dbus::MessageWriter entry_writer(NULL); + + array_writer.OpenDictEntry(&entry_writer); + + entry_writer.AppendString(m.first); + entry_writer.AppendArrayOfBytes(vector_as_array(&m.second), + m.second.size()); + + array_writer.CloseContainer(&entry_writer); + } + writer->CloseContainer(&array_writer); + } + + // Origin thread (i.e. the UI thread in production). + base::PlatformThreadId origin_thread_id_; + + // D-Bus bus object is exported on, not owned by this object and must + // outlive it. + dbus::Bus* bus_; + + // All incoming method calls are passed on to the Delegate and a callback + // passed to generate the reply. |delegate_| is generally the object that + // owns this one, and must outlive it. + Delegate* delegate_; + + // Advertisement data that needs to be provided to BlueZ when requested. + AdvertisementType type_; + scoped_ptr<UUIDList> service_uuids_; + scoped_ptr<ManufacturerData> manufacturer_data_; + scoped_ptr<UUIDList> solicit_uuids_; + scoped_ptr<ServiceData> service_data_; + + // D-Bus object we are exporting, owned by this object. + scoped_refptr<dbus::ExportedObject> exported_object_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothAdvertisementServiceProviderImpl> + weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothAdvertisementServiceProviderImpl); +}; + +BluetoothLEAdvertisementServiceProvider:: + BluetoothLEAdvertisementServiceProvider() {} + +BluetoothLEAdvertisementServiceProvider:: + ~BluetoothLEAdvertisementServiceProvider() {} + +// static +scoped_ptr<BluetoothLEAdvertisementServiceProvider> +BluetoothLEAdvertisementServiceProvider::Create( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate, + AdvertisementType type, + scoped_ptr<UUIDList> service_uuids, + scoped_ptr<ManufacturerData> manufacturer_data, + scoped_ptr<UUIDList> solicit_uuids, + scoped_ptr<ServiceData> service_data) { + if (!bluez::BluezDBusManager::Get()->IsUsingStub()) { + return make_scoped_ptr(new BluetoothAdvertisementServiceProviderImpl( + bus, object_path, delegate, type, service_uuids.Pass(), + manufacturer_data.Pass(), solicit_uuids.Pass(), service_data.Pass())); + } else { + return make_scoped_ptr( + new FakeBluetoothLEAdvertisementServiceProvider(object_path, delegate)); + } +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.h b/device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.h new file mode 100644 index 0000000..8f4692f8 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.h
@@ -0,0 +1,82 @@ +// Copyright 2015 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 DEVICE_BLUETOOTH_DBUS_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_ + +#include <stdint.h> + +#include <map> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" +#include "dbus/bus.h" +#include "dbus/file_descriptor.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" + +namespace bluez { + +// BluetoothAdvertisementServiceProvider is used to provide a D-Bus object that +// the Bluetooth daemon can communicate with to advertise data. +class DEVICE_BLUETOOTH_EXPORT BluetoothLEAdvertisementServiceProvider { + public: + using UUIDList = std::vector<std::string>; + using ManufacturerData = std::map<uint16_t, std::vector<uint8_t>>; + using ServiceData = std::map<std::string, std::vector<uint8_t>>; + + // Type of advertisement. + enum AdvertisementType { + ADVERTISEMENT_TYPE_BROADCAST, + ADVERTISEMENT_TYPE_PERIPHERAL + }; + + // Interface for reacting to advertisement changes. + class Delegate { + public: + virtual ~Delegate() {} + + // This method will be called when the advertisement is unregistered from + // the Bluetooth daemon, generally at shutdown or if the adapter goes away. + // It may be used to perform cleanup tasks. This corresponds to the + // org.bluez.LEAdvertisement1.Release method and is renamed to avoid a + // conflict with base::Refcounted<T>. + virtual void Released() = 0; + }; + + virtual ~BluetoothLEAdvertisementServiceProvider(); + + const dbus::ObjectPath& object_path() { return object_path_; } + + // Creates the instance where |bus| is the D-Bus bus connection to export + // the object onto, |object_path| is the object path that it should have + // and |delegate| is the object to which all method calls will be passed + // and responses generated from. + static scoped_ptr<BluetoothLEAdvertisementServiceProvider> Create( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate, + AdvertisementType type, + scoped_ptr<UUIDList> service_uuids, + scoped_ptr<ManufacturerData> manufacturer_data, + scoped_ptr<UUIDList> solicit_uuids, + scoped_ptr<ServiceData> service_data); + + protected: + BluetoothLEAdvertisementServiceProvider(); + + // D-Bus object path of object we are exporting, kept so we can unregister + // again in our destructor. + dbus::ObjectPath object_path_; + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothLEAdvertisementServiceProvider); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_
diff --git a/device/bluetooth/dbus/bluetooth_le_advertising_manager_client.cc b/device/bluetooth/dbus/bluetooth_le_advertising_manager_client.cc new file mode 100644 index 0000000..3c934e63 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_le_advertising_manager_client.cc
@@ -0,0 +1,187 @@ +// Copyright 2015 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 "device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/observer_list.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_manager.h" +#include "dbus/object_proxy.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +const char BluetoothLEAdvertisingManagerClient::kNoResponseError[] = + "org.chromium.Error.NoResponse"; + +// The BluetoothAdvertisementManagerClient implementation used in production. +class BluetoothAdvertisementManagerClientImpl + : public BluetoothLEAdvertisingManagerClient, + public dbus::ObjectManager::Interface { + public: + BluetoothAdvertisementManagerClientImpl() + : object_manager_(NULL), weak_ptr_factory_(this) {} + + ~BluetoothAdvertisementManagerClientImpl() override { + if (object_manager_) { + object_manager_->UnregisterInterface( + bluetooth_advertising_manager::kBluetoothAdvertisingManagerInterface); + } + } + + // BluetoothAdapterClient override. + void AddObserver( + BluetoothLEAdvertisingManagerClient::Observer* observer) override { + DCHECK(observer); + observers_.AddObserver(observer); + } + + // BluetoothAdapterClient override. + void RemoveObserver( + BluetoothLEAdvertisingManagerClient::Observer* observer) override { + DCHECK(observer); + observers_.RemoveObserver(observer); + } + + // dbus::ObjectManager::Interface override. + dbus::PropertySet* CreateProperties( + dbus::ObjectProxy* object_proxy, + const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + return new dbus::PropertySet(object_proxy, interface_name, + dbus::PropertySet::PropertyChangedCallback()); + } + + // BluetoothAdvertisementManagerClient override. + void RegisterAdvertisement(const dbus::ObjectPath& manager_object_path, + const dbus::ObjectPath& advertisement_object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call( + bluetooth_advertising_manager::kBluetoothAdvertisingManagerInterface, + bluetooth_advertising_manager::kRegisterAdvertisement); + + dbus::MessageWriter writer(&method_call); + writer.AppendObjectPath(advertisement_object_path); + + // Empty dictionary for options. + dbus::MessageWriter array_writer(NULL); + writer.OpenArray("{sv}", &array_writer); + writer.CloseContainer(&array_writer); + + DCHECK(object_manager_); + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(manager_object_path); + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAdvertisementManagerClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothAdvertisementManagerClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothAdvertisementManagerClient override. + void UnregisterAdvertisement( + const dbus::ObjectPath& manager_object_path, + const dbus::ObjectPath& advertisement_object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call( + bluetooth_advertising_manager::kBluetoothAdvertisingManagerInterface, + bluetooth_advertising_manager::kUnregisterAdvertisement); + + dbus::MessageWriter writer(&method_call); + writer.AppendObjectPath(advertisement_object_path); + + DCHECK(object_manager_); + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(manager_object_path); + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAdvertisementManagerClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothAdvertisementManagerClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + protected: + void Init(dbus::Bus* bus) override { + DCHECK(bus); + object_manager_ = bus->GetObjectManager( + bluetooth_object_manager::kBluetoothObjectManagerServiceName, + dbus::ObjectPath( + bluetooth_object_manager::kBluetoothObjectManagerServicePath)); + object_manager_->RegisterInterface( + bluetooth_advertising_manager::kBluetoothAdvertisingManagerInterface, + this); + } + + private: + // Called by dbus::ObjectManager when an object with the advertising manager + // interface is created. Informs observers. + void ObjectAdded(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + FOR_EACH_OBSERVER(BluetoothLEAdvertisingManagerClient::Observer, observers_, + AdvertisingManagerAdded(object_path)); + } + + // Called by dbus::ObjectManager when an object with the advertising manager + // interface is removed. Informs observers. + void ObjectRemoved(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + FOR_EACH_OBSERVER(BluetoothLEAdvertisingManagerClient::Observer, observers_, + AdvertisingManagerRemoved(object_path)); + } + + // Called when a response for successful method call is received. + void OnSuccess(const base::Closure& callback, dbus::Response* response) { + DCHECK(response); + callback.Run(); + } + + // Called when a response for a failed method call is received. + void OnError(const ErrorCallback& error_callback, + dbus::ErrorResponse* response) { + // Error response has optional error message argument. + std::string error_name; + std::string error_message; + if (response) { + dbus::MessageReader reader(response); + error_name = response->GetErrorName(); + reader.PopString(&error_message); + } else { + error_name = kNoResponseError; + error_message = ""; + } + error_callback.Run(error_name, error_message); + } + + dbus::ObjectManager* object_manager_; + + // List of observers interested in event notifications from us. + base::ObserverList<BluetoothLEAdvertisingManagerClient::Observer> observers_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothAdvertisementManagerClientImpl> + weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothAdvertisementManagerClientImpl); +}; + +BluetoothLEAdvertisingManagerClient::BluetoothLEAdvertisingManagerClient() {} + +BluetoothLEAdvertisingManagerClient::~BluetoothLEAdvertisingManagerClient() {} + +BluetoothLEAdvertisingManagerClient* +BluetoothLEAdvertisingManagerClient::Create() { + return new BluetoothAdvertisementManagerClientImpl(); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h b/device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h new file mode 100644 index 0000000..73aa9ed --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h
@@ -0,0 +1,85 @@ +// Copyright 2015 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 DEVICE_BLUETOOTH_DBUS_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_ + +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/values.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluez_dbus_client.h" + +namespace bluez { + +// BluetoothAdvertisingManagerClient is used to communicate with the advertising +// manager object of the BlueZ daemon. +class DEVICE_BLUETOOTH_EXPORT BluetoothLEAdvertisingManagerClient + : public BluezDBusClient { + public: + // Interface for observing changes to advertising managers. + class Observer { + public: + virtual ~Observer() {} + + // Called when an advertising manager with object path |object_path| is + // added to the system. + virtual void AdvertisingManagerAdded(const dbus::ObjectPath& object_path) {} + + // Called when an advertising manager with object path |object_path| is + // removed from the system. + virtual void AdvertisingManagerRemoved( + const dbus::ObjectPath& object_path) {} + }; + + ~BluetoothLEAdvertisingManagerClient() override; + + // Adds and removes observers for events which change the advertising + // managers on the system. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // The ErrorCallback is used by advertising manager methods to indicate + // failure. It receives two arguments: the name of the error in |error_name| + // and an optional message in |error_message|. + using ErrorCallback = base::Callback<void(const std::string& error_name, + const std::string& error_message)>; + + // Registers an advertisement with the DBus object path + // |advertisement_object_path| with BlueZ's advertising manager. + virtual void RegisterAdvertisement( + const dbus::ObjectPath& manager_object_path, + const dbus::ObjectPath& advertisement_object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Unregisters an advertisement with the DBus object path + // |advertisement_object_path| with BlueZ's advertising manager. + virtual void UnregisterAdvertisement( + const dbus::ObjectPath& manager_object_path, + const dbus::ObjectPath& advertisement_object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Creates the instance. + static BluetoothLEAdvertisingManagerClient* Create(); + + // Constants used to indicate exceptional error conditions. + static const char kNoResponseError[]; + + protected: + BluetoothLEAdvertisingManagerClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothLEAdvertisingManagerClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_
diff --git a/device/bluetooth/dbus/bluetooth_media_client.cc b/device/bluetooth/dbus/bluetooth_media_client.cc new file mode 100644 index 0000000..0927d45 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_media_client.cc
@@ -0,0 +1,227 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/bluetooth_media_client.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/observer_list.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_manager.h" +#include "dbus/object_proxy.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace { + +// Since there is no property associated with Media objects, an empty callback +// is used. +void DoNothing(const std::string& property_name) {} + +// TODO(mcchou): Add these service constants into dbus/service_constants.h +// later. +const char kBluetoothMediaInterface[] = "org.bluez.Media1"; + +// Method names supported by Media Interface. +const char kRegisterEndpoint[] = "RegisterEndpoint"; +const char kUnregisterEndpoint[] = "UnregisterEndpoint"; + +// The set of properties which are used to register a media endpoint. +const char kUUIDEndpointProperty[] = "UUID"; +const char kCodecEndpointProperty[] = "Codec"; +const char kCapabilitiesEndpointProperty[] = "Capabilities"; + +} // namespace + +namespace bluez { + +// static +const char BluetoothMediaClient::kNoResponseError[] = + "org.chromium.Error.NoResponse"; + +// static +const char BluetoothMediaClient::kBluetoothAudioSinkUUID[] = + "0000110b-0000-1000-8000-00805f9b34fb"; + +BluetoothMediaClient::EndpointProperties::EndpointProperties() : codec(0x00) {} + +BluetoothMediaClient::EndpointProperties::~EndpointProperties() {} + +class BluetoothMediaClientImpl : public BluetoothMediaClient, + dbus::ObjectManager::Interface { + public: + BluetoothMediaClientImpl() + : object_manager_(nullptr), weak_ptr_factory_(this) {} + + ~BluetoothMediaClientImpl() override { + object_manager_->UnregisterInterface(kBluetoothMediaInterface); + } + + // dbus::ObjectManager::Interface overrides. + + dbus::PropertySet* CreateProperties( + dbus::ObjectProxy* object_proxy, + const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + return new dbus::PropertySet(object_proxy, interface_name, + base::Bind(&DoNothing)); + } + + void ObjectAdded(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + VLOG(1) << "Remote Media added: " << object_path.value(); + FOR_EACH_OBSERVER(BluetoothMediaClient::Observer, observers_, + MediaAdded(object_path)); + } + + void ObjectRemoved(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + VLOG(1) << "Remote Media removed: " << object_path.value(); + FOR_EACH_OBSERVER(BluetoothMediaClient::Observer, observers_, + MediaRemoved(object_path)); + } + + // BluetoothMediaClient overrides. + + void AddObserver(BluetoothMediaClient::Observer* observer) override { + DCHECK(observer); + observers_.AddObserver(observer); + } + + void RemoveObserver(BluetoothMediaClient::Observer* observer) override { + DCHECK(observer); + observers_.RemoveObserver(observer); + } + + void RegisterEndpoint(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& endpoint_path, + const EndpointProperties& properties, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + VLOG(1) << "RegisterEndpoint - endpoint: " << endpoint_path.value(); + + dbus::MethodCall method_call(kBluetoothMediaInterface, kRegisterEndpoint); + + dbus::MessageWriter writer(&method_call); + dbus::MessageWriter array_writer(nullptr); + dbus::MessageWriter dict_entry_writer(nullptr); + + // Send the path to the endpoint. + writer.AppendObjectPath(endpoint_path); + + writer.OpenArray("{sv}", &array_writer); + + // Send UUID. + array_writer.OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString(kUUIDEndpointProperty); + dict_entry_writer.AppendVariantOfString(properties.uuid); + array_writer.CloseContainer(&dict_entry_writer); + + // Send Codec. + array_writer.OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString(kCodecEndpointProperty); + dict_entry_writer.AppendVariantOfByte(properties.codec); + array_writer.CloseContainer(&dict_entry_writer); + + // Send Capabilities. + dbus::MessageWriter variant_writer(nullptr); + array_writer.OpenDictEntry(&dict_entry_writer); + dict_entry_writer.AppendString(kCapabilitiesEndpointProperty); + dict_entry_writer.OpenVariant("ay", &variant_writer); + variant_writer.AppendArrayOfBytes(properties.capabilities.data(), + properties.capabilities.size()); + dict_entry_writer.CloseContainer(&variant_writer); + array_writer.CloseContainer(&dict_entry_writer); + + writer.CloseContainer(&array_writer); + + // Get Object Proxy based on the service name and the service path and call + // RegisterEndpoint medthod. + scoped_refptr<dbus::ObjectProxy> object_proxy( + object_manager_->GetObjectProxy(object_path)); + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothMediaClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothMediaClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + void UnregisterEndpoint(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& endpoint_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + VLOG(1) << "UnregisterEndpoint - endpoint: " << endpoint_path.value(); + + dbus::MethodCall method_call(kBluetoothMediaInterface, kUnregisterEndpoint); + + // Send the path to the endpoint. + dbus::MessageWriter writer(&method_call); + writer.AppendObjectPath(endpoint_path); + + // Get Object Proxy based on the service name and the service path and call + // RegisterEndpoint medthod. + scoped_refptr<dbus::ObjectProxy> object_proxy( + object_manager_->GetObjectProxy(object_path)); + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothMediaClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothMediaClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + protected: + void Init(dbus::Bus* bus) override { + DCHECK(bus); + object_manager_ = bus->GetObjectManager( + bluetooth_object_manager::kBluetoothObjectManagerServiceName, + dbus::ObjectPath( + bluetooth_object_manager::kBluetoothObjectManagerServicePath)); + object_manager_->RegisterInterface(kBluetoothMediaInterface, this); + } + + private: + // Called when a response for successful method call is received. + void OnSuccess(const base::Closure& callback, dbus::Response* response) { + DCHECK(response); + callback.Run(); + } + + // Called when a response for a failed method call is received. + void OnError(const ErrorCallback& error_callback, + dbus::ErrorResponse* response) { + // Error response has an optional error message argument. + std::string error_name; + std::string error_message; + if (response) { + dbus::MessageReader reader(response); + error_name = response->GetErrorName(); + reader.PopString(&error_message); + } else { + error_name = kNoResponseError; + } + error_callback.Run(error_name, error_message); + } + + dbus::ObjectManager* object_manager_; + + // List of observers interested in event notifications from us. + base::ObserverList<BluetoothMediaClient::Observer> observers_; + + base::WeakPtrFactory<BluetoothMediaClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothMediaClientImpl); +}; + +BluetoothMediaClient::BluetoothMediaClient() {} + +BluetoothMediaClient::~BluetoothMediaClient() {} + +BluetoothMediaClient* BluetoothMediaClient::Create() { + return new BluetoothMediaClientImpl(); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_media_client.h b/device/bluetooth/dbus/bluetooth_media_client.h new file mode 100644 index 0000000..88597c5 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_media_client.h
@@ -0,0 +1,108 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_CLIENT_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/values.h" +#include "dbus/object_path.h" +#include "dbus/property.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluez_dbus_client.h" + +namespace bluez { + +// BluetoothMediaClient is used to communicate with the Media interface of a +// local Bluetooth adapter. +class DEVICE_BLUETOOTH_EXPORT BluetoothMediaClient : public BluezDBusClient { + public: + // Properties used to register a Media Endpoint. + struct DEVICE_BLUETOOTH_EXPORT EndpointProperties { + EndpointProperties(); + ~EndpointProperties(); + + // UUID of the profile implemented by the endpoint. + std::string uuid; + + // Assigned codec value supported by the endpoint. The byte should match the + // codec specification indicated by the UUID. + // Since SBC codec is mandatory for A2DP, the default value of codec should + // be 0x00. + uint8_t codec; + + // Capabilities of the endpoints. The order of bytes should match the bit + // arrangement in the specification indicated by the UUID. + std::vector<uint8_t> capabilities; + }; + + class Observer { + public: + virtual ~Observer() {} + + // Called when the Media object with object path |object_path| is added to + // the system. + virtual void MediaAdded(const dbus::ObjectPath& object_path) {} + + // Called when the Media object with object path |object_path| is removed + // from the system. + virtual void MediaRemoved(const dbus::ObjectPath& object_path) {} + }; + + // Constants used to indicate exceptional error conditions. + static const char kNoResponseError[]; + + // The string representation for the 128-bit UUID for A2DP Sink. + static const char kBluetoothAudioSinkUUID[]; + + ~BluetoothMediaClient() override; + + // The ErrorCallback is used by media API methods to indicate failure. + // It receives two arguments: the name of the error in |error_name| and + // an optional message in |error_message|. + typedef base::Callback<void(const std::string& error_name, + const std::string& error_message)> ErrorCallback; + + // Adds and removes observers for events on all Media objects. Check the + // |object_path| parameter of observer methods to determine which Media object + // is issuing the event. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Registers a media endpoint to sender at the D-Bus object path + // |endpoint_path|. |properties| specifies profile UUID which the endpoint is + // for, Codec implemented by the endpoint and the Capabilities of the + // endpoint. + virtual void RegisterEndpoint(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& endpoint_path, + const EndpointProperties& properties, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Unregisters the media endpoint with the D-Bus object path |endpoint_path|. + virtual void UnregisterEndpoint(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& endpoint_path, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // TODO(mcchou): The RegisterPlayer and UnregisterPlayer methods are not + // included, since they are not used. These two methods may be added later. + + static BluetoothMediaClient* Create(); + + protected: + BluetoothMediaClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothMediaClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_CLIENT_H_
diff --git a/device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.cc b/device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.cc new file mode 100644 index 0000000..864a04d --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.cc
@@ -0,0 +1,313 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/threading/platform_thread.h" +#include "dbus/exported_object.h" +#include "device/bluetooth/dbus/bluetooth_media_transport_client.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h" + +namespace { + +// TODO(mcchou): Move these constants to dbus/service_constants.h. +// Bluetooth Media Endpoint service identifier. +const char kBluetoothMediaEndpointInterface[] = "org.bluez.MediaEndpoint1"; + +// Method names in Bluetooth Media Endpoint interface. +const char kSetConfiguration[] = "SetConfiguration"; +const char kSelectConfiguration[] = "SelectConfiguration"; +const char kClearConfiguration[] = "ClearConfiguration"; +const char kRelease[] = "Release"; + +const uint8_t kInvalidCodec = 0xff; +const char kInvalidState[] = "unknown"; + +} // namespace + +namespace bluez { + +// The BluetoothMediaEndopintServiceProvider implementation used in production. +class DEVICE_BLUETOOTH_EXPORT BluetoothMediaEndpointServiceProviderImpl + : public BluetoothMediaEndpointServiceProvider { + public: + BluetoothMediaEndpointServiceProviderImpl(dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate) + : origin_thread_id_(base::PlatformThread::CurrentId()), + bus_(bus), + delegate_(delegate), + object_path_(object_path), + weak_ptr_factory_(this) { + VLOG(1) << "Creating Bluetooth Media Endpoint: " << object_path_.value(); + DCHECK(bus_); + DCHECK(delegate_); + DCHECK(object_path_.IsValid()); + + exported_object_ = bus_->GetExportedObject(object_path_); + + exported_object_->ExportMethod( + kBluetoothMediaEndpointInterface, kSetConfiguration, + base::Bind(&BluetoothMediaEndpointServiceProviderImpl::SetConfiguration, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + kBluetoothMediaEndpointInterface, kSelectConfiguration, + base::Bind( + &BluetoothMediaEndpointServiceProviderImpl::SelectConfiguration, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + kBluetoothMediaEndpointInterface, kClearConfiguration, + base::Bind( + &BluetoothMediaEndpointServiceProviderImpl::ClearConfiguration, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + kBluetoothMediaEndpointInterface, kRelease, + base::Bind(&BluetoothMediaEndpointServiceProviderImpl::Release, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + } + + ~BluetoothMediaEndpointServiceProviderImpl() override { + VLOG(1) << "Cleaning up Bluetooth Media Endpoint: " << object_path_.value(); + + bus_->UnregisterExportedObject(object_path_); + } + + private: + // Returns true if the current thread is on the origin thread, false + // otherwise. + bool OnOriginThread() const { + return base::PlatformThread::CurrentId() == origin_thread_id_; + } + + // Called by dbus:: when a method is exported. + void OnExported(const std::string& interface_name, + const std::string& method_name, + bool success) { + LOG_IF(ERROR, !success) << "Failed to export " << interface_name << "." + << method_name; + } + + // Called by dbus:: when the remote device connects to the Media Endpoint. + void SetConfiguration(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(1) << "SetConfiguration"; + + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + dbus::ObjectPath transport_path; + dbus::MessageReader property_reader(method_call); + if (!reader.PopObjectPath(&transport_path) || + !reader.PopArray(&property_reader)) { + LOG(ERROR) << "SetConfiguration called with incorrect parameters: " + << method_call->ToString(); + return; + } + + // Parses |properties| and passes the property set as a + // Delegate::TransportProperties structure to |delegate_|. + Delegate::TransportProperties properties; + while (property_reader.HasMoreData()) { + dbus::MessageReader dict_entry_reader(nullptr); + std::string key; + if (!property_reader.PopDictEntry(&dict_entry_reader) || + !dict_entry_reader.PopString(&key)) { + LOG(ERROR) << "SetConfiguration called with incorrect parameters: " + << method_call->ToString(); + } else if (key == BluetoothMediaTransportClient::kDeviceProperty) { + dict_entry_reader.PopVariantOfObjectPath(&properties.device); + } else if (key == BluetoothMediaTransportClient::kUUIDProperty) { + dict_entry_reader.PopVariantOfString(&properties.uuid); + } else if (key == BluetoothMediaTransportClient::kCodecProperty) { + dict_entry_reader.PopVariantOfByte(&properties.codec); + } else if (key == BluetoothMediaTransportClient::kConfigurationProperty) { + dbus::MessageReader variant_reader(nullptr); + const uint8_t* bytes = nullptr; + size_t length = 0; + dict_entry_reader.PopVariant(&variant_reader); + variant_reader.PopArrayOfBytes(&bytes, &length); + properties.configuration.assign(bytes, bytes + length); + } else if (key == BluetoothMediaTransportClient::kStateProperty) { + dict_entry_reader.PopVariantOfString(&properties.state); + } else if (key == BluetoothMediaTransportClient::kDelayProperty) { + properties.delay.reset(new uint16_t()); + dict_entry_reader.PopVariantOfUint16(properties.delay.get()); + } else if (key == BluetoothMediaTransportClient::kVolumeProperty) { + properties.volume.reset(new uint16_t()); + dict_entry_reader.PopVariantOfUint16(properties.volume.get()); + } + } + + if (properties.codec != kInvalidCodec && + properties.state != kInvalidState) { + delegate_->SetConfiguration(transport_path, properties); + } else { + LOG(ERROR) << "SetConfiguration called with incorrect parameters: " + << method_call->ToString(); + } + + response_sender.Run(dbus::Response::FromMethodCall(method_call)); + } + + // Called by dbus:: when the remote device receives the configuration for + // media transport. + void SelectConfiguration( + dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(1) << "SelectConfiguration"; + + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + const uint8_t* capabilities = nullptr; + size_t length = 0; + if (!reader.PopArrayOfBytes(&capabilities, &length)) { + LOG(ERROR) << "SelectConfiguration called with incorrect parameters: " + << method_call->ToString(); + return; + } + + std::vector<uint8_t> configuration(capabilities, capabilities + length); + + // |delegate_| generates the response to |SelectConfiguration| and sends it + // back via |callback|. + Delegate::SelectConfigurationCallback callback = base::Bind( + &BluetoothMediaEndpointServiceProviderImpl::OnConfiguration, + weak_ptr_factory_.GetWeakPtr(), method_call, response_sender); + + delegate_->SelectConfiguration(configuration, callback); + } + + // Called by dbus:: when the remote device is about to close the connection. + void ClearConfiguration( + dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(1) << "ClearConfiguration"; + + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + dbus::ObjectPath transport_path; + if (!reader.PopObjectPath(&transport_path)) { + LOG(ERROR) << "ClearConfiguration called with incorrect parameters: " + << method_call->ToString(); + return; + } + + delegate_->ClearConfiguration(transport_path); + + response_sender.Run(dbus::Response::FromMethodCall(method_call)); + } + + // Called by Bluetooth daemon to do the clean up after unregistering the Media + // Endpoint. + void Release(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + VLOG(1) << "Release"; + + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + delegate_->Released(); + + response_sender.Run(dbus::Response::FromMethodCall(method_call)); + } + + // Called by Delegate to response to a method requiring transport + // configuration. + void OnConfiguration(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender, + const std::vector<uint8_t>& configuration) { + VLOG(1) << "OnConfiguration"; + + DCHECK(OnOriginThread()); + + // Generates the response to the method call. + scoped_ptr<dbus::Response> response( + dbus::Response::FromMethodCall(method_call)); + dbus::MessageWriter writer(response.get()); + if (configuration.empty()) { + LOG(ERROR) << "OnConfiguration called with empty configuration."; + writer.AppendArrayOfBytes(nullptr, 0); + } else { + writer.AppendArrayOfBytes(&configuration[0], configuration.size()); + } + response_sender.Run(response.Pass()); + } + + // Origin thread (i.e. the UI thread in production). + base::PlatformThreadId origin_thread_id_; + + // D-Bus Bus object is exported on. + dbus::Bus* bus_; + + // All incoming method calls are passed on to |delegate_|. |callback| passed + // to |delegate+| will generate the response for those methods whose returns + // are non-void. + Delegate* delegate_; + + // D-Bus object path of the object we are exporting, kept so we can unregister + // again in you destructor. + dbus::ObjectPath object_path_; + + // D-Bus object we are exporting, owned by this object. + scoped_refptr<dbus::ExportedObject> exported_object_; + + // Weak pointer factory for generating 'this' printers that might live longer + // than we do. + // Note This should remain the last member so it'll be destroyed and + // invalidate it's weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothMediaEndpointServiceProviderImpl> + weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothMediaEndpointServiceProviderImpl); +}; + +BluetoothMediaEndpointServiceProvider::Delegate::TransportProperties:: + TransportProperties() + : codec(kInvalidCodec), state(kInvalidState) {} + +BluetoothMediaEndpointServiceProvider::Delegate::TransportProperties:: + ~TransportProperties() {} + +BluetoothMediaEndpointServiceProvider::BluetoothMediaEndpointServiceProvider() { +} + +BluetoothMediaEndpointServiceProvider:: + ~BluetoothMediaEndpointServiceProvider() {} + +BluetoothMediaEndpointServiceProvider* +BluetoothMediaEndpointServiceProvider::Create( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate) { + // Returns a real implementation. + if (!bluez::BluezDBusManager::Get()->IsUsingStub()) { + return new BluetoothMediaEndpointServiceProviderImpl(bus, object_path, + delegate); + } + // Returns a fake implementation. + return new FakeBluetoothMediaEndpointServiceProvider(object_path, delegate); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.h b/device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.h new file mode 100644 index 0000000..d44c065 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.h
@@ -0,0 +1,134 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_ + +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/macros.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" + +namespace bluez { + +// BluetoothMediaEndpointServiceProvider is used to provide a D-Bus object that +// the Bluetooth daemon can commuicate with to serve as a media source/sink. +// +// Instantiate with a chosen D-Bus object path and a delegate object, and pass +// the D-Bus object path as |endpoint_path| argument to the +// chromeos::BluetoothMediaClient::RegisterEndoint() method. +// +// After initiating a connection between an audio source and an audio sink, the +// Bluetooth daemon will make calls to this endpoint object and they will be +// passed to user's Delegate object for handling. For SelectConfiguration method +// the response is returned using the SelectConfiguration callback. +class DEVICE_BLUETOOTH_EXPORT BluetoothMediaEndpointServiceProvider { + public: + // Delegate is the interface for reacting to endpoint requests. User + // applications will implement this interface to handle either A2DP Sink or + // Source. + class Delegate { + public: + // Transport-specific properties. + struct DEVICE_BLUETOOTH_EXPORT TransportProperties { + TransportProperties(); + ~TransportProperties(); + + // The path to the device object which the transport is connected to. + dbus::ObjectPath device; + + // The UUID of the profile which the transport is for. + std::string uuid; + + // The Codec value agreed by the remote device and used by the media + // transport. + uint8_t codec; + + // The configuration used by the media transport. + std::vector<uint8_t> configuration; + + // The state of the transport. The values can be one of the following: + // "idle": not streaming + // "pending": streaming but not acquired + // "active": streaming and acquired + std::string state; + + // The unit of transport is in 1/10 millisecond. Optional. + scoped_ptr<uint16_t> delay; + + // The volume level of the transport. Optional. + scoped_ptr<uint16_t> volume; + + private: + DISALLOW_COPY_AND_ASSIGN(TransportProperties); + }; + + virtual ~Delegate() {} + + // SelectConfigurationCallback is used for the SelectConfiguration() method, + // it should be called with two arguements, the |configuration| which is + // agreed by the application and the |length| of |configuration|. + typedef base::Callback<void(const std::vector<uint8_t>&)> + SelectConfigurationCallback; + + // This method will be called after an Audio Source receives the agreed + // capabilities from the Audio Sink to set the configuration for the + // media transport object. |transport_path| is the path to the + // MediaTransport object, and |properties| are the properties for that + // MediaTransport object. + virtual void SetConfiguration(const dbus::ObjectPath& transport_path, + const TransportProperties& properties) = 0; + + // This method will be called when an Audio Source connects to an Audio Sink + // and asks it to decide the configuration to be used during the oncoming + // streaming. Audio Sources provide |capabilities| as a reference, where + // a user application can use these |capabilities| to figure out + // a well-matched configuration and return it to the Audio Source via + // |callback|. + virtual void SelectConfiguration( + const std::vector<uint8_t>& capabilities, + const SelectConfigurationCallback& callback) = 0; + + // This method will be called when an Audio Source disconnects from an Audio + // Sink. A user application is supposed to clear any of its resources which + // it keeps for that particular connection. |transport_path| is the Media + // Transport object which has been kept by an endpoint during the + // connection. + virtual void ClearConfiguration(const dbus::ObjectPath& transport_path) = 0; + + // This method will be called when the Bluetooth daemon unregisters the + // Media Endpoint. Media Endpoint objects can use this method to clean up + // tasks. There is no need to unregister the endpoint, since when this + // method gets called, that endpoint has been unregistered. This corresponds + // to the org.bluez.MediaEndpoint1.Release and is renamed to avoid + // a conflict with base::RefCounted<T>. + virtual void Released() = 0; + }; + + virtual ~BluetoothMediaEndpointServiceProvider(); + + // Creates the instance where |bus| is the D-Bus bus connection to export the + // object onto, |object_path| is the object path that it should have and + // |delegate| is the object to which all method calls will be passed and + // responses generated from. + static BluetoothMediaEndpointServiceProvider* Create( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate); + + protected: + BluetoothMediaEndpointServiceProvider(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothMediaEndpointServiceProvider); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_
diff --git a/device/bluetooth/dbus/bluetooth_media_transport_client.cc b/device/bluetooth/dbus/bluetooth_media_transport_client.cc new file mode 100644 index 0000000..7fc47d7 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_media_transport_client.cc
@@ -0,0 +1,286 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/bluetooth_media_transport_client.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/observer_list.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_manager.h" +#include "dbus/object_proxy.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace { + +// TODO(mcchou): Add these service constants into dbus/service_constants.h +// later. +const char kBluetoothMediaTransportInterface[] = "org.bluez.MediaTransport1"; + +// Constants used to indicate exceptional error conditions. +const char kNoResponseError[] = "org.chromium.Error.NoResponse"; +const char kUnexpectedResponse[] = "org.chromium.Error.UnexpectedResponse"; + +// Method names of Media Transport interface. +const char kAcquire[] = "Acquire"; +const char kTryAcquire[] = "TryAcquire"; +const char kRelease[] = "Release"; + +} // namespace + +namespace bluez { + +// static +const char BluetoothMediaTransportClient::kDeviceProperty[] = "Device"; +const char BluetoothMediaTransportClient::kUUIDProperty[] = "UUID"; +const char BluetoothMediaTransportClient::kCodecProperty[] = "Codec"; +const char BluetoothMediaTransportClient::kConfigurationProperty[] = + "Configuration"; +const char BluetoothMediaTransportClient::kStateProperty[] = "State"; +const char BluetoothMediaTransportClient::kDelayProperty[] = "Delay"; +const char BluetoothMediaTransportClient::kVolumeProperty[] = "Volume"; + +// static +const char BluetoothMediaTransportClient::kStateIdle[] = "idle"; +const char BluetoothMediaTransportClient::kStatePending[] = "pending"; +const char BluetoothMediaTransportClient::kStateActive[] = "active"; + +BluetoothMediaTransportClient::Properties::Properties( + dbus::ObjectProxy* object_proxy, + const std::string& interface_name, + const PropertyChangedCallback& callback) + : dbus::PropertySet(object_proxy, interface_name, callback) { + RegisterProperty(kDeviceProperty, &device); + RegisterProperty(kUUIDProperty, &uuid); + RegisterProperty(kCodecProperty, &codec); + RegisterProperty(kConfigurationProperty, &configuration); + RegisterProperty(kStateProperty, &state); + RegisterProperty(kDelayProperty, &delay); + RegisterProperty(kVolumeProperty, &volume); +} + +BluetoothMediaTransportClient::Properties::~Properties() {} + +class BluetoothMediaTransportClientImpl + : public BluetoothMediaTransportClient, + public dbus::ObjectManager::Interface { + public: + BluetoothMediaTransportClientImpl() + : object_manager_(nullptr), weak_ptr_factory_(this) {} + + ~BluetoothMediaTransportClientImpl() override { + object_manager_->UnregisterInterface(kBluetoothMediaTransportInterface); + } + + // dbus::ObjectManager::Interface overrides. + + dbus::PropertySet* CreateProperties( + dbus::ObjectProxy* object_proxy, + const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + Properties* properties = new Properties( + object_proxy, interface_name, + base::Bind(&BluetoothMediaTransportClientImpl::OnPropertyChanged, + weak_ptr_factory_.GetWeakPtr(), object_path)); + return properties; + } + + void ObjectAdded(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + VLOG(1) << "Remote Media Transport added: " << object_path.value(); + FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, + MediaTransportAdded(object_path)); + } + + void ObjectRemoved(const dbus::ObjectPath& object_path, + const std::string& interface_name) override { + VLOG(1) << "Remote Media Transport removed: " << object_path.value(); + FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, + MediaTransportRemoved(object_path)); + } + + // BluetoothMediaTransportClient overrides. + + void AddObserver(BluetoothMediaTransportClient::Observer* observer) override { + DCHECK(observer); + observers_.AddObserver(observer); + } + + void RemoveObserver( + BluetoothMediaTransportClient::Observer* observer) override { + DCHECK(observer); + observers_.RemoveObserver(observer); + } + + Properties* GetProperties(const dbus::ObjectPath& object_path) override { + DCHECK(object_manager_); + return static_cast<Properties*>(object_manager_->GetProperties( + object_path, kBluetoothMediaTransportInterface)); + } + + void Acquire(const dbus::ObjectPath& object_path, + const AcquireCallback& callback, + const ErrorCallback& error_callback) override { + VLOG(1) << "Acquire - transport: " << object_path.value(); + + DCHECK(object_manager_); + + dbus::MethodCall method_call(kBluetoothMediaTransportInterface, kAcquire); + + // Get object proxy. + scoped_refptr<dbus::ObjectProxy> object_proxy( + object_manager_->GetObjectProxy(object_path)); + + // Call Acquire method of Media Transport interface. + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothMediaTransportClientImpl::OnAcquireSuccess, + weak_ptr_factory_.GetWeakPtr(), callback, error_callback), + base::Bind(&BluetoothMediaTransportClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + void TryAcquire(const dbus::ObjectPath& object_path, + const AcquireCallback& callback, + const ErrorCallback& error_callback) override { + VLOG(1) << "TryAcquire - transport: " << object_path.value(); + + DCHECK(object_manager_); + + dbus::MethodCall method_call(kBluetoothMediaTransportInterface, + kTryAcquire); + + // Get object proxy. + scoped_refptr<dbus::ObjectProxy> object_proxy( + object_manager_->GetObjectProxy(object_path)); + + // Call TryAcquire method of Media Transport interface. + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothMediaTransportClientImpl::OnAcquireSuccess, + weak_ptr_factory_.GetWeakPtr(), callback, error_callback), + base::Bind(&BluetoothMediaTransportClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + void Release(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + VLOG(1) << "Release - transport: " << object_path.value(); + + DCHECK(object_manager_); + + dbus::MethodCall method_call(kBluetoothMediaTransportInterface, kRelease); + + // Get object proxy. + scoped_refptr<dbus::ObjectProxy> object_proxy( + object_manager_->GetObjectProxy(object_path)); + + // Call TryAcquire method of Media Transport interface. + object_proxy->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothMediaTransportClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothMediaTransportClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + protected: + void Init(dbus::Bus* bus) override { + DCHECK(bus); + object_manager_ = bus->GetObjectManager( + bluetooth_object_manager::kBluetoothObjectManagerServiceName, + dbus::ObjectPath( + bluetooth_object_manager::kBluetoothObjectManagerServicePath)); + object_manager_->RegisterInterface(kBluetoothMediaTransportInterface, this); + } + + private: + // Called by dbus::PropertySet when a property value is changed. + void OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) { + VLOG(1) << "Name of the changed property: " << property_name; + + // Dispatches the change to the corresponding property-changed handler. + FOR_EACH_OBSERVER( + BluetoothMediaTransportClient::Observer, observers_, + MediaTransportPropertyChanged(object_path, property_name)); + } + + // Called when a response for successful method call is received. + void OnSuccess(const base::Closure& callback, dbus::Response* response) { + DCHECK(response); + callback.Run(); + } + + // Called when a response for |Acquire|/|TryAcquire| method call is received. + void OnAcquireSuccess(const AcquireCallback& callback, + const ErrorCallback& error_callback, + dbus::Response* response) { + DCHECK(response); + + dbus::FileDescriptor fd; + uint16_t read_mtu; + uint16_t write_mtu; + + // Parse the response. + dbus::MessageReader reader(response); + if (reader.PopFileDescriptor(&fd) && reader.PopUint16(&read_mtu) && + reader.PopUint16(&write_mtu)) { + fd.CheckValidity(); + DCHECK(fd.is_valid()); + + VLOG(1) << "OnAcquireSuccess - fd: " << fd.value() + << ", read MTU: " << read_mtu << ", write MTU: " << write_mtu; + + // The ownership of the file descriptor is transferred to the user + // application. + callback.Run(&fd, read_mtu, write_mtu); + return; + } + + error_callback.Run( + kUnexpectedResponse, + "Failed to retrieve file descriptor, read MTU and write MTU."); + } + + // Called when a response for a failed method call is received. + void OnError(const ErrorCallback& error_callback, + dbus::ErrorResponse* response) { + DCHECK(response); + + // Error response has optional error message argument. + std::string error_name; + std::string error_message; + if (response) { + dbus::MessageReader reader(response); + error_name = response->GetErrorName(); + reader.PopString(&error_message); + } else { + error_name = kNoResponseError; + } + error_callback.Run(error_name, error_message); + } + + dbus::ObjectManager* object_manager_; + + // List of observers interested in event notifications from us. + base::ObserverList<BluetoothMediaTransportClient::Observer> observers_; + + base::WeakPtrFactory<BluetoothMediaTransportClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothMediaTransportClientImpl); +}; + +BluetoothMediaTransportClient::BluetoothMediaTransportClient() {} + +BluetoothMediaTransportClient::~BluetoothMediaTransportClient() {} + +BluetoothMediaTransportClient* BluetoothMediaTransportClient::Create() { + return new BluetoothMediaTransportClientImpl(); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_media_transport_client.h b/device/bluetooth/dbus/bluetooth_media_transport_client.h new file mode 100644 index 0000000..09c6ea0 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_media_transport_client.h
@@ -0,0 +1,144 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_ + +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/macros.h" +#include "dbus/file_descriptor.h" +#include "dbus/object_path.h" +#include "dbus/property.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluez_dbus_client.h" + +namespace bluez { + +class DEVICE_BLUETOOTH_EXPORT BluetoothMediaTransportClient + : public BluezDBusClient { + public: + struct Properties : public dbus::PropertySet { + // The path to the device object which the transport is connected to. + // Read-only. + dbus::Property<dbus::ObjectPath> device; + + // UUID of the profile which the transport is for. Read-only. + dbus::Property<std::string> uuid; + + // Assigned codec value supported by the media transport. Read-only. + dbus::Property<uint8_t> codec; + + // The configuration used by the media transport. Read-only. + dbus::Property<std::vector<uint8_t>> configuration; + + // The state of the transport. Read-only. + // The values can be one of the following: + // "idle": not streaming + // "pending": streaming but not acquired + // "active": streaming and acquired + dbus::Property<std::string> state; + + // The unit of transport delay is in 1/10 of millisecond. This property is + // only writeable when the transport was aquired by the sender. Optional. + dbus::Property<uint16_t> delay; + + // The volume level of the transport. This property is only writable when + // the transport was aquired by the sender. Optional. + dbus::Property<uint16_t> volume; + + Properties(dbus::ObjectProxy* object_proxy, + const std::string& interface_name, + const PropertyChangedCallback& callback); + ~Properties() override; + }; + + class Observer { + public: + virtual ~Observer() {} + + // Called when the Media Transport with object path |object_path| is added + // to the system. + virtual void MediaTransportAdded(const dbus::ObjectPath& object_path) {} + + // Called when the Media Transport with object path |object_path| is removed + // from the system. + virtual void MediaTransportRemoved(const dbus::ObjectPath& object_path) {} + + // Called when the Media Transport with object path |object_path| has + // a change in the value of the property with name |property_name|. + virtual void MediaTransportPropertyChanged( + const dbus::ObjectPath& object_path, + const std::string& property_name) {} + }; + + // TODO(mcchou): Move all static constants to service_constants.h. + // Constants used for the names of Media Transport's properties. + static const char kDeviceProperty[]; + static const char kUUIDProperty[]; + static const char kCodecProperty[]; + static const char kConfigurationProperty[]; + static const char kStateProperty[]; + static const char kDelayProperty[]; + static const char kVolumeProperty[]; + + // All possible states of a valid media transport object. + static const char kStateIdle[]; + static const char kStatePending[]; + static const char kStateActive[]; + + ~BluetoothMediaTransportClient() override; + + // The ErrorCallback is used by media transport API methods to indicate + // failure. It receives two arguments: the name of the error in |error_name| + // and an optional message in |error_message|. + typedef base::Callback<void(const std::string& error_name, + const std::string& error_message)> ErrorCallback; + + // The AcquireCallback is used by |Acquire| method of media tansport API tp + // indicate the success of the method. + typedef base::Callback<void(dbus::FileDescriptor* fd, + const uint16_t read_mtu, + const uint16_t write_mtu)> AcquireCallback; + + // Adds and removes observers for events on all remote Media Transports. Check + // the |object_path| parameter of observer methods to determine which Media + // Transport is issuing the event. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; + + // Acquires transport file descriptor and the MTU for read and write. + virtual void Acquire(const dbus::ObjectPath& object_path, + const AcquireCallback& callback, + const ErrorCallback& error_callback) = 0; + + // Acquires transport file descriptor only if the transport is in "pending" + // state at the time the message is received by BlueZ. Otherwise no request + // will be sent to the remote device and the function will just fail with + // org.bluez.Error.NotAvailable. + virtual void TryAcquire(const dbus::ObjectPath& object_path, + const AcquireCallback& callback, + const ErrorCallback& error_callback) = 0; + + // Releases the file descriptor of the transport. + virtual void Release(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + static BluetoothMediaTransportClient* Create(); + + protected: + BluetoothMediaTransportClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothMediaTransportClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_
diff --git a/device/bluetooth/dbus/bluetooth_profile_manager_client.cc b/device/bluetooth/dbus/bluetooth_profile_manager_client.cc new file mode 100644 index 0000000..742988a --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_profile_manager_client.cc
@@ -0,0 +1,234 @@ +// Copyright 2013 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 "device/bluetooth/dbus/bluetooth_profile_manager_client.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_proxy.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +const char BluetoothProfileManagerClient::kNoResponseError[] = + "org.chromium.Error.NoResponse"; + +BluetoothProfileManagerClient::Options::Options() {} + +BluetoothProfileManagerClient::Options::~Options() {} + +// The BluetoothProfileManagerClient implementation used in production. +class BluetoothProfileManagerClientImpl : public BluetoothProfileManagerClient { + public: + BluetoothProfileManagerClientImpl() : weak_ptr_factory_(this) {} + + ~BluetoothProfileManagerClientImpl() override {} + + // BluetoothProfileManagerClient override. + void RegisterProfile(const dbus::ObjectPath& profile_path, + const std::string& uuid, + const Options& options, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call( + bluetooth_profile_manager::kBluetoothProfileManagerInterface, + bluetooth_profile_manager::kRegisterProfile); + + dbus::MessageWriter writer(&method_call); + writer.AppendObjectPath(profile_path); + writer.AppendString(uuid); + + dbus::MessageWriter array_writer(NULL); + writer.OpenArray("{sv}", &array_writer); + + dbus::MessageWriter dict_writer(NULL); + + // Send Name if provided. + if (options.name.get() != NULL) { + array_writer.OpenDictEntry(&dict_writer); + dict_writer.AppendString(bluetooth_profile_manager::kNameOption); + dict_writer.AppendVariantOfString(*(options.name)); + array_writer.CloseContainer(&dict_writer); + } + + // Send Service if provided. + if (options.service.get() != NULL) { + dbus::MessageWriter dict_writer(NULL); + array_writer.OpenDictEntry(&dict_writer); + dict_writer.AppendString(bluetooth_profile_manager::kServiceOption); + dict_writer.AppendVariantOfString(*(options.service)); + array_writer.CloseContainer(&dict_writer); + } + + // Send Role if not the default value. + if (options.role != SYMMETRIC) { + dbus::MessageWriter dict_writer(NULL); + array_writer.OpenDictEntry(&dict_writer); + dict_writer.AppendString(bluetooth_profile_manager::kRoleOption); + if (options.role == CLIENT) + dict_writer.AppendVariantOfString( + bluetooth_profile_manager::kClientRoleOption); + else if (options.role == SERVER) + dict_writer.AppendVariantOfString( + bluetooth_profile_manager::kServerRoleOption); + else + dict_writer.AppendVariantOfString(""); + array_writer.CloseContainer(&dict_writer); + } + + // Send Channel if provided. + if (options.channel.get() != NULL) { + dbus::MessageWriter dict_writer(NULL); + array_writer.OpenDictEntry(&dict_writer); + dict_writer.AppendString(bluetooth_profile_manager::kChannelOption); + dict_writer.AppendVariantOfUint16(*(options.channel)); + array_writer.CloseContainer(&dict_writer); + } + + // Send PSM if provided. + if (options.psm.get() != NULL) { + dbus::MessageWriter dict_writer(NULL); + array_writer.OpenDictEntry(&dict_writer); + dict_writer.AppendString(bluetooth_profile_manager::kPSMOption); + dict_writer.AppendVariantOfUint16(*(options.psm)); + array_writer.CloseContainer(&dict_writer); + } + + // Send RequireAuthentication if provided. + if (options.require_authentication.get() != NULL) { + array_writer.OpenDictEntry(&dict_writer); + dict_writer.AppendString( + bluetooth_profile_manager::kRequireAuthenticationOption); + dict_writer.AppendVariantOfBool(*(options.require_authentication)); + array_writer.CloseContainer(&dict_writer); + } + + // Send RequireAuthorization if provided. + if (options.require_authorization.get() != NULL) { + array_writer.OpenDictEntry(&dict_writer); + dict_writer.AppendString( + bluetooth_profile_manager::kRequireAuthorizationOption); + dict_writer.AppendVariantOfBool(*(options.require_authorization)); + array_writer.CloseContainer(&dict_writer); + } + + // Send AutoConnect if provided. + if (options.auto_connect.get() != NULL) { + array_writer.OpenDictEntry(&dict_writer); + dict_writer.AppendString(bluetooth_profile_manager::kAutoConnectOption); + dict_writer.AppendVariantOfBool(*(options.auto_connect)); + array_writer.CloseContainer(&dict_writer); + } + + // Send ServiceRecord if provided. + if (options.service_record.get() != NULL) { + dbus::MessageWriter dict_writer(NULL); + array_writer.OpenDictEntry(&dict_writer); + dict_writer.AppendString(bluetooth_profile_manager::kServiceRecordOption); + dict_writer.AppendVariantOfString(*(options.service_record)); + array_writer.CloseContainer(&dict_writer); + } + + // Send Version if provided. + if (options.version.get() != NULL) { + dbus::MessageWriter dict_writer(NULL); + array_writer.OpenDictEntry(&dict_writer); + dict_writer.AppendString(bluetooth_profile_manager::kVersionOption); + dict_writer.AppendVariantOfUint16(*(options.version)); + array_writer.CloseContainer(&dict_writer); + } + + // Send Features if provided. + if (options.features.get() != NULL) { + dbus::MessageWriter dict_writer(NULL); + array_writer.OpenDictEntry(&dict_writer); + dict_writer.AppendString(bluetooth_profile_manager::kFeaturesOption); + dict_writer.AppendVariantOfUint16(*(options.features)); + array_writer.CloseContainer(&dict_writer); + } + + writer.CloseContainer(&array_writer); + + object_proxy_->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothProfileManagerClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothProfileManagerClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + // BluetoothProfileManagerClient override. + void UnregisterProfile(const dbus::ObjectPath& profile_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override { + dbus::MethodCall method_call( + bluetooth_profile_manager::kBluetoothProfileManagerInterface, + bluetooth_profile_manager::kUnregisterProfile); + + dbus::MessageWriter writer(&method_call); + writer.AppendObjectPath(profile_path); + + object_proxy_->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothProfileManagerClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&BluetoothProfileManagerClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), error_callback)); + } + + protected: + void Init(dbus::Bus* bus) override { + DCHECK(bus); + object_proxy_ = bus->GetObjectProxy( + bluetooth_profile_manager::kBluetoothProfileManagerServiceName, + dbus::ObjectPath( + bluetooth_profile_manager::kBluetoothProfileManagerServicePath)); + } + + private: + // Called when a response for successful method call is received. + void OnSuccess(const base::Closure& callback, dbus::Response* response) { + DCHECK(response); + callback.Run(); + } + + // Called when a response for a failed method call is received. + void OnError(const ErrorCallback& error_callback, + dbus::ErrorResponse* response) { + // Error response has optional error message argument. + std::string error_name; + std::string error_message; + if (response) { + dbus::MessageReader reader(response); + error_name = response->GetErrorName(); + reader.PopString(&error_message); + } else { + error_name = kNoResponseError; + error_message = ""; + } + error_callback.Run(error_name, error_message); + } + + dbus::ObjectProxy* object_proxy_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothProfileManagerClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothProfileManagerClientImpl); +}; + +BluetoothProfileManagerClient::BluetoothProfileManagerClient() {} + +BluetoothProfileManagerClient::~BluetoothProfileManagerClient() {} + +BluetoothProfileManagerClient* BluetoothProfileManagerClient::Create() { + return new BluetoothProfileManagerClientImpl(); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_profile_manager_client.h b/device/bluetooth/dbus/bluetooth_profile_manager_client.h new file mode 100644 index 0000000..4b6bd96 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_profile_manager_client.h
@@ -0,0 +1,109 @@ +// Copyright 2013 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 DEVICE_BLUETOOTH_DBUS_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_ + +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/values.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluez_dbus_client.h" + +namespace bluez { + +// BluetoothProfileManagerClient is used to communicate with the profile +// manager object of the Bluetooth daemon. +class DEVICE_BLUETOOTH_EXPORT BluetoothProfileManagerClient + : public BluezDBusClient { + public: + // Species the role of the object within the profile. SYMMETRIC should be + // usually used unless the profile requires you specify as a CLIENT or as a + // SERVER. + enum ProfileRole { SYMMETRIC, CLIENT, SERVER }; + + // Options used to register a Profile object. + struct DEVICE_BLUETOOTH_EXPORT Options { + Options(); + ~Options(); + + // Human readable name for the profile. + scoped_ptr<std::string> name; + + // Primary service class UUID (if different from the actual UUID) + scoped_ptr<std::string> service; + + // Role. + enum ProfileRole role; + + // RFCOMM channel number. + scoped_ptr<uint16> channel; + + // PSM number. + scoped_ptr<uint16> psm; + + // Pairing is required before connections will be established. + scoped_ptr<bool> require_authentication; + + // Request authorization before connections will be established. + scoped_ptr<bool> require_authorization; + + // Force connections when a remote device is connected. + scoped_ptr<bool> auto_connect; + + // Manual SDP record. + scoped_ptr<std::string> service_record; + + // Profile version. + scoped_ptr<uint16> version; + + // Profile features. + scoped_ptr<uint16> features; + }; + + ~BluetoothProfileManagerClient() override; + + // The ErrorCallback is used by adapter methods to indicate failure. + // It receives two arguments: the name of the error in |error_name| and + // an optional message in |error_message|. + typedef base::Callback<void(const std::string& error_name, + const std::string& error_message)> ErrorCallback; + + // Registers a profile implementation within the local process at the + // D-bus object path |profile_path| with the remote profile manager. + // |uuid| specifies the identifier of the profile and |options| the way in + // which the profile is implemented. + virtual void RegisterProfile(const dbus::ObjectPath& profile_path, + const std::string& uuid, + const Options& options, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Unregisters the profile with the D-Bus object path |agent_path| from the + // remote profile manager. + virtual void UnregisterProfile(const dbus::ObjectPath& profile_path, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + + // Creates the instance. + static BluetoothProfileManagerClient* Create(); + + // Constants used to indicate exceptional error conditions. + static const char kNoResponseError[]; + + protected: + BluetoothProfileManagerClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothProfileManagerClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_
diff --git a/device/bluetooth/dbus/bluetooth_profile_service_provider.cc b/device/bluetooth/dbus/bluetooth_profile_service_provider.cc new file mode 100644 index 0000000..a2a23bb8 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_profile_service_provider.cc
@@ -0,0 +1,248 @@ +// Copyright 2013 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 "device/bluetooth/dbus/bluetooth_profile_service_provider.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/threading/platform_thread.h" +#include "dbus/exported_object.h" +#include "dbus/message.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +// The BluetoothProfileServiceProvider implementation used in production. +class BluetoothProfileServiceProviderImpl + : public BluetoothProfileServiceProvider { + public: + BluetoothProfileServiceProviderImpl(dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate) + : origin_thread_id_(base::PlatformThread::CurrentId()), + bus_(bus), + delegate_(delegate), + object_path_(object_path), + weak_ptr_factory_(this) { + VLOG(1) << "Creating Bluetooth Profile: " << object_path_.value(); + + exported_object_ = bus_->GetExportedObject(object_path_); + + exported_object_->ExportMethod( + bluetooth_profile::kBluetoothProfileInterface, + bluetooth_profile::kRelease, + base::Bind(&BluetoothProfileServiceProviderImpl::Release, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothProfileServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_profile::kBluetoothProfileInterface, + bluetooth_profile::kNewConnection, + base::Bind(&BluetoothProfileServiceProviderImpl::NewConnection, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothProfileServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_profile::kBluetoothProfileInterface, + bluetooth_profile::kRequestDisconnection, + base::Bind(&BluetoothProfileServiceProviderImpl::RequestDisconnection, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothProfileServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_profile::kBluetoothProfileInterface, + bluetooth_profile::kCancel, + base::Bind(&BluetoothProfileServiceProviderImpl::Cancel, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothProfileServiceProviderImpl::OnExported, + weak_ptr_factory_.GetWeakPtr())); + } + + ~BluetoothProfileServiceProviderImpl() override { + VLOG(1) << "Cleaning up Bluetooth Profile: " << object_path_.value(); + + // Unregister the object path so we can reuse with a new agent. + bus_->UnregisterExportedObject(object_path_); + } + + private: + // Returns true if the current thread is on the origin thread. + bool OnOriginThread() { + return base::PlatformThread::CurrentId() == origin_thread_id_; + } + + // Called by dbus:: when the profile is unregistered from the Bluetooth + // daemon, generally by our request. + void Release(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + delegate_->Released(); + + response_sender.Run(dbus::Response::FromMethodCall(method_call)); + } + + // Called by dbus:: when the Bluetooth daemon establishes a new connection + // to the profile. + void NewConnection(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + dbus::ObjectPath device_path; + scoped_ptr<dbus::FileDescriptor> fd(new dbus::FileDescriptor()); + dbus::MessageReader array_reader(NULL); + if (!reader.PopObjectPath(&device_path) || + !reader.PopFileDescriptor(fd.get()) || + !reader.PopArray(&array_reader)) { + LOG(WARNING) << "NewConnection called with incorrect paramters: " + << method_call->ToString(); + return; + } + + Delegate::Options options; + while (array_reader.HasMoreData()) { + dbus::MessageReader dict_entry_reader(NULL); + std::string key; + if (!array_reader.PopDictEntry(&dict_entry_reader) || + !dict_entry_reader.PopString(&key)) { + LOG(WARNING) << "NewConnection called with incorrect paramters: " + << method_call->ToString(); + } else { + if (key == bluetooth_profile::kVersionProperty) + dict_entry_reader.PopVariantOfUint16(&options.version); + else if (key == bluetooth_profile::kFeaturesProperty) + dict_entry_reader.PopVariantOfUint16(&options.features); + } + } + + Delegate::ConfirmationCallback callback = base::Bind( + &BluetoothProfileServiceProviderImpl::OnConfirmation, + weak_ptr_factory_.GetWeakPtr(), method_call, response_sender); + + delegate_->NewConnection(device_path, fd.Pass(), options, callback); + } + + // Called by dbus:: when the Bluetooth daemon is about to disconnect the + // profile. + void RequestDisconnection( + dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + dbus::ObjectPath device_path; + if (!reader.PopObjectPath(&device_path)) { + LOG(WARNING) << "RequestDisconnection called with incorrect paramters: " + << method_call->ToString(); + return; + } + + Delegate::ConfirmationCallback callback = base::Bind( + &BluetoothProfileServiceProviderImpl::OnConfirmation, + weak_ptr_factory_.GetWeakPtr(), method_call, response_sender); + + delegate_->RequestDisconnection(device_path, callback); + } + + // Called by dbus:: when the request failed before a reply was returned + // from the device. + void Cancel(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + delegate_->Cancel(); + + response_sender.Run(dbus::Response::FromMethodCall(method_call)); + } + + // Called by dbus:: when a method is exported. + void OnExported(const std::string& interface_name, + const std::string& method_name, + bool success) { + LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "." + << method_name; + } + + // Called by the Delegate in response to a method requiring confirmation. + void OnConfirmation(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender, + Delegate::Status status) { + DCHECK(OnOriginThread()); + + switch (status) { + case Delegate::SUCCESS: { + response_sender.Run(dbus::Response::FromMethodCall(method_call)); + break; + } + case Delegate::REJECTED: { + response_sender.Run(dbus::ErrorResponse::FromMethodCall( + method_call, bluetooth_profile::kErrorRejected, "rejected")); + break; + } + case Delegate::CANCELLED: { + response_sender.Run(dbus::ErrorResponse::FromMethodCall( + method_call, bluetooth_profile::kErrorCanceled, "canceled")); + break; + } + default: + NOTREACHED() << "Unexpected status code from delegate: " << status; + } + } + + // Origin thread (i.e. the UI thread in production). + base::PlatformThreadId origin_thread_id_; + + // D-Bus bus object is exported on, not owned by this object and must + // outlive it. + dbus::Bus* bus_; + + // All incoming method calls are passed on to the Delegate and a callback + // passed to generate the reply. |delegate_| is generally the object that + // owns this one, and must outlive it. + Delegate* delegate_; + + // D-Bus object path of object we are exporting, kept so we can unregister + // again in our destructor. + dbus::ObjectPath object_path_; + + // D-Bus object we are exporting, owned by this object. + scoped_refptr<dbus::ExportedObject> exported_object_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothProfileServiceProviderImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothProfileServiceProviderImpl); +}; + +BluetoothProfileServiceProvider::BluetoothProfileServiceProvider() {} + +BluetoothProfileServiceProvider::~BluetoothProfileServiceProvider() {} + +// static +BluetoothProfileServiceProvider* BluetoothProfileServiceProvider::Create( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate) { + if (!bluez::BluezDBusManager::Get()->IsUsingStub()) { + return new BluetoothProfileServiceProviderImpl(bus, object_path, delegate); + } else { + return new FakeBluetoothProfileServiceProvider(object_path, delegate); + } +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_profile_service_provider.h b/device/bluetooth/dbus/bluetooth_profile_service_provider.h new file mode 100644 index 0000000..f2db22c7 --- /dev/null +++ b/device/bluetooth/dbus/bluetooth_profile_service_provider.h
@@ -0,0 +1,120 @@ +// Copyright 2013 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 DEVICE_BLUETOOTH_DBUS_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" +#include "dbus/bus.h" +#include "dbus/file_descriptor.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" + +namespace bluez { + +// BluetoothProfileServiceProvider is used to provide a D-Bus object that the +// Bluetooth daemon can communicate with to connect application profiles. +// +// Instantiate with a chosen D-Bus object path and delegate object, and pass +// the D-Bus object path as the |agent_path| argument to the +// chromeos::BluetoothProfileManagerClient::RegisterProfile() method. +// +// When an incoming profile connection occurs, or after initiating a connection +// using the chromeos::BluetoothDeviceClient::ConnectProfile() method, the +// Bluetooth daemon will make calls to this profile object and they will be +// passed on to your Delegate object for handling. Responses should be returned +// using the callbacks supplied to those methods. +class DEVICE_BLUETOOTH_EXPORT BluetoothProfileServiceProvider { + public: + // Interface for reacting to profile requests. + class Delegate { + public: + virtual ~Delegate() {} + + // Possible status values that may be returned to callbacks on a new + // connection or a requested disconnection. Success indicates acceptance, + // reject indicates the user rejected or denied the request; cancelled + // means the user cancelled the request without confirming either way. + enum Status { SUCCESS, REJECTED, CANCELLED }; + + // Connection-specific options. + struct DEVICE_BLUETOOTH_EXPORT Options { + Options() {} + ~Options() {} + + // Profile version. + uint16 version; + + // Profile features. + uint16 features; + }; + + // The ConfirmationCallback is used for methods which require confirmation; + // it should be called with one argument, the |status| of the request + // (success, rejected or cancelled). + typedef base::Callback<void(Status)> ConfirmationCallback; + + // This method will be called when the profile is unregistered from the + // Bluetooth daemon, generally at shutdown or at the applications' request. + // It may be used to perform cleanup tasks. This corresponds to the + // org.bluez.Profile1.Release method and is renamed to avoid a conflict + // with base::Refcounted<T>. + virtual void Released() = 0; + + // This method will be called when a profile connection to the device + // with object path |device_path| is established. |callback| must be called + // to confirm the connection, or indicate rejection or cancellation. + // + // A file descriptor for the connection socket is provided in |fd|, and + // details about the specific implementation of the profile in |options|. + // + // IMPORTANT: Ownership of the file descriptor object |fd| is passed to + // the delegate by this call. The delegate is responsible for checking the + // validity of |fd| on a thread where I/O is permitted before taking the + // value. If the value is not taken, the file descriptor is closed. + // + // Ownership of |options| is NOT passed so information out of it must be + // copied if required. + virtual void NewConnection(const dbus::ObjectPath& device_path, + scoped_ptr<dbus::FileDescriptor> fd, + const Options& options, + const ConfirmationCallback& callback) = 0; + + // This method will be called when a profile connection to the device + // with object path |device_path| is disconnected. Any file descriptors + // owned by the service should be cleaned up and |callback| called to + // confirm, or indicate rejection or cancellation of the disconnection. + virtual void RequestDisconnection(const dbus::ObjectPath& device_path, + const ConfirmationCallback& callback) = 0; + + // This method will be called by the Bluetooth daemon to indicate that + // a profile request failed before a reply was returned from the device. + virtual void Cancel() = 0; + }; + + virtual ~BluetoothProfileServiceProvider(); + + // Creates the instance where |bus| is the D-Bus bus connection to export + // the object onto, |object_path| is the object path that it should have + // and |delegate| is the object to which all method calls will be passed + // and responses generated from. + static BluetoothProfileServiceProvider* Create( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate); + + protected: + BluetoothProfileServiceProvider(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothProfileServiceProvider); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_
diff --git a/device/bluetooth/dbus/bluez_dbus_client.h b/device/bluetooth/dbus/bluez_dbus_client.h new file mode 100644 index 0000000..3dd09853 --- /dev/null +++ b/device/bluetooth/dbus/bluez_dbus_client.h
@@ -0,0 +1,37 @@ +// Copyright 2013 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 DEVICE_BLUETOOTH_DBUS_BLUEZ_DBUS_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUEZ_DBUS_CLIENT_H_ + +#include "base/basictypes.h" + +namespace dbus { +class Bus; +} // namespace dbus + +namespace bluez { + +// Interface for all Bluez DBus clients handled by BluezDBusManager. It +// restricts +// access to the Init function to BluezDBusManager only to prevent +// incorrect calls. Stub clients may lift that restriction however. +class BluezDBusClient { + protected: + virtual ~BluezDBusClient() {} + + // This function is called by DBusThreadManager. Only in unit tests, which + // don't use DBusThreadManager, this function can be called through Stub + // implementations (they change Init's member visibility to public). + virtual void Init(dbus::Bus* bus) = 0; + + private: + friend class BluezDBusManager; + + DISALLOW_ASSIGN(BluezDBusClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUEZ_DBUS_CLIENT_H_
diff --git a/device/bluetooth/dbus/bluez_dbus_manager.cc b/device/bluetooth/dbus/bluez_dbus_manager.cc new file mode 100644 index 0000000..376261d --- /dev/null +++ b/device/bluetooth/dbus/bluez_dbus_manager.cc
@@ -0,0 +1,250 @@ +// Copyright (c) 2012 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 "device/bluetooth/dbus/bluez_dbus_manager.h" + +#include "base/command_line.h" +#include "base/sys_info.h" +#include "base/threading/thread.h" +#include "dbus/bus.h" +#include "dbus/dbus_statistics.h" +#include "device/bluetooth/dbus/bluetooth_adapter_client.h" +#include "device/bluetooth/dbus/bluetooth_agent_manager_client.h" +#include "device/bluetooth/dbus/bluetooth_device_client.h" +#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h" +#include "device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h" +#include "device/bluetooth/dbus/bluetooth_gatt_manager_client.h" +#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h" +#include "device/bluetooth/dbus/bluetooth_input_client.h" +#include "device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h" +#include "device/bluetooth/dbus/bluetooth_media_client.h" +#include "device/bluetooth/dbus/bluetooth_media_transport_client.h" +#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h" + +namespace bluez { + +static BluezDBusManager* g_bluez_dbus_manager = nullptr; +static bool g_using_bluez_dbus_manager_for_testing = false; + +BluezDBusManager::BluezDBusManager( + dbus::Bus* bus, + scoped_ptr<BluetoothDBusClientBundle> client_bundle) + : bus_(bus), client_bundle_(client_bundle.Pass()) {} + +BluezDBusManager::~BluezDBusManager() { + // Delete all D-Bus clients before shutting down the system bus. + client_bundle_.reset(); +} + +dbus::Bus* bluez::BluezDBusManager::GetSystemBus() { + return bus_; +} + +BluetoothAdapterClient* bluez::BluezDBusManager::GetBluetoothAdapterClient() { + return client_bundle_->bluetooth_adapter_client(); +} + +BluetoothLEAdvertisingManagerClient* +bluez::BluezDBusManager::GetBluetoothLEAdvertisingManagerClient() { + return client_bundle_->bluetooth_le_advertising_manager_client(); +} + +BluetoothAgentManagerClient* +bluez::BluezDBusManager::GetBluetoothAgentManagerClient() { + return client_bundle_->bluetooth_agent_manager_client(); +} + +BluetoothDeviceClient* bluez::BluezDBusManager::GetBluetoothDeviceClient() { + return client_bundle_->bluetooth_device_client(); +} + +BluetoothGattCharacteristicClient* +bluez::BluezDBusManager::GetBluetoothGattCharacteristicClient() { + return client_bundle_->bluetooth_gatt_characteristic_client(); +} + +BluetoothGattDescriptorClient* +bluez::BluezDBusManager::GetBluetoothGattDescriptorClient() { + return client_bundle_->bluetooth_gatt_descriptor_client(); +} + +BluetoothGattManagerClient* +bluez::BluezDBusManager::GetBluetoothGattManagerClient() { + return client_bundle_->bluetooth_gatt_manager_client(); +} + +BluetoothGattServiceClient* +bluez::BluezDBusManager::GetBluetoothGattServiceClient() { + return client_bundle_->bluetooth_gatt_service_client(); +} + +BluetoothInputClient* bluez::BluezDBusManager::GetBluetoothInputClient() { + return client_bundle_->bluetooth_input_client(); +} + +BluetoothMediaClient* bluez::BluezDBusManager::GetBluetoothMediaClient() { + return client_bundle_->bluetooth_media_client(); +} + +BluetoothMediaTransportClient* +bluez::BluezDBusManager::GetBluetoothMediaTransportClient() { + return client_bundle_->bluetooth_media_transport_client(); +} + +BluetoothProfileManagerClient* +bluez::BluezDBusManager::GetBluetoothProfileManagerClient() { + return client_bundle_->bluetooth_profile_manager_client(); +} + +void BluezDBusManager::InitializeClients() { + GetBluetoothAdapterClient()->Init(GetSystemBus()); + GetBluetoothAgentManagerClient()->Init(GetSystemBus()); + GetBluetoothDeviceClient()->Init(GetSystemBus()); + GetBluetoothGattCharacteristicClient()->Init(GetSystemBus()); + GetBluetoothGattDescriptorClient()->Init(GetSystemBus()); + GetBluetoothGattManagerClient()->Init(GetSystemBus()); + GetBluetoothGattServiceClient()->Init(GetSystemBus()); + GetBluetoothInputClient()->Init(GetSystemBus()); + GetBluetoothLEAdvertisingManagerClient()->Init(GetSystemBus()); + GetBluetoothMediaClient()->Init(GetSystemBus()); + GetBluetoothMediaTransportClient()->Init(GetSystemBus()); + GetBluetoothProfileManagerClient()->Init(GetSystemBus()); + + // This must be called after the list of clients so they've each had a + // chance to register with their object g_dbus_thread_managers. + if (GetSystemBus()) + GetSystemBus()->GetManagedObjects(); +} + +// static +void BluezDBusManager::Initialize(dbus::Bus* bus, bool use_dbus_stub) { + // If we initialize BluezDBusManager twice we may also be shutting it down + // early; do not allow that. + if (g_using_bluez_dbus_manager_for_testing) + return; + + CHECK(!g_bluez_dbus_manager); + CreateGlobalInstance(bus, use_dbus_stub); +} + +// static +scoped_ptr<BluezDBusManagerSetter> +bluez::BluezDBusManager::GetSetterForTesting() { + if (!g_using_bluez_dbus_manager_for_testing) { + g_using_bluez_dbus_manager_for_testing = true; + CreateGlobalInstance(nullptr, true); + } + + return make_scoped_ptr(new BluezDBusManagerSetter()); +} + +// static +void BluezDBusManager::CreateGlobalInstance(dbus::Bus* bus, bool use_stubs) { + CHECK(!g_bluez_dbus_manager); + g_bluez_dbus_manager = new BluezDBusManager( + bus, make_scoped_ptr(new BluetoothDBusClientBundle(use_stubs))); + g_bluez_dbus_manager->InitializeClients(); +} + +// static +bool BluezDBusManager::IsInitialized() { + return g_bluez_dbus_manager != nullptr; +} + +// static +void BluezDBusManager::Shutdown() { + // Ensure that we only shutdown BluezDBusManager once. + CHECK(g_bluez_dbus_manager); + BluezDBusManager* dbus_manager = g_bluez_dbus_manager; + g_bluez_dbus_manager = nullptr; + g_using_bluez_dbus_manager_for_testing = false; + delete dbus_manager; + VLOG(1) << "BluezDBusManager Shutdown completed"; +} + +// static +BluezDBusManager* bluez::BluezDBusManager::Get() { + CHECK(g_bluez_dbus_manager) + << "bluez::BluezDBusManager::Get() called before Initialize()"; + return g_bluez_dbus_manager; +} + +BluezDBusManagerSetter::BluezDBusManagerSetter() {} + +BluezDBusManagerSetter::~BluezDBusManagerSetter() {} + +void BluezDBusManagerSetter::SetBluetoothAdapterClient( + scoped_ptr<BluetoothAdapterClient> client) { + bluez::BluezDBusManager::Get()->client_bundle_->bluetooth_adapter_client_ = + client.Pass(); +} + +void BluezDBusManagerSetter::SetBluetoothLEAdvertisingManagerClient( + scoped_ptr<BluetoothLEAdvertisingManagerClient> client) { + bluez::BluezDBusManager::Get() + ->client_bundle_->bluetooth_le_advertising_manager_client_ = + client.Pass(); +} + +void BluezDBusManagerSetter::SetBluetoothAgentManagerClient( + scoped_ptr<BluetoothAgentManagerClient> client) { + bluez::BluezDBusManager::Get() + ->client_bundle_->bluetooth_agent_manager_client_ = client.Pass(); +} + +void BluezDBusManagerSetter::SetBluetoothDeviceClient( + scoped_ptr<BluetoothDeviceClient> client) { + bluez::BluezDBusManager::Get()->client_bundle_->bluetooth_device_client_ = + client.Pass(); +} + +void BluezDBusManagerSetter::SetBluetoothGattCharacteristicClient( + scoped_ptr<BluetoothGattCharacteristicClient> client) { + bluez::BluezDBusManager::Get() + ->client_bundle_->bluetooth_gatt_characteristic_client_ = client.Pass(); +} + +void BluezDBusManagerSetter::SetBluetoothGattDescriptorClient( + scoped_ptr<BluetoothGattDescriptorClient> client) { + bluez::BluezDBusManager::Get() + ->client_bundle_->bluetooth_gatt_descriptor_client_ = client.Pass(); +} + +void BluezDBusManagerSetter::SetBluetoothGattManagerClient( + scoped_ptr<BluetoothGattManagerClient> client) { + bluez::BluezDBusManager::Get() + ->client_bundle_->bluetooth_gatt_manager_client_ = client.Pass(); +} + +void BluezDBusManagerSetter::SetBluetoothGattServiceClient( + scoped_ptr<BluetoothGattServiceClient> client) { + bluez::BluezDBusManager::Get() + ->client_bundle_->bluetooth_gatt_service_client_ = client.Pass(); +} + +void BluezDBusManagerSetter::SetBluetoothInputClient( + scoped_ptr<BluetoothInputClient> client) { + bluez::BluezDBusManager::Get()->client_bundle_->bluetooth_input_client_ = + client.Pass(); +} + +void BluezDBusManagerSetter::SetBluetoothMediaClient( + scoped_ptr<BluetoothMediaClient> client) { + bluez::BluezDBusManager::Get()->client_bundle_->bluetooth_media_client_ = + client.Pass(); +} + +void BluezDBusManagerSetter::SetBluetoothMediaTransportClient( + scoped_ptr<BluetoothMediaTransportClient> client) { + bluez::BluezDBusManager::Get() + ->client_bundle_->bluetooth_media_transport_client_ = client.Pass(); +} + +void BluezDBusManagerSetter::SetBluetoothProfileManagerClient( + scoped_ptr<BluetoothProfileManagerClient> client) { + bluez::BluezDBusManager::Get() + ->client_bundle_->bluetooth_profile_manager_client_ = client.Pass(); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/bluez_dbus_manager.h b/device/bluetooth/dbus/bluez_dbus_manager.h new file mode 100644 index 0000000..d87fadc --- /dev/null +++ b/device/bluetooth/dbus/bluez_dbus_manager.h
@@ -0,0 +1,158 @@ +// Copyright (c) 2012 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 DEVICE_BLUETOOTH_DBUS_BLUEZ_DBUS_MANAGER_H_ +#define DEVICE_BLUETOOTH_DBUS_BLUEZ_DBUS_MANAGER_H_ + +#include <string> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_dbus_client_bundle.h" + +namespace dbus { +class Bus; +class ObjectPath; +} // namespace dbus + +namespace bluez { + +// Style Note: Clients are sorted by names. +class BluetoothAdapterClient; +class BluetoothAgentManagerClient; +class BluetoothDeviceClient; +class BluetoothGattCharacteristicClient; +class BluetoothGattDescriptorClient; +class BluetoothGattManagerClient; +class BluetoothGattServiceClient; +class BluetoothInputClient; +class BluetoothLEAdvertisingManagerClient; +class BluetoothMediaClient; +class BluetoothMediaTransportClient; +class BluetoothProfileManagerClient; +class BluezDBusManagerSetter; + +// BluezDBusManager manages manages D-Bus connections and D-Bus clients, which +// depend on the D-Bus thread to ensure the right order of shutdowns for +// the D-Bus thread, the D-Bus connections, and the D-Bus clients. +// +// CALLBACKS IN D-BUS CLIENTS: +// +// D-Bus clients managed by BluezDBusManagerSetter are guaranteed to be deleted +// after the D-Bus thread so the clients don't need to worry if new +// incoming messages arrive from the D-Bus thread during shutdown of the +// clients. The UI message loop is not running during the shutdown hence +// the UI message loop won't post tasks to D-BUS clients during the +// shutdown. However, to be extra cautious, clients should use +// WeakPtrFactory when creating callbacks that run on UI thread. See +// session_manager_client.cc for examples. +// +class DEVICE_BLUETOOTH_EXPORT BluezDBusManager { + public: + // Sets the global instance. Must be called before any calls to Get(). + // We explicitly initialize and shut down the global object, rather than + // making it a Singleton, to ensure clean startup and shutdown. + // This will initialize real or stub DBusClients depending on command-line + // arguments and whether this process runs in a ChromeOS environment. + static void Initialize(dbus::Bus* bus, bool use_dbus_stub); + + // Returns a BluezDBusManagerSetter instance that allows tests to + // replace individual D-Bus clients with their own implementations. + // Also initializes the main BluezDBusManager for testing if necessary. + static scoped_ptr<BluezDBusManagerSetter> GetSetterForTesting(); + + // Returns true if BluezDBusManager has been initialized. Call this to + // avoid initializing + shutting down BluezDBusManager more than once. + static bool IsInitialized(); + + // Destroys the global instance. + static void Shutdown(); + + // Gets the global instance. Initialize() must be called first. + static BluezDBusManager* Get(); + + // Returns true if |client| is stubbed. + bool IsUsingStub() { return client_bundle_->IsUsingStub(); } + + // Returns various D-Bus bus instances, owned by BluezDBusManager. + dbus::Bus* GetSystemBus(); + + // All returned objects are owned by BluezDBusManager. Do not use these + // pointers after BluezDBusManager has been shut down. + BluetoothAdapterClient* GetBluetoothAdapterClient(); + BluetoothLEAdvertisingManagerClient* GetBluetoothLEAdvertisingManagerClient(); + BluetoothAgentManagerClient* GetBluetoothAgentManagerClient(); + BluetoothDeviceClient* GetBluetoothDeviceClient(); + BluetoothGattCharacteristicClient* GetBluetoothGattCharacteristicClient(); + BluetoothGattDescriptorClient* GetBluetoothGattDescriptorClient(); + BluetoothGattManagerClient* GetBluetoothGattManagerClient(); + BluetoothGattServiceClient* GetBluetoothGattServiceClient(); + BluetoothInputClient* GetBluetoothInputClient(); + BluetoothMediaClient* GetBluetoothMediaClient(); + BluetoothMediaTransportClient* GetBluetoothMediaTransportClient(); + BluetoothProfileManagerClient* GetBluetoothProfileManagerClient(); + + private: + friend class BluezDBusManagerSetter; + + // Creates a new BluezDBusManager using the DBusClients set in + // |client_bundle|. + explicit BluezDBusManager( + dbus::Bus* bus, + scoped_ptr<BluetoothDBusClientBundle> client_bundle); + ~BluezDBusManager(); + + // Creates a global instance of BluezDBusManager. Cannot be called more than + // once. + static void CreateGlobalInstance(dbus::Bus* bus, bool use_stubs); + + // Initializes all currently stored DBusClients with the system bus and + // performs additional setup. + void InitializeClients(); + + dbus::Bus* bus_; + scoped_ptr<BluetoothDBusClientBundle> client_bundle_; + + DISALLOW_COPY_AND_ASSIGN(BluezDBusManager); +}; + +class DEVICE_BLUETOOTH_EXPORT BluezDBusManagerSetter { + public: + ~BluezDBusManagerSetter(); + + void SetBluetoothAdapterClient(scoped_ptr<BluetoothAdapterClient> client); + void SetBluetoothLEAdvertisingManagerClient( + scoped_ptr<BluetoothLEAdvertisingManagerClient> client); + void SetBluetoothAgentManagerClient( + scoped_ptr<BluetoothAgentManagerClient> client); + void SetBluetoothDeviceClient(scoped_ptr<BluetoothDeviceClient> client); + void SetBluetoothGattCharacteristicClient( + scoped_ptr<BluetoothGattCharacteristicClient> client); + void SetBluetoothGattDescriptorClient( + scoped_ptr<BluetoothGattDescriptorClient> client); + void SetBluetoothGattManagerClient( + scoped_ptr<BluetoothGattManagerClient> client); + void SetBluetoothGattServiceClient( + scoped_ptr<BluetoothGattServiceClient> client); + void SetBluetoothInputClient(scoped_ptr<BluetoothInputClient> client); + void SetBluetoothMediaClient(scoped_ptr<BluetoothMediaClient> client); + void SetBluetoothMediaTransportClient( + scoped_ptr<BluetoothMediaTransportClient> client); + void SetBluetoothProfileManagerClient( + scoped_ptr<BluetoothProfileManagerClient> client); + + private: + friend class BluezDBusManager; + + BluezDBusManagerSetter(); + + DISALLOW_COPY_AND_ASSIGN(BluezDBusManagerSetter); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_BLUEZ_DBUS_MANAGER_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_adapter_client.cc b/device/bluetooth/dbus/fake_bluetooth_adapter_client.cc new file mode 100644 index 0000000..f928768 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_adapter_client.cc
@@ -0,0 +1,296 @@ +// Copyright (c) 2013 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 "device/bluetooth/dbus/fake_bluetooth_adapter_client.h" + +#include "base/location.h" +#include "base/logging.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" +#include "base/time/time.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_device_client.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +namespace { + +// Default interval for delayed tasks. +const int kSimulationIntervalMs = 750; + +} // namespace + +const char FakeBluetoothAdapterClient::kAdapterPath[] = "/fake/hci0"; +const char FakeBluetoothAdapterClient::kAdapterName[] = "Fake Adapter"; +const char FakeBluetoothAdapterClient::kAdapterAddress[] = "01:1A:2B:1A:2B:03"; + +const char FakeBluetoothAdapterClient::kSecondAdapterPath[] = "/fake/hci1"; +const char FakeBluetoothAdapterClient::kSecondAdapterName[] = + "Second Fake Adapter"; +const char FakeBluetoothAdapterClient::kSecondAdapterAddress[] = + "00:DE:51:10:01:00"; + +FakeBluetoothAdapterClient::Properties::Properties( + const PropertyChangedCallback& callback) + : BluetoothAdapterClient::Properties( + NULL, + bluetooth_adapter::kBluetoothAdapterInterface, + callback) {} + +FakeBluetoothAdapterClient::Properties::~Properties() {} + +void FakeBluetoothAdapterClient::Properties::Get( + dbus::PropertyBase* property, + dbus::PropertySet::GetCallback callback) { + VLOG(1) << "Get " << property->name(); + callback.Run(false); +} + +void FakeBluetoothAdapterClient::Properties::GetAll() { + VLOG(1) << "GetAll"; +} + +void FakeBluetoothAdapterClient::Properties::Set( + dbus::PropertyBase* property, + dbus::PropertySet::SetCallback callback) { + VLOG(1) << "Set " << property->name(); + if (property->name() == powered.name() || property->name() == alias.name() || + property->name() == discoverable.name() || + property->name() == discoverable_timeout.name()) { + callback.Run(true); + property->ReplaceValueWithSetValue(); + } else { + callback.Run(false); + } +} + +FakeBluetoothAdapterClient::FakeBluetoothAdapterClient() + : visible_(true), + second_visible_(false), + discovering_count_(0), + set_discovery_filter_should_fail_(false), + simulation_interval_ms_(kSimulationIntervalMs) { + properties_.reset(new Properties(base::Bind( + &FakeBluetoothAdapterClient::OnPropertyChanged, base::Unretained(this)))); + + properties_->address.ReplaceValue(kAdapterAddress); + properties_->name.ReplaceValue("Fake Adapter (Name)"); + properties_->alias.ReplaceValue(kAdapterName); + properties_->pairable.ReplaceValue(true); + + second_properties_.reset(new Properties(base::Bind( + &FakeBluetoothAdapterClient::OnPropertyChanged, base::Unretained(this)))); + + second_properties_->address.ReplaceValue(kSecondAdapterAddress); + second_properties_->name.ReplaceValue("Second Fake Adapter (Name)"); + second_properties_->alias.ReplaceValue(kSecondAdapterName); + second_properties_->pairable.ReplaceValue(true); +} + +FakeBluetoothAdapterClient::~FakeBluetoothAdapterClient() {} + +void FakeBluetoothAdapterClient::Init(dbus::Bus* bus) {} + +void FakeBluetoothAdapterClient::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void FakeBluetoothAdapterClient::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +std::vector<dbus::ObjectPath> FakeBluetoothAdapterClient::GetAdapters() { + std::vector<dbus::ObjectPath> object_paths; + if (visible_) + object_paths.push_back(dbus::ObjectPath(kAdapterPath)); + if (second_visible_) + object_paths.push_back(dbus::ObjectPath(kSecondAdapterPath)); + return object_paths; +} + +FakeBluetoothAdapterClient::Properties* +FakeBluetoothAdapterClient::GetProperties(const dbus::ObjectPath& object_path) { + if (object_path == dbus::ObjectPath(kAdapterPath)) + return properties_.get(); + else if (object_path == dbus::ObjectPath(kSecondAdapterPath)) + return second_properties_.get(); + else + return NULL; +} + +void FakeBluetoothAdapterClient::StartDiscovery( + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + if (object_path != dbus::ObjectPath(kAdapterPath)) { + PostDelayedTask(base::Bind(error_callback, kNoResponseError, "")); + return; + } + + ++discovering_count_; + VLOG(1) << "StartDiscovery: " << object_path.value() << ", " + << "count is now " << discovering_count_; + PostDelayedTask(callback); + + if (discovering_count_ == 1) { + properties_->discovering.ReplaceValue(true); + + FakeBluetoothDeviceClient* device_client = + static_cast<FakeBluetoothDeviceClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()); + device_client->BeginDiscoverySimulation(dbus::ObjectPath(kAdapterPath)); + } +} + +void FakeBluetoothAdapterClient::StopDiscovery( + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + if (object_path != dbus::ObjectPath(kAdapterPath)) { + PostDelayedTask(base::Bind(error_callback, kNoResponseError, "")); + return; + } + + if (!discovering_count_) { + LOG(WARNING) << "StopDiscovery called when not discovering"; + PostDelayedTask(base::Bind(error_callback, kNoResponseError, "")); + return; + } + + --discovering_count_; + VLOG(1) << "StopDiscovery: " << object_path.value() << ", " + << "count is now " << discovering_count_; + PostDelayedTask(callback); + + if (discovering_count_ == 0) { + FakeBluetoothDeviceClient* device_client = + static_cast<FakeBluetoothDeviceClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()); + device_client->EndDiscoverySimulation(dbus::ObjectPath(kAdapterPath)); + + if (simulation_interval_ms_ > 100) { + device_client->BeginIncomingPairingSimulation( + dbus::ObjectPath(kAdapterPath)); + } + + discovery_filter_.reset(); + properties_->discovering.ReplaceValue(false); + } +} + +void FakeBluetoothAdapterClient::RemoveDevice( + const dbus::ObjectPath& object_path, + const dbus::ObjectPath& device_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + if (object_path != dbus::ObjectPath(kAdapterPath)) { + error_callback.Run(kNoResponseError, ""); + return; + } + + VLOG(1) << "RemoveDevice: " << object_path.value() << " " + << device_path.value(); + callback.Run(); + + FakeBluetoothDeviceClient* device_client = + static_cast<FakeBluetoothDeviceClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()); + device_client->RemoveDevice(dbus::ObjectPath(kAdapterPath), device_path); +} + +void FakeBluetoothAdapterClient::MakeSetDiscoveryFilterFail() { + set_discovery_filter_should_fail_ = true; +} + +void FakeBluetoothAdapterClient::SetDiscoveryFilter( + const dbus::ObjectPath& object_path, + const DiscoveryFilter& discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) { + if (object_path != dbus::ObjectPath(kAdapterPath)) { + PostDelayedTask(base::Bind(error_callback, kNoResponseError, "")); + return; + } + VLOG(1) << "SetDiscoveryFilter: " << object_path.value(); + + if (set_discovery_filter_should_fail_) { + PostDelayedTask(base::Bind(error_callback, kNoResponseError, "")); + set_discovery_filter_should_fail_ = false; + return; + } + + discovery_filter_.reset(new DiscoveryFilter()); + discovery_filter_->CopyFrom(discovery_filter); + PostDelayedTask(callback); +} + +void FakeBluetoothAdapterClient::SetSimulationIntervalMs(int interval_ms) { + simulation_interval_ms_ = interval_ms; +} + +BluetoothAdapterClient::DiscoveryFilter* +FakeBluetoothAdapterClient::GetDiscoveryFilter() { + return discovery_filter_.get(); +} + +void FakeBluetoothAdapterClient::SetVisible(bool visible) { + if (visible && !visible_) { + // Adapter becoming visible + visible_ = visible; + + FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, + AdapterAdded(dbus::ObjectPath(kAdapterPath))); + + } else if (visible_ && !visible) { + // Adapter becoming invisible + visible_ = visible; + + FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, + AdapterRemoved(dbus::ObjectPath(kAdapterPath))); + } +} + +void FakeBluetoothAdapterClient::SetSecondVisible(bool visible) { + if (visible && !second_visible_) { + // Second adapter becoming visible + second_visible_ = visible; + + FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, + AdapterAdded(dbus::ObjectPath(kSecondAdapterPath))); + + } else if (second_visible_ && !visible) { + // Second adapter becoming invisible + second_visible_ = visible; + + FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, + AdapterRemoved(dbus::ObjectPath(kSecondAdapterPath))); + } +} + +void FakeBluetoothAdapterClient::OnPropertyChanged( + const std::string& property_name) { + if (property_name == properties_->powered.name() && + !properties_->powered.value()) { + VLOG(1) << "Adapter powered off"; + + if (discovering_count_) { + discovering_count_ = 0; + properties_->discovering.ReplaceValue(false); + } + } + + FOR_EACH_OBSERVER( + BluetoothAdapterClient::Observer, observers_, + AdapterPropertyChanged(dbus::ObjectPath(kAdapterPath), property_name)); +} + +void FakeBluetoothAdapterClient::PostDelayedTask( + const base::Closure& callback) { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, callback, + base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_adapter_client.h b/device/bluetooth/dbus/fake_bluetooth_adapter_client.h new file mode 100644 index 0000000..0dced89c --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_adapter_client.h
@@ -0,0 +1,118 @@ +// Copyright (c) 2013 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 DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_ADAPTER_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_ADAPTER_CLIENT_H_ + +#include <vector> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/observer_list.h" +#include "dbus/object_path.h" +#include "dbus/property.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_adapter_client.h" + +namespace bluez { + +// FakeBluetoothAdapterClient simulates the behavior of the Bluetooth Daemon +// adapter objects and is used both in test cases in place of a mock and on +// the Linux desktop. +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothAdapterClient + : public BluetoothAdapterClient { + public: + struct Properties : public BluetoothAdapterClient::Properties { + explicit Properties(const PropertyChangedCallback& callback); + ~Properties() override; + + // dbus::PropertySet override + void Get(dbus::PropertyBase* property, + dbus::PropertySet::GetCallback callback) override; + void GetAll() override; + void Set(dbus::PropertyBase* property, + dbus::PropertySet::SetCallback callback) override; + }; + + FakeBluetoothAdapterClient(); + ~FakeBluetoothAdapterClient() override; + + // BluetoothAdapterClient overrides + void Init(dbus::Bus* bus) override; + void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; + std::vector<dbus::ObjectPath> GetAdapters() override; + Properties* GetProperties(const dbus::ObjectPath& object_path) override; + void StartDiscovery(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void StopDiscovery(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void RemoveDevice(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& device_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void SetDiscoveryFilter(const dbus::ObjectPath& object_path, + const DiscoveryFilter& discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + + // Sets the current simulation timeout interval. + void SetSimulationIntervalMs(int interval_ms); + + // Returns current discovery filter in use by this adapter. + DiscoveryFilter* GetDiscoveryFilter(); + + // Make SetDiscoveryFilter fail when called next time. + void MakeSetDiscoveryFilterFail(); + + // Mark the adapter and second adapter as visible or invisible. + void SetVisible(bool visible); + void SetSecondVisible(bool visible); + + // Object path, name and addresses of the adapters we emulate. + static const char kAdapterPath[]; + static const char kAdapterName[]; + static const char kAdapterAddress[]; + + static const char kSecondAdapterPath[]; + static const char kSecondAdapterName[]; + static const char kSecondAdapterAddress[]; + + private: + // Property callback passed when we create Properties* structures. + void OnPropertyChanged(const std::string& property_name); + + // Posts the delayed task represented by |callback| onto the current + // message loop to be executed after |simulation_interval_ms_| milliseconds. + void PostDelayedTask(const base::Closure& callback); + + // List of observers interested in event notifications from us. + base::ObserverList<Observer> observers_; + + // Static properties we return. + scoped_ptr<Properties> properties_; + scoped_ptr<Properties> second_properties_; + + // Whether the adapter and second adapter should be visible or not. + bool visible_; + bool second_visible_; + + // Number of times we've been asked to discover. + int discovering_count_; + + // Current discovery filter + scoped_ptr<DiscoveryFilter> discovery_filter_; + + // When set, next call to SetDiscoveryFilter would fail. + bool set_discovery_filter_should_fail_; + + // Current timeout interval used when posting delayed tasks. + int simulation_interval_ms_; +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_ADAPTER_CLIENT_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.cc b/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.cc new file mode 100644 index 0000000..59044412 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.cc
@@ -0,0 +1,78 @@ +// Copyright (c) 2013 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 "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h" + +#include "base/logging.h" +#include "device/bluetooth/dbus/fake_bluetooth_agent_service_provider.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +FakeBluetoothAgentManagerClient::FakeBluetoothAgentManagerClient() + : service_provider_(NULL) {} + +FakeBluetoothAgentManagerClient::~FakeBluetoothAgentManagerClient() {} + +void FakeBluetoothAgentManagerClient::Init(dbus::Bus* bus) {} + +void FakeBluetoothAgentManagerClient::RegisterAgent( + const dbus::ObjectPath& agent_path, + const std::string& capability, + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "RegisterAgent: " << agent_path.value(); + + if (service_provider_ == NULL) { + error_callback.Run(bluetooth_agent_manager::kErrorInvalidArguments, + "No agent created"); + } else if (service_provider_->object_path_ != agent_path) { + error_callback.Run(bluetooth_agent_manager::kErrorAlreadyExists, + "Agent already registered"); + } else { + callback.Run(); + } +} + +void FakeBluetoothAgentManagerClient::UnregisterAgent( + const dbus::ObjectPath& agent_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "UnregisterAgent: " << agent_path.value(); + if (service_provider_ == NULL) { + error_callback.Run(bluetooth_agent_manager::kErrorDoesNotExist, + "No agent registered"); + } else if (service_provider_->object_path_ != agent_path) { + error_callback.Run(bluetooth_agent_manager::kErrorDoesNotExist, + "Agent still registered"); + } else { + callback.Run(); + } +} + +void FakeBluetoothAgentManagerClient::RequestDefaultAgent( + const dbus::ObjectPath& agent_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "RequestDefaultAgent: " << agent_path.value(); + callback.Run(); +} + +void FakeBluetoothAgentManagerClient::RegisterAgentServiceProvider( + FakeBluetoothAgentServiceProvider* service_provider) { + service_provider_ = service_provider; +} + +void FakeBluetoothAgentManagerClient::UnregisterAgentServiceProvider( + FakeBluetoothAgentServiceProvider* service_provider) { + if (service_provider_ == service_provider) + service_provider_ = NULL; +} + +FakeBluetoothAgentServiceProvider* +FakeBluetoothAgentManagerClient::GetAgentServiceProvider() { + return service_provider_; +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h b/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h new file mode 100644 index 0000000..d5c83cf --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h
@@ -0,0 +1,57 @@ +// Copyright (c) 2013 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 DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_AGENT_MANAGER_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_AGENT_MANAGER_CLIENT_H_ + +#include "base/bind.h" +#include "base/callback.h" +#include "base/observer_list.h" +#include "dbus/object_path.h" +#include "dbus/property.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_agent_manager_client.h" + +namespace bluez { + +class FakeBluetoothAgentServiceProvider; + +// FakeBluetoothAgentManagerClient simulates the behavior of the Bluetooth +// Daemon's agent manager object and is used both in test cases in place of a +// mock and on the Linux desktop. +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothAgentManagerClient + : public BluetoothAgentManagerClient { + public: + FakeBluetoothAgentManagerClient(); + ~FakeBluetoothAgentManagerClient() override; + + // BluetoothAgentManagerClient overrides + void Init(dbus::Bus* bus) override; + void RegisterAgent(const dbus::ObjectPath& agent_path, + const std::string& capability, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void UnregisterAgent(const dbus::ObjectPath& agent_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void RequestDefaultAgent(const dbus::ObjectPath& agent_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + + // Register, unregister and retrieve pointers to agent service providers. + void RegisterAgentServiceProvider( + FakeBluetoothAgentServiceProvider* service_provider); + void UnregisterAgentServiceProvider( + FakeBluetoothAgentServiceProvider* service_provider); + FakeBluetoothAgentServiceProvider* GetAgentServiceProvider(); + + private: + // The single agent service provider we permit, owned by the application + // using it. + FakeBluetoothAgentServiceProvider* service_provider_; +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_AGENT_MANAGER_CLIENT_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_agent_service_provider.cc b/device/bluetooth/dbus/fake_bluetooth_agent_service_provider.cc new file mode 100644 index 0000000..777deb0e0 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_agent_service_provider.cc
@@ -0,0 +1,102 @@ +// Copyright (c) 2013 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 "device/bluetooth/dbus/fake_bluetooth_agent_service_provider.h" + +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h" + +namespace bluez { + +FakeBluetoothAgentServiceProvider::FakeBluetoothAgentServiceProvider( + const dbus::ObjectPath& object_path, + Delegate* delegate) + : object_path_(object_path), delegate_(delegate) { + VLOG(1) << "Creating Bluetooth Agent: " << object_path_.value(); + + FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client = + static_cast<FakeBluetoothAgentManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothAgentManagerClient()); + fake_bluetooth_agent_manager_client->RegisterAgentServiceProvider(this); +} + +FakeBluetoothAgentServiceProvider::~FakeBluetoothAgentServiceProvider() { + VLOG(1) << "Cleaning up Bluetooth Agent: " << object_path_.value(); + + FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client = + static_cast<FakeBluetoothAgentManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothAgentManagerClient()); + fake_bluetooth_agent_manager_client->UnregisterAgentServiceProvider(this); +} + +void FakeBluetoothAgentServiceProvider::Release() { + VLOG(1) << object_path_.value() << ": Release"; + delegate_->Released(); +} + +void FakeBluetoothAgentServiceProvider::RequestPinCode( + const dbus::ObjectPath& device_path, + const Delegate::PinCodeCallback& callback) { + VLOG(1) << object_path_.value() << ": RequestPinCode for " + << device_path.value(); + delegate_->RequestPinCode(device_path, callback); +} + +void FakeBluetoothAgentServiceProvider::DisplayPinCode( + const dbus::ObjectPath& device_path, + const std::string& pincode) { + VLOG(1) << object_path_.value() << ": DisplayPincode " << pincode << " for " + << device_path.value(); + delegate_->DisplayPinCode(device_path, pincode); +} + +void FakeBluetoothAgentServiceProvider::RequestPasskey( + const dbus::ObjectPath& device_path, + const Delegate::PasskeyCallback& callback) { + VLOG(1) << object_path_.value() << ": RequestPasskey for " + << device_path.value(); + delegate_->RequestPasskey(device_path, callback); +} + +void FakeBluetoothAgentServiceProvider::DisplayPasskey( + const dbus::ObjectPath& device_path, + uint32 passkey, + int16 entered) { + VLOG(1) << object_path_.value() << ": DisplayPasskey " << passkey << " (" + << entered << " entered) for " << device_path.value(); + delegate_->DisplayPasskey(device_path, passkey, entered); +} + +void FakeBluetoothAgentServiceProvider::RequestConfirmation( + const dbus::ObjectPath& device_path, + uint32 passkey, + const Delegate::ConfirmationCallback& callback) { + VLOG(1) << object_path_.value() << ": RequestConfirmation " << passkey + << " for " << device_path.value(); + delegate_->RequestConfirmation(device_path, passkey, callback); +} + +void FakeBluetoothAgentServiceProvider::RequestAuthorization( + const dbus::ObjectPath& device_path, + const Delegate::ConfirmationCallback& callback) { + VLOG(1) << object_path_.value() << ": RequestAuthorization for " + << device_path.value(); + delegate_->RequestAuthorization(device_path, callback); +} + +void FakeBluetoothAgentServiceProvider::AuthorizeService( + const dbus::ObjectPath& device_path, + const std::string& uuid, + const Delegate::ConfirmationCallback& callback) { + VLOG(1) << object_path_.value() << ": AuthorizeService " << uuid << " for " + << device_path.value(); + delegate_->AuthorizeService(device_path, uuid, callback); +} + +void FakeBluetoothAgentServiceProvider::Cancel() { + VLOG(1) << object_path_.value() << ": Cancel"; + delegate_->Cancel(); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_agent_service_provider.h b/device/bluetooth/dbus/fake_bluetooth_agent_service_provider.h new file mode 100644 index 0000000..e3c8cd4 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_agent_service_provider.h
@@ -0,0 +1,68 @@ +// Copyright (c) 2013 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 DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_ + +#include "base/bind.h" +#include "base/callback.h" +#include "base/observer_list.h" +#include "dbus/object_path.h" +#include "dbus/property.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_agent_service_provider.h" + +namespace bluez { + +class FakeBluetoothAgentManagerClient; + +// FakeBluetoothAgentServiceProvider simulates the behavior of a local +// Bluetooth agent object and is used both in test cases in place of a +// mock and on the Linux desktop. +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothAgentServiceProvider + : public BluetoothAgentServiceProvider { + public: + FakeBluetoothAgentServiceProvider(const dbus::ObjectPath& object_path, + Delegate* delegate); + ~FakeBluetoothAgentServiceProvider() override; + + // Each of these calls the equivalent BluetoothAgentServiceProvider::Delegate + // method on the object passed on construction. + virtual void Release(); + virtual void RequestPinCode(const dbus::ObjectPath& device_path, + const Delegate::PinCodeCallback& callback); + virtual void DisplayPinCode(const dbus::ObjectPath& device_path, + const std::string& pincode); + virtual void RequestPasskey(const dbus::ObjectPath& device_path, + const Delegate::PasskeyCallback& callback); + virtual void DisplayPasskey(const dbus::ObjectPath& device_path, + uint32 passkey, + int16 entered); + virtual void RequestConfirmation( + const dbus::ObjectPath& device_path, + uint32 passkey, + const Delegate::ConfirmationCallback& callback); + virtual void RequestAuthorization( + const dbus::ObjectPath& device_path, + const Delegate::ConfirmationCallback& callback); + virtual void AuthorizeService(const dbus::ObjectPath& device_path, + const std::string& uuid, + const Delegate::ConfirmationCallback& callback); + virtual void Cancel(); + + private: + friend class FakeBluetoothAgentManagerClient; + + // D-Bus object path we are faking. + dbus::ObjectPath object_path_; + + // All incoming method calls are passed on to the Delegate and a callback + // passed to generate the reply. |delegate_| is generally the object that + // owns this one, and must outlive it. + Delegate* delegate_; +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_device_client.cc b/device/bluetooth/dbus/fake_bluetooth_device_client.cc new file mode 100644 index 0000000..83d31dd4 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_device_client.cc
@@ -0,0 +1,1662 @@ +// Copyright (c) 2013 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 "device/bluetooth/dbus/fake_bluetooth_device_client.h" + +#include <fcntl.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <unistd.h> + +#include <algorithm> +#include <string> +#include <utility> + +#include "base/location.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/rand_util.h" +#include "base/single_thread_task_runner.h" +#include "base/stl_util.h" +#include "base/thread_task_runner_handle.h" +#include "base/threading/worker_pool.h" +#include "base/time/time.h" +#include "dbus/file_descriptor.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_agent_service_provider.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_input_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace { + +// Default interval between simulated events. +const int kSimulationIntervalMs = 750; + +// Minimum and maximum bounds for randomly generated RSSI values. +const int kMinRSSI = -90; +const int kMaxRSSI = -30; + +// The default value of connection info properties from GetConnInfo(). +const int kUnkownPower = 127; + +// This is meant to delay the removal of a pre defined device until the +// developer has time to see it. +const int kVanishingDevicePairTimeMultiplier = 4; + +// Meant to delay a pair request for an observable amount of time. +const int kIncomingSimulationPairTimeMultiplier = 45; + +// Meant to delay a request that asks for pair requests for an observable +// amount of time. +const int kIncomingSimulationStartPairTimeMultiplier = 30; + +// This allows the PIN code dialog to be shown for a long enough time to see +// the PIN code UI in detail. +const int kPinCodeDevicePairTimeMultiplier = 7; + +// This allows the pairing dialog to be shown for a long enough time to see +// its UI in detail. +const int kSimulateNormalPairTimeMultiplier = 3; + +void SimulatedProfileSocket(int fd) { + // Simulate a server-side socket of a profile; read data from the socket, + // write it back, and then close. + char buf[1024]; + ssize_t len; + ssize_t count; + + len = read(fd, buf, sizeof buf); + if (len < 0) { + close(fd); + return; + } + + count = len; + len = write(fd, buf, count); + if (len < 0) { + close(fd); + return; + } + + close(fd); +} + +void SimpleErrorCallback(const std::string& error_name, + const std::string& error_message) { + VLOG(1) << "Bluetooth Error: " << error_name << ": " << error_message; +} + +} // namespace + +namespace bluez { + +const char FakeBluetoothDeviceClient::kTestPinCode[] = "123456"; +const int FakeBluetoothDeviceClient::kTestPassKey = 123456; + +const char FakeBluetoothDeviceClient::kPairingMethodNone[] = "None"; +const char FakeBluetoothDeviceClient::kPairingMethodPinCode[] = "PIN Code"; +const char FakeBluetoothDeviceClient::kPairingMethodPassKey[] = "PassKey"; + +const char FakeBluetoothDeviceClient::kPairingActionConfirmation[] = + "Confirmation"; +const char FakeBluetoothDeviceClient::kPairingActionDisplay[] = "Display"; +const char FakeBluetoothDeviceClient::kPairingActionFail[] = "Fail"; +const char FakeBluetoothDeviceClient::kPairingActionRequest[] = "Request"; + +const char FakeBluetoothDeviceClient::kPairedDevicePath[] = "/fake/hci0/dev0"; +const char FakeBluetoothDeviceClient::kPairedDeviceAddress[] = + "00:11:22:33:44:55"; +const char FakeBluetoothDeviceClient::kPairedDeviceName[] = "Fake Device"; +const uint32 FakeBluetoothDeviceClient::kPairedDeviceClass = 0x000104; + +const char FakeBluetoothDeviceClient::kLegacyAutopairPath[] = "/fake/hci0/dev1"; +const char FakeBluetoothDeviceClient::kLegacyAutopairAddress[] = + "28:CF:DA:00:00:00"; +const char FakeBluetoothDeviceClient::kLegacyAutopairName[] = + "Bluetooth 2.0 Mouse"; +const uint32 FakeBluetoothDeviceClient::kLegacyAutopairClass = 0x002580; + +const char FakeBluetoothDeviceClient::kDisplayPinCodePath[] = "/fake/hci0/dev2"; +const char FakeBluetoothDeviceClient::kDisplayPinCodeAddress[] = + "28:37:37:00:00:00"; +const char FakeBluetoothDeviceClient::kDisplayPinCodeName[] = + "Bluetooth 2.0 Keyboard"; +const uint32 FakeBluetoothDeviceClient::kDisplayPinCodeClass = 0x002540; + +const char FakeBluetoothDeviceClient::kVanishingDevicePath[] = + "/fake/hci0/dev3"; +const char FakeBluetoothDeviceClient::kVanishingDeviceAddress[] = + "01:02:03:04:05:06"; +const char FakeBluetoothDeviceClient::kVanishingDeviceName[] = + "Vanishing Device"; +const uint32 FakeBluetoothDeviceClient::kVanishingDeviceClass = 0x000104; + +const char FakeBluetoothDeviceClient::kConnectUnpairablePath[] = + "/fake/hci0/dev4"; +const char FakeBluetoothDeviceClient::kConnectUnpairableAddress[] = + "7C:ED:8D:00:00:00"; +const char FakeBluetoothDeviceClient::kConnectUnpairableName[] = + "Unpairable Device"; +const uint32 FakeBluetoothDeviceClient::kConnectUnpairableClass = 0x002580; + +const char FakeBluetoothDeviceClient::kDisplayPasskeyPath[] = "/fake/hci0/dev5"; +const char FakeBluetoothDeviceClient::kDisplayPasskeyAddress[] = + "00:0F:F6:00:00:00"; +const char FakeBluetoothDeviceClient::kDisplayPasskeyName[] = + "Bluetooth 2.1+ Keyboard"; +const uint32 FakeBluetoothDeviceClient::kDisplayPasskeyClass = 0x002540; + +const char FakeBluetoothDeviceClient::kRequestPinCodePath[] = "/fake/hci0/dev6"; +const char FakeBluetoothDeviceClient::kRequestPinCodeAddress[] = + "00:24:BE:00:00:00"; +const char FakeBluetoothDeviceClient::kRequestPinCodeName[] = "PIN Device"; +const uint32 FakeBluetoothDeviceClient::kRequestPinCodeClass = 0x240408; + +const char FakeBluetoothDeviceClient::kConfirmPasskeyPath[] = "/fake/hci0/dev7"; +const char FakeBluetoothDeviceClient::kConfirmPasskeyAddress[] = + "20:7D:74:00:00:00"; +const char FakeBluetoothDeviceClient::kConfirmPasskeyName[] = "Phone"; +const uint32 FakeBluetoothDeviceClient::kConfirmPasskeyClass = 0x7a020c; + +const char FakeBluetoothDeviceClient::kRequestPasskeyPath[] = "/fake/hci0/dev8"; +const char FakeBluetoothDeviceClient::kRequestPasskeyAddress[] = + "20:7D:74:00:00:01"; +const char FakeBluetoothDeviceClient::kRequestPasskeyName[] = "Passkey Device"; +const uint32 FakeBluetoothDeviceClient::kRequestPasskeyClass = 0x7a020c; + +const char FakeBluetoothDeviceClient::kUnconnectableDevicePath[] = + "/fake/hci0/dev9"; +const char FakeBluetoothDeviceClient::kUnconnectableDeviceAddress[] = + "20:7D:74:00:00:02"; +const char FakeBluetoothDeviceClient::kUnconnectableDeviceName[] = + "Unconnectable Device"; +const uint32 FakeBluetoothDeviceClient::kUnconnectableDeviceClass = 0x7a020c; + +const char FakeBluetoothDeviceClient::kUnpairableDevicePath[] = + "/fake/hci0/devA"; +const char FakeBluetoothDeviceClient::kUnpairableDeviceAddress[] = + "20:7D:74:00:00:03"; +const char FakeBluetoothDeviceClient::kUnpairableDeviceName[] = + "Unpairable Device"; +const uint32 FakeBluetoothDeviceClient::kUnpairableDeviceClass = 0x002540; + +const char FakeBluetoothDeviceClient::kJustWorksPath[] = "/fake/hci0/devB"; +const char FakeBluetoothDeviceClient::kJustWorksAddress[] = "00:0C:8A:00:00:00"; +const char FakeBluetoothDeviceClient::kJustWorksName[] = "Just-Works Device"; +const uint32 FakeBluetoothDeviceClient::kJustWorksClass = 0x240428; + +const char FakeBluetoothDeviceClient::kLowEnergyPath[] = "/fake/hci0/devC"; +const char FakeBluetoothDeviceClient::kLowEnergyAddress[] = "00:1A:11:00:15:30"; +const char FakeBluetoothDeviceClient::kLowEnergyName[] = + "Bluetooth 4.0 Heart Rate Monitor"; +const uint32 FakeBluetoothDeviceClient::kLowEnergyClass = + 0x000918; // Major class "Health", Minor class "Heart/Pulse Rate Monitor." + +const char FakeBluetoothDeviceClient::kPairedUnconnectableDevicePath[] = + "/fake/hci0/devD"; +const char FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress[] = + "20:7D:74:00:00:04"; +const char FakeBluetoothDeviceClient::kPairedUnconnectableDeviceName[] = + "Paired Unconnectable Device"; +const uint32 FakeBluetoothDeviceClient::kPairedUnconnectableDeviceClass = + 0x000104; + +const char FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDevicePath[] = + "/fake/hci0/devE"; +const char + FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDeviceAddress[] = + "11:22:33:44:55:66"; +const char FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDeviceName[] = + "Connected Pairable Device"; +const uint32 FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDeviceClass = + 0x7a020c; + +FakeBluetoothDeviceClient::Properties::Properties( + const PropertyChangedCallback& callback) + : BluetoothDeviceClient::Properties( + NULL, + bluetooth_device::kBluetoothDeviceInterface, + callback) {} + +FakeBluetoothDeviceClient::Properties::~Properties() {} + +void FakeBluetoothDeviceClient::Properties::Get( + dbus::PropertyBase* property, + dbus::PropertySet::GetCallback callback) { + VLOG(1) << "Get " << property->name(); + callback.Run(false); +} + +void FakeBluetoothDeviceClient::Properties::GetAll() { + VLOG(1) << "GetAll"; +} + +void FakeBluetoothDeviceClient::Properties::Set( + dbus::PropertyBase* property, + dbus::PropertySet::SetCallback callback) { + VLOG(1) << "Set " << property->name(); + if (property->name() == trusted.name()) { + callback.Run(true); + property->ReplaceValueWithSetValue(); + } else { + callback.Run(false); + } +} + +FakeBluetoothDeviceClient::SimulatedPairingOptions::SimulatedPairingOptions() {} + +FakeBluetoothDeviceClient::SimulatedPairingOptions::~SimulatedPairingOptions() { +} + +FakeBluetoothDeviceClient::IncomingDeviceProperties:: + IncomingDeviceProperties() {} + +FakeBluetoothDeviceClient::IncomingDeviceProperties:: + ~IncomingDeviceProperties() {} + +FakeBluetoothDeviceClient::FakeBluetoothDeviceClient() + : simulation_interval_ms_(kSimulationIntervalMs), + discovery_simulation_step_(0), + incoming_pairing_simulation_step_(0), + pairing_cancelled_(false), + connection_rssi_(kUnkownPower), + transmit_power_(kUnkownPower), + max_transmit_power_(kUnkownPower) { + scoped_ptr<Properties> properties(new Properties( + base::Bind(&FakeBluetoothDeviceClient::OnPropertyChanged, + base::Unretained(this), dbus::ObjectPath(kPairedDevicePath)))); + properties->address.ReplaceValue(kPairedDeviceAddress); + properties->bluetooth_class.ReplaceValue(kPairedDeviceClass); + properties->name.ReplaceValue("Fake Device (Name)"); + properties->alias.ReplaceValue(kPairedDeviceName); + properties->paired.ReplaceValue(true); + properties->trusted.ReplaceValue(true); + properties->adapter.ReplaceValue( + dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); + + std::vector<std::string> uuids; + uuids.push_back("00001800-0000-1000-8000-00805f9b34fb"); + uuids.push_back("00001801-0000-1000-8000-00805f9b34fb"); + properties->uuids.ReplaceValue(uuids); + + properties->modalias.ReplaceValue("usb:v05ACp030Dd0306"); + + properties_map_.insert(dbus::ObjectPath(kPairedDevicePath), + properties.Pass()); + device_list_.push_back(dbus::ObjectPath(kPairedDevicePath)); + + properties.reset(new Properties(base::Bind( + &FakeBluetoothDeviceClient::OnPropertyChanged, base::Unretained(this), + dbus::ObjectPath(kPairedUnconnectableDevicePath)))); + properties->address.ReplaceValue(kPairedUnconnectableDeviceAddress); + properties->bluetooth_class.ReplaceValue(kPairedUnconnectableDeviceClass); + properties->name.ReplaceValue("Fake Device 2 (Unconnectable)"); + properties->alias.ReplaceValue(kPairedUnconnectableDeviceName); + properties->paired.ReplaceValue(true); + properties->trusted.ReplaceValue(true); + properties->adapter.ReplaceValue( + dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); + + properties->uuids.ReplaceValue(uuids); + + properties->modalias.ReplaceValue("usb:v05ACp030Dd0306"); + + properties_map_.insert(dbus::ObjectPath(kPairedUnconnectableDevicePath), + properties.Pass()); + device_list_.push_back(dbus::ObjectPath(kPairedUnconnectableDevicePath)); +} + +FakeBluetoothDeviceClient::~FakeBluetoothDeviceClient() {} + +void FakeBluetoothDeviceClient::Init(dbus::Bus* bus) {} + +void FakeBluetoothDeviceClient::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void FakeBluetoothDeviceClient::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +std::vector<dbus::ObjectPath> FakeBluetoothDeviceClient::GetDevicesForAdapter( + const dbus::ObjectPath& adapter_path) { + if (adapter_path == + dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)) + return device_list_; + else + return std::vector<dbus::ObjectPath>(); +} + +FakeBluetoothDeviceClient::Properties* FakeBluetoothDeviceClient::GetProperties( + const dbus::ObjectPath& object_path) { + PropertiesMap::const_iterator iter = properties_map_.find(object_path); + if (iter != properties_map_.end()) + return iter->second; + return NULL; +} + +FakeBluetoothDeviceClient::SimulatedPairingOptions* +FakeBluetoothDeviceClient::GetPairingOptions( + const dbus::ObjectPath& object_path) { + PairingOptionsMap::const_iterator iter = + pairing_options_map_.find(object_path); + if (iter != pairing_options_map_.end()) + return iter->second; + return iter != pairing_options_map_.end() ? iter->second : nullptr; +} + +void FakeBluetoothDeviceClient::Connect(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "Connect: " << object_path.value(); + Properties* properties = GetProperties(object_path); + + if (properties->connected.value() == true) { + // Already connected. + callback.Run(); + return; + } + + if (properties->paired.value() != true && + object_path != dbus::ObjectPath(kConnectUnpairablePath) && + object_path != dbus::ObjectPath(kLowEnergyPath)) { + // Must be paired. + error_callback.Run(bluetooth_device::kErrorFailed, "Not paired"); + return; + } else if (properties->paired.value() == true && + (object_path == dbus::ObjectPath(kUnconnectableDevicePath) || + object_path == + dbus::ObjectPath(kPairedUnconnectableDevicePath))) { + // Must not be paired + error_callback.Run(bluetooth_device::kErrorFailed, + "Connection fails while paired"); + return; + } + + // The device can be connected. + properties->connected.ReplaceValue(true); + callback.Run(); + + // Expose GATT services if connected to LE device. + if (object_path == dbus::ObjectPath(kLowEnergyPath)) { + FakeBluetoothGattServiceClient* gatt_service_client = + static_cast<FakeBluetoothGattServiceClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothGattServiceClient()); + gatt_service_client->ExposeHeartRateService( + dbus::ObjectPath(kLowEnergyPath)); + properties->gatt_services.ReplaceValue(gatt_service_client->GetServices()); + } + + AddInputDeviceIfNeeded(object_path, properties); +} + +void FakeBluetoothDeviceClient::Disconnect( + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "Disconnect: " << object_path.value(); + Properties* properties = GetProperties(object_path); + + if (!properties->connected.value()) { + error_callback.Run("org.bluez.Error.NotConnected", "Not Connected"); + return; + } + + // Hide the Heart Rate Service if disconnected from LE device. + if (object_path == dbus::ObjectPath(kLowEnergyPath)) { + FakeBluetoothGattServiceClient* gatt_service_client = + static_cast<FakeBluetoothGattServiceClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothGattServiceClient()); + gatt_service_client->HideHeartRateService(); + } + + callback.Run(); + properties->connected.ReplaceValue(false); +} + +void FakeBluetoothDeviceClient::ConnectProfile( + const dbus::ObjectPath& object_path, + const std::string& uuid, + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "ConnectProfile: " << object_path.value() << " " << uuid; + + FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = + static_cast<FakeBluetoothProfileManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothProfileManagerClient()); + FakeBluetoothProfileServiceProvider* profile_service_provider = + fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid); + if (profile_service_provider == NULL) { + error_callback.Run(kNoResponseError, "Missing profile"); + return; + } + + if (object_path == dbus::ObjectPath(kPairedUnconnectableDevicePath)) { + error_callback.Run(bluetooth_device::kErrorFailed, "unconnectable"); + return; + } + + // Make a socket pair of a compatible type with the type used by Bluetooth; + // spin up a thread to simulate the server side and wrap the client side in + // a D-Bus file descriptor object. + int socket_type = SOCK_STREAM; + if (uuid == FakeBluetoothProfileManagerClient::kL2capUuid) + socket_type = SOCK_SEQPACKET; + + int fds[2]; + if (socketpair(AF_UNIX, socket_type, 0, fds) < 0) { + error_callback.Run(kNoResponseError, "socketpair call failed"); + return; + } + + int args; + args = fcntl(fds[1], F_GETFL, NULL); + if (args < 0) { + error_callback.Run(kNoResponseError, "failed to get socket flags"); + return; + } + + args |= O_NONBLOCK; + if (fcntl(fds[1], F_SETFL, args) < 0) { + error_callback.Run(kNoResponseError, "failed to set socket non-blocking"); + return; + } + + base::WorkerPool::GetTaskRunner(false) + ->PostTask(FROM_HERE, base::Bind(&SimulatedProfileSocket, fds[0])); + + scoped_ptr<dbus::FileDescriptor> fd(new dbus::FileDescriptor(fds[1])); + + // Post the new connection to the service provider. + BluetoothProfileServiceProvider::Delegate::Options options; + + profile_service_provider->NewConnection( + object_path, fd.Pass(), options, + base::Bind(&FakeBluetoothDeviceClient::ConnectionCallback, + base::Unretained(this), object_path, callback, + error_callback)); +} + +void FakeBluetoothDeviceClient::DisconnectProfile( + const dbus::ObjectPath& object_path, + const std::string& uuid, + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "DisconnectProfile: " << object_path.value() << " " << uuid; + + FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = + static_cast<FakeBluetoothProfileManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothProfileManagerClient()); + FakeBluetoothProfileServiceProvider* profile_service_provider = + fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid); + if (profile_service_provider == NULL) { + error_callback.Run(kNoResponseError, "Missing profile"); + return; + } + + profile_service_provider->RequestDisconnection( + object_path, base::Bind(&FakeBluetoothDeviceClient::DisconnectionCallback, + base::Unretained(this), object_path, callback, + error_callback)); +} + +void FakeBluetoothDeviceClient::Pair(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "Pair: " << object_path.value(); + Properties* properties = GetProperties(object_path); + + if (properties->paired.value() == true) { + // Already paired. + callback.Run(); + return; + } + + SimulatePairing(object_path, false, callback, error_callback); +} + +void FakeBluetoothDeviceClient::CancelPairing( + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "CancelPairing: " << object_path.value(); + pairing_cancelled_ = true; + callback.Run(); +} + +void FakeBluetoothDeviceClient::GetConnInfo( + const dbus::ObjectPath& object_path, + const ConnInfoCallback& callback, + const ErrorCallback& error_callback) { + Properties* properties = GetProperties(object_path); + if (!properties->connected.value()) { + error_callback.Run("org.bluez.Error.NotConnected", "Not Connected"); + return; + } + + callback.Run(connection_rssi_, transmit_power_, max_transmit_power_); +} + +void FakeBluetoothDeviceClient::BeginDiscoverySimulation( + const dbus::ObjectPath& adapter_path) { + VLOG(1) << "starting discovery simulation"; + + discovery_simulation_step_ = 1; + + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer, + base::Unretained(this)), + base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); +} + +void FakeBluetoothDeviceClient::EndDiscoverySimulation( + const dbus::ObjectPath& adapter_path) { + VLOG(1) << "stopping discovery simulation"; + discovery_simulation_step_ = 0; +} + +void FakeBluetoothDeviceClient::BeginIncomingPairingSimulation( + const dbus::ObjectPath& adapter_path) { + VLOG(1) << "starting incoming pairing simulation"; + + incoming_pairing_simulation_step_ = 1; + + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::IncomingPairingSimulationTimer, + base::Unretained(this)), + base::TimeDelta::FromMilliseconds( + kIncomingSimulationStartPairTimeMultiplier * + simulation_interval_ms_)); +} + +void FakeBluetoothDeviceClient::EndIncomingPairingSimulation( + const dbus::ObjectPath& adapter_path) { + VLOG(1) << "stopping incoming pairing simulation"; + incoming_pairing_simulation_step_ = 0; +} + +void FakeBluetoothDeviceClient::SetSimulationIntervalMs(int interval_ms) { + simulation_interval_ms_ = interval_ms; +} + +void FakeBluetoothDeviceClient::CreateDevice( + const dbus::ObjectPath& adapter_path, + const dbus::ObjectPath& device_path) { + if (std::find(device_list_.begin(), device_list_.end(), device_path) != + device_list_.end()) + return; + + scoped_ptr<Properties> properties( + new Properties(base::Bind(&FakeBluetoothDeviceClient::OnPropertyChanged, + base::Unretained(this), device_path))); + properties->adapter.ReplaceValue(adapter_path); + + if (device_path == dbus::ObjectPath(kLegacyAutopairPath)) { + properties->address.ReplaceValue(kLegacyAutopairAddress); + properties->bluetooth_class.ReplaceValue(kLegacyAutopairClass); + properties->name.ReplaceValue("LegacyAutopair"); + properties->alias.ReplaceValue(kLegacyAutopairName); + + std::vector<std::string> uuids; + uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); + properties->uuids.ReplaceValue(uuids); + + } else if (device_path == dbus::ObjectPath(kDisplayPinCodePath)) { + properties->address.ReplaceValue(kDisplayPinCodeAddress); + properties->bluetooth_class.ReplaceValue(kDisplayPinCodeClass); + properties->name.ReplaceValue("DisplayPinCode"); + properties->alias.ReplaceValue(kDisplayPinCodeName); + + std::vector<std::string> uuids; + uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); + properties->uuids.ReplaceValue(uuids); + + } else if (device_path == dbus::ObjectPath(kVanishingDevicePath)) { + properties->address.ReplaceValue(kVanishingDeviceAddress); + properties->bluetooth_class.ReplaceValue(kVanishingDeviceClass); + properties->name.ReplaceValue("VanishingDevice"); + properties->alias.ReplaceValue(kVanishingDeviceName); + + } else if (device_path == dbus::ObjectPath(kConnectUnpairablePath)) { + properties->address.ReplaceValue(kConnectUnpairableAddress); + properties->bluetooth_class.ReplaceValue(kConnectUnpairableClass); + properties->name.ReplaceValue("ConnectUnpairable"); + properties->alias.ReplaceValue(kConnectUnpairableName); + + std::vector<std::string> uuids; + uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); + properties->uuids.ReplaceValue(uuids); + + } else if (device_path == dbus::ObjectPath(kDisplayPasskeyPath)) { + properties->address.ReplaceValue(kDisplayPasskeyAddress); + properties->bluetooth_class.ReplaceValue(kDisplayPasskeyClass); + properties->name.ReplaceValue("DisplayPasskey"); + properties->alias.ReplaceValue(kDisplayPasskeyName); + + std::vector<std::string> uuids; + uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); + properties->uuids.ReplaceValue(uuids); + + } else if (device_path == dbus::ObjectPath(kRequestPinCodePath)) { + properties->address.ReplaceValue(kRequestPinCodeAddress); + properties->bluetooth_class.ReplaceValue(kRequestPinCodeClass); + properties->name.ReplaceValue("RequestPinCode"); + properties->alias.ReplaceValue(kRequestPinCodeName); + + } else if (device_path == dbus::ObjectPath(kConfirmPasskeyPath)) { + properties->address.ReplaceValue(kConfirmPasskeyAddress); + properties->bluetooth_class.ReplaceValue(kConfirmPasskeyClass); + properties->name.ReplaceValue("ConfirmPasskey"); + properties->alias.ReplaceValue(kConfirmPasskeyName); + + } else if (device_path == dbus::ObjectPath(kRequestPasskeyPath)) { + properties->address.ReplaceValue(kRequestPasskeyAddress); + properties->bluetooth_class.ReplaceValue(kRequestPasskeyClass); + properties->name.ReplaceValue("RequestPasskey"); + properties->alias.ReplaceValue(kRequestPasskeyName); + + } else if (device_path == dbus::ObjectPath(kUnconnectableDevicePath)) { + properties->address.ReplaceValue(kUnconnectableDeviceAddress); + properties->bluetooth_class.ReplaceValue(kUnconnectableDeviceClass); + properties->name.ReplaceValue("UnconnectableDevice"); + properties->alias.ReplaceValue(kUnconnectableDeviceName); + + } else if (device_path == dbus::ObjectPath(kUnpairableDevicePath)) { + properties->address.ReplaceValue(kUnpairableDeviceAddress); + properties->bluetooth_class.ReplaceValue(kUnpairableDeviceClass); + properties->name.ReplaceValue("Fake Unpairable Device"); + properties->alias.ReplaceValue(kUnpairableDeviceName); + + } else if (device_path == dbus::ObjectPath(kJustWorksPath)) { + properties->address.ReplaceValue(kJustWorksAddress); + properties->bluetooth_class.ReplaceValue(kJustWorksClass); + properties->name.ReplaceValue("JustWorks"); + properties->alias.ReplaceValue(kJustWorksName); + + } else if (device_path == dbus::ObjectPath(kLowEnergyPath)) { + properties->address.ReplaceValue(kLowEnergyAddress); + properties->bluetooth_class.ReplaceValue(kLowEnergyClass); + properties->name.ReplaceValue("Heart Rate Monitor"); + properties->alias.ReplaceValue(kLowEnergyName); + + std::vector<std::string> uuids; + uuids.push_back(FakeBluetoothGattServiceClient::kHeartRateServiceUUID); + properties->uuids.ReplaceValue(uuids); + } else if (device_path == + dbus::ObjectPath(kConnectedTrustedNotPairedDevicePath)) { + properties->address.ReplaceValue(kConnectedTrustedNotPairedDeviceAddress); + properties->bluetooth_class.ReplaceValue( + kConnectedTrustedNotPairedDeviceClass); + properties->trusted.ReplaceValue(true); + properties->connected.ReplaceValue(true); + properties->paired.ReplaceValue(false); + properties->name.ReplaceValue("Connected Pairable Device"); + properties->alias.ReplaceValue(kConnectedTrustedNotPairedDeviceName); + } else { + NOTREACHED(); + } + + properties_map_.insert(device_path, properties.Pass()); + device_list_.push_back(device_path); + FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, + DeviceAdded(device_path)); +} + +void FakeBluetoothDeviceClient::CreateDeviceWithProperties( + const dbus::ObjectPath& adapter_path, + const IncomingDeviceProperties& props) { + dbus::ObjectPath device_path(props.device_path); + if (std::find(device_list_.begin(), device_list_.end(), device_path) != + device_list_.end()) + return; + + scoped_ptr<Properties> properties( + new Properties(base::Bind(&FakeBluetoothDeviceClient::OnPropertyChanged, + base::Unretained(this), device_path))); + properties->adapter.ReplaceValue(adapter_path); + properties->name.ReplaceValue(props.device_name); + properties->alias.ReplaceValue(props.device_alias); + properties->address.ReplaceValue(props.device_address); + properties->bluetooth_class.ReplaceValue(props.device_class); + properties->trusted.ReplaceValue(props.is_trusted); + + if (props.is_trusted) + properties->paired.ReplaceValue(true); + + scoped_ptr<SimulatedPairingOptions> options(new SimulatedPairingOptions); + options->pairing_method = props.pairing_method; + options->pairing_auth_token = props.pairing_auth_token; + options->pairing_action = props.pairing_action; + options->incoming = props.incoming; + + properties_map_.insert(device_path, properties.Pass()); + device_list_.push_back(device_path); + pairing_options_map_.insert(device_path, options.Pass()); + FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, + DeviceAdded(device_path)); +} + +scoped_ptr<base::ListValue> +FakeBluetoothDeviceClient::GetBluetoothDevicesAsDictionaries() const { + scoped_ptr<base::ListValue> predefined_devices(new base::ListValue); + scoped_ptr<base::DictionaryValue> pairedDevice(new base::DictionaryValue); + pairedDevice->SetString("path", kPairedDevicePath); + pairedDevice->SetString("address", kPairedDeviceAddress); + pairedDevice->SetString("name", kPairedDeviceName); + pairedDevice->SetString("alias", kPairedDeviceName); + pairedDevice->SetString("pairingMethod", ""); + pairedDevice->SetString("pairingAuthToken", ""); + pairedDevice->SetString("pairingAction", ""); + pairedDevice->SetInteger("classValue", kPairedDeviceClass); + pairedDevice->SetBoolean("discoverable", true); + pairedDevice->SetBoolean("isTrusted", true); + pairedDevice->SetBoolean("paired", true); + pairedDevice->SetBoolean("incoming", false); + predefined_devices->Append(pairedDevice.Pass()); + + scoped_ptr<base::DictionaryValue> legacyDevice(new base::DictionaryValue); + legacyDevice->SetString("path", kLegacyAutopairPath); + legacyDevice->SetString("address", kLegacyAutopairAddress); + legacyDevice->SetString("name", kLegacyAutopairName); + legacyDevice->SetString("alias", kLegacyAutopairName); + legacyDevice->SetString("pairingMethod", ""); + legacyDevice->SetString("pairingAuthToken", ""); + legacyDevice->SetString("pairingAction", ""); + legacyDevice->SetInteger("classValue", kLegacyAutopairClass); + legacyDevice->SetBoolean("isTrusted", true); + legacyDevice->SetBoolean("discoverable", false); + legacyDevice->SetBoolean("paired", false); + legacyDevice->SetBoolean("incoming", false); + predefined_devices->Append(legacyDevice.Pass()); + + scoped_ptr<base::DictionaryValue> pin(new base::DictionaryValue); + pin->SetString("path", kDisplayPinCodePath); + pin->SetString("address", kDisplayPinCodeAddress); + pin->SetString("name", kDisplayPinCodeName); + pin->SetString("alias", kDisplayPinCodeName); + pin->SetString("pairingMethod", kPairingMethodPinCode); + pin->SetString("pairingAuthToken", kTestPinCode); + pin->SetString("pairingAction", kPairingActionDisplay); + pin->SetInteger("classValue", kDisplayPinCodeClass); + pin->SetBoolean("isTrusted", false); + pin->SetBoolean("discoverable", false); + pin->SetBoolean("paired", false); + pin->SetBoolean("incoming", false); + predefined_devices->Append(pin.Pass()); + + scoped_ptr<base::DictionaryValue> vanishing(new base::DictionaryValue); + vanishing->SetString("path", kVanishingDevicePath); + vanishing->SetString("address", kVanishingDeviceAddress); + vanishing->SetString("name", kVanishingDeviceName); + vanishing->SetString("alias", kVanishingDeviceName); + vanishing->SetString("pairingMethod", ""); + vanishing->SetString("pairingAuthToken", ""); + vanishing->SetString("pairingAction", ""); + vanishing->SetInteger("classValue", kVanishingDeviceClass); + vanishing->SetBoolean("isTrusted", false); + vanishing->SetBoolean("discoverable", false); + vanishing->SetBoolean("paired", false); + vanishing->SetBoolean("incoming", false); + predefined_devices->Append(vanishing.Pass()); + + scoped_ptr<base::DictionaryValue> connect_unpairable( + new base::DictionaryValue); + connect_unpairable->SetString("path", kConnectUnpairablePath); + connect_unpairable->SetString("address", kConnectUnpairableAddress); + connect_unpairable->SetString("name", kConnectUnpairableName); + connect_unpairable->SetString("pairingMethod", ""); + connect_unpairable->SetString("pairingAuthToken", ""); + connect_unpairable->SetString("pairingAction", ""); + connect_unpairable->SetString("alias", kConnectUnpairableName); + connect_unpairable->SetInteger("classValue", kConnectUnpairableClass); + connect_unpairable->SetBoolean("isTrusted", false); + connect_unpairable->SetBoolean("discoverable", false); + connect_unpairable->SetBoolean("paired", false); + connect_unpairable->SetBoolean("incoming", false); + predefined_devices->Append(connect_unpairable.Pass()); + + scoped_ptr<base::DictionaryValue> passkey(new base::DictionaryValue); + passkey->SetString("path", kDisplayPasskeyPath); + passkey->SetString("address", kDisplayPasskeyAddress); + passkey->SetString("name", kDisplayPasskeyName); + passkey->SetString("alias", kDisplayPasskeyName); + passkey->SetString("pairingMethod", kPairingMethodPassKey); + passkey->SetInteger("pairingAuthToken", kTestPassKey); + passkey->SetString("pairingAction", kPairingActionDisplay); + passkey->SetInteger("classValue", kDisplayPasskeyClass); + passkey->SetBoolean("isTrusted", false); + passkey->SetBoolean("discoverable", false); + passkey->SetBoolean("paired", false); + passkey->SetBoolean("incoming", false); + predefined_devices->Append(passkey.Pass()); + + scoped_ptr<base::DictionaryValue> request_pin(new base::DictionaryValue); + request_pin->SetString("path", kRequestPinCodePath); + request_pin->SetString("address", kRequestPinCodeAddress); + request_pin->SetString("name", kRequestPinCodeName); + request_pin->SetString("alias", kRequestPinCodeName); + request_pin->SetString("pairingMethod", ""); + request_pin->SetString("pairingAuthToken", ""); + request_pin->SetString("pairingAction", kPairingActionRequest); + request_pin->SetInteger("classValue", kRequestPinCodeClass); + request_pin->SetBoolean("isTrusted", false); + request_pin->SetBoolean("discoverable", false); + request_pin->SetBoolean("paired", false); + request_pin->SetBoolean("incoming", false); + predefined_devices->Append(request_pin.Pass()); + + scoped_ptr<base::DictionaryValue> confirm(new base::DictionaryValue); + confirm->SetString("path", kConfirmPasskeyPath); + confirm->SetString("address", kConfirmPasskeyAddress); + confirm->SetString("name", kConfirmPasskeyName); + confirm->SetString("alias", kConfirmPasskeyName); + confirm->SetString("pairingMethod", ""); + confirm->SetInteger("pairingAuthToken", kTestPassKey); + confirm->SetString("pairingAction", kPairingActionConfirmation); + confirm->SetInteger("classValue", kConfirmPasskeyClass); + confirm->SetBoolean("isTrusted", false); + confirm->SetBoolean("discoverable", false); + confirm->SetBoolean("paired", false); + confirm->SetBoolean("incoming", false); + predefined_devices->Append(confirm.Pass()); + + scoped_ptr<base::DictionaryValue> request_passkey(new base::DictionaryValue); + request_passkey->SetString("path", kRequestPasskeyPath); + request_passkey->SetString("address", kRequestPasskeyAddress); + request_passkey->SetString("name", kRequestPasskeyName); + request_passkey->SetString("alias", kRequestPasskeyName); + request_passkey->SetString("pairingMethod", kPairingMethodPassKey); + request_passkey->SetString("pairingAction", kPairingActionRequest); + request_passkey->SetInteger("pairingAuthToken", kTestPassKey); + request_passkey->SetInteger("classValue", kRequestPasskeyClass); + request_passkey->SetBoolean("isTrusted", false); + request_passkey->SetBoolean("discoverable", false); + request_passkey->SetBoolean("paired", false); + request_passkey->SetBoolean("incoming", false); + predefined_devices->Append(request_passkey.Pass()); + + scoped_ptr<base::DictionaryValue> unconnectable(new base::DictionaryValue); + unconnectable->SetString("path", kUnconnectableDevicePath); + unconnectable->SetString("address", kUnconnectableDeviceAddress); + unconnectable->SetString("name", kUnconnectableDeviceName); + unconnectable->SetString("alias", kUnconnectableDeviceName); + unconnectable->SetString("pairingMethod", ""); + unconnectable->SetString("pairingAuthToken", ""); + unconnectable->SetString("pairingAction", ""); + unconnectable->SetInteger("classValue", kUnconnectableDeviceClass); + unconnectable->SetBoolean("isTrusted", true); + unconnectable->SetBoolean("discoverable", false); + unconnectable->SetBoolean("paired", false); + unconnectable->SetBoolean("incoming", false); + predefined_devices->Append(unconnectable.Pass()); + + scoped_ptr<base::DictionaryValue> unpairable(new base::DictionaryValue); + unpairable->SetString("path", kUnpairableDevicePath); + unpairable->SetString("address", kUnpairableDeviceAddress); + unpairable->SetString("name", kUnpairableDeviceName); + unpairable->SetString("alias", kUnpairableDeviceName); + unpairable->SetString("pairingMethod", ""); + unpairable->SetString("pairingAuthToken", ""); + unpairable->SetString("pairingAction", kPairingActionFail); + unpairable->SetInteger("classValue", kUnpairableDeviceClass); + unpairable->SetBoolean("isTrusted", false); + unpairable->SetBoolean("discoverable", false); + unpairable->SetBoolean("paired", false); + unpairable->SetBoolean("incoming", false); + predefined_devices->Append(unpairable.Pass()); + + scoped_ptr<base::DictionaryValue> just_works(new base::DictionaryValue); + just_works->SetString("path", kJustWorksPath); + just_works->SetString("address", kJustWorksAddress); + just_works->SetString("name", kJustWorksName); + just_works->SetString("alias", kJustWorksName); + just_works->SetString("pairingMethod", ""); + just_works->SetString("pairingAuthToken", ""); + just_works->SetString("pairingAction", ""); + just_works->SetInteger("classValue", kJustWorksClass); + just_works->SetBoolean("isTrusted", false); + just_works->SetBoolean("discoverable", false); + just_works->SetBoolean("paired", false); + just_works->SetBoolean("incoming", false); + predefined_devices->Append(just_works.Pass()); + + scoped_ptr<base::DictionaryValue> low_energy(new base::DictionaryValue); + low_energy->SetString("path", kLowEnergyPath); + low_energy->SetString("address", kLowEnergyAddress); + low_energy->SetString("name", kLowEnergyName); + low_energy->SetString("alias", kLowEnergyName); + low_energy->SetString("pairingMethod", ""); + low_energy->SetString("pairingAuthToken", ""); + low_energy->SetString("pairingAction", ""); + low_energy->SetInteger("classValue", kLowEnergyClass); + low_energy->SetBoolean("isTrusted", false); + low_energy->SetBoolean("discoverable", false); + low_energy->SetBoolean("paireed", false); + low_energy->SetBoolean("incoming", false); + predefined_devices->Append(low_energy.Pass()); + + scoped_ptr<base::DictionaryValue> paired_unconnectable( + new base::DictionaryValue); + paired_unconnectable->SetString("path", kPairedUnconnectableDevicePath); + paired_unconnectable->SetString("address", kPairedUnconnectableDeviceAddress); + paired_unconnectable->SetString("name", kPairedUnconnectableDeviceName); + paired_unconnectable->SetString("pairingMethod", ""); + paired_unconnectable->SetString("pairingAuthToken", ""); + paired_unconnectable->SetString("pairingAction", ""); + paired_unconnectable->SetString("alias", kPairedUnconnectableDeviceName); + paired_unconnectable->SetInteger("classValue", + kPairedUnconnectableDeviceClass); + paired_unconnectable->SetBoolean("isTrusted", false); + paired_unconnectable->SetBoolean("discoverable", true); + paired_unconnectable->SetBoolean("paired", true); + paired_unconnectable->SetBoolean("incoming", false); + predefined_devices->Append(paired_unconnectable.Pass()); + + scoped_ptr<base::DictionaryValue> connected_trusted_not_paired( + new base::DictionaryValue); + connected_trusted_not_paired->SetString("path", + kConnectedTrustedNotPairedDevicePath); + connected_trusted_not_paired->SetString( + "address", kConnectedTrustedNotPairedDeviceAddress); + connected_trusted_not_paired->SetString("name", + kConnectedTrustedNotPairedDeviceName); + connected_trusted_not_paired->SetString("pairingMethod", ""); + connected_trusted_not_paired->SetString("pairingAuthToken", ""); + connected_trusted_not_paired->SetString("pairingAction", ""); + connected_trusted_not_paired->SetString("alias", + kConnectedTrustedNotPairedDeviceName); + connected_trusted_not_paired->SetInteger( + "classValue", kConnectedTrustedNotPairedDeviceClass); + connected_trusted_not_paired->SetBoolean("isTrusted", true); + connected_trusted_not_paired->SetBoolean("discoverable", true); + connected_trusted_not_paired->SetBoolean("paired", false); + connected_trusted_not_paired->SetBoolean("incoming", false); + predefined_devices->Append(connected_trusted_not_paired.Pass()); + + return predefined_devices.Pass(); +} + +void FakeBluetoothDeviceClient::RemoveDevice( + const dbus::ObjectPath& adapter_path, + const dbus::ObjectPath& device_path) { + std::vector<dbus::ObjectPath>::iterator listiter = + std::find(device_list_.begin(), device_list_.end(), device_path); + if (listiter == device_list_.end()) + return; + + PropertiesMap::const_iterator iter = properties_map_.find(device_path); + Properties* properties = iter->second; + + VLOG(1) << "removing device: " << properties->alias.value(); + device_list_.erase(listiter); + + // Remove the Input interface if it exists. This should be called before the + // BluetoothDeviceClient::Observer::DeviceRemoved because it deletes the + // BluetoothDeviceChromeOS object, including the device_path referenced here. + FakeBluetoothInputClient* fake_bluetooth_input_client = + static_cast<FakeBluetoothInputClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothInputClient()); + fake_bluetooth_input_client->RemoveInputDevice(device_path); + + if (device_path == dbus::ObjectPath(kLowEnergyPath)) { + FakeBluetoothGattServiceClient* gatt_service_client = + static_cast<FakeBluetoothGattServiceClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothGattServiceClient()); + gatt_service_client->HideHeartRateService(); + } + + FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, + DeviceRemoved(device_path)); + + properties_map_.erase(iter); + PairingOptionsMap::const_iterator options_iter = + pairing_options_map_.find(device_path); + + if (options_iter != pairing_options_map_.end()) { + pairing_options_map_.erase(options_iter); + } +} + +void FakeBluetoothDeviceClient::OnPropertyChanged( + const dbus::ObjectPath& object_path, + const std::string& property_name) { + VLOG(2) << "Fake Bluetooth device property changed: " << object_path.value() + << ": " << property_name; + FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, + DevicePropertyChanged(object_path, property_name)); +} + +void FakeBluetoothDeviceClient::DiscoverySimulationTimer() { + if (!discovery_simulation_step_) + return; + + // Timer fires every .75s, the numbers below are arbitrary to give a feel + // for a discovery process. + VLOG(1) << "discovery simulation, step " << discovery_simulation_step_; + if (discovery_simulation_step_ == 2) { + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kLegacyAutopairPath)); + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kLowEnergyPath)); + + } else if (discovery_simulation_step_ == 4) { + UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), + base::RandInt(kMinRSSI, kMaxRSSI)); + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kDisplayPinCodePath)); + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kVanishingDevicePath)); + + } else if (discovery_simulation_step_ == 7) { + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kConnectUnpairablePath)); + UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), + base::RandInt(kMinRSSI, kMaxRSSI)); + + } else if (discovery_simulation_step_ == 8) { + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kDisplayPasskeyPath)); + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kRequestPinCodePath)); + UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), + base::RandInt(kMinRSSI, kMaxRSSI)); + + } else if (discovery_simulation_step_ == 10) { + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kConfirmPasskeyPath)); + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kRequestPasskeyPath)); + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kUnconnectableDevicePath)); + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kUnpairableDevicePath)); + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kJustWorksPath)); + UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), + base::RandInt(kMinRSSI, kMaxRSSI)); + + } else if (discovery_simulation_step_ == 13) { + UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), + base::RandInt(kMinRSSI, kMaxRSSI)); + RemoveDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kVanishingDevicePath)); + } else if (discovery_simulation_step_ == 14) { + UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), + base::RandInt(kMinRSSI, kMaxRSSI)); + return; + } + + ++discovery_simulation_step_; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer, + base::Unretained(this)), + base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); +} + +void FakeBluetoothDeviceClient::IncomingPairingSimulationTimer() { + if (!incoming_pairing_simulation_step_) + return; + + VLOG(1) << "incoming pairing simulation, step " + << incoming_pairing_simulation_step_; + switch (incoming_pairing_simulation_step_) { + case 1: + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kConfirmPasskeyPath)); + SimulatePairing(dbus::ObjectPath(kConfirmPasskeyPath), true, + base::Bind(&base::DoNothing), + base::Bind(&SimpleErrorCallback)); + break; + case 2: + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kJustWorksPath)); + SimulatePairing(dbus::ObjectPath(kJustWorksPath), true, + base::Bind(&base::DoNothing), + base::Bind(&SimpleErrorCallback)); + break; + case 3: + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kDisplayPinCodePath)); + SimulatePairing(dbus::ObjectPath(kDisplayPinCodePath), true, + base::Bind(&base::DoNothing), + base::Bind(&SimpleErrorCallback)); + break; + case 4: + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kDisplayPasskeyPath)); + SimulatePairing(dbus::ObjectPath(kDisplayPasskeyPath), true, + base::Bind(&base::DoNothing), + base::Bind(&SimpleErrorCallback)); + break; + case 5: + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kRequestPinCodePath)); + SimulatePairing(dbus::ObjectPath(kRequestPinCodePath), true, + base::Bind(&base::DoNothing), + base::Bind(&SimpleErrorCallback)); + break; + case 6: + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kRequestPasskeyPath)); + SimulatePairing(dbus::ObjectPath(kRequestPasskeyPath), true, + base::Bind(&base::DoNothing), + base::Bind(&SimpleErrorCallback)); + break; + default: + return; + } + + ++incoming_pairing_simulation_step_; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::IncomingPairingSimulationTimer, + base::Unretained(this)), + base::TimeDelta::FromMilliseconds(kIncomingSimulationPairTimeMultiplier * + simulation_interval_ms_)); +} + +void FakeBluetoothDeviceClient::SimulatePairing( + const dbus::ObjectPath& object_path, + bool incoming_request, + const base::Closure& callback, + const ErrorCallback& error_callback) { + pairing_cancelled_ = false; + + FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client = + static_cast<FakeBluetoothAgentManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothAgentManagerClient()); + FakeBluetoothAgentServiceProvider* agent_service_provider = + fake_bluetooth_agent_manager_client->GetAgentServiceProvider(); + CHECK(agent_service_provider != NULL); + + // Grab the device's pairing properties. + PairingOptionsMap::const_iterator iter = + pairing_options_map_.find(object_path); + + // If the device with path |object_path| has simulated pairing properties + // defined, then pair it based on its |pairing_method|. + if (iter != pairing_options_map_.end()) { + if (iter->second->pairing_action == kPairingActionFail) { + // Fails the pairing with an org.bluez.Error.Failed error. + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::FailSimulatedPairing, + base::Unretained(this), object_path, error_callback), + base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); + } else if (iter->second->pairing_method == kPairingMethodNone || + iter->second->pairing_method.empty()) { + if (!iter->second->incoming) { + // Simply pair and connect the device. + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, + base::Unretained(this), object_path, callback, + error_callback), + base::TimeDelta::FromMilliseconds( + kSimulateNormalPairTimeMultiplier * simulation_interval_ms_)); + } else { + agent_service_provider->RequestAuthorization( + object_path, + base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback, + base::Unretained(this), object_path, callback, + error_callback)); + } + } else if (iter->second->pairing_method == kPairingMethodPinCode) { + if (iter->second->pairing_action == kPairingActionDisplay) { + // Display a Pincode, and wait before acting as if the other end + // accepted it. + agent_service_provider->DisplayPinCode( + object_path, iter->second->pairing_auth_token); + + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, + base::Unretained(this), object_path, callback, + error_callback), + base::TimeDelta::FromMilliseconds(kPinCodeDevicePairTimeMultiplier * + simulation_interval_ms_)); + } else if (iter->second->pairing_action == kPairingActionRequest) { + // Request a pin code. + agent_service_provider->RequestPinCode( + object_path, base::Bind(&FakeBluetoothDeviceClient::PinCodeCallback, + base::Unretained(this), object_path, + callback, error_callback)); + } else if (iter->second->pairing_action == kPairingActionConfirmation) { + error_callback.Run(kNoResponseError, "No confirm for pincode pairing."); + } + } else if (iter->second->pairing_method == kPairingMethodPassKey) { + // Display a passkey, and each interval act as if another key was entered + // for it. + if (iter->second->pairing_action == kPairingActionDisplay) { + agent_service_provider->DisplayPasskey( + object_path, std::stoi(iter->second->pairing_auth_token), 0); + + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress, + base::Unretained(this), 1, object_path, + callback, error_callback), + base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); + } else if (iter->second->pairing_action == kPairingActionRequest) { + agent_service_provider->RequestPasskey( + object_path, base::Bind(&FakeBluetoothDeviceClient::PasskeyCallback, + base::Unretained(this), object_path, + callback, error_callback)); + } else if (iter->second->pairing_action == kPairingActionConfirmation) { + agent_service_provider->RequestConfirmation( + object_path, std::stoi(iter->second->pairing_auth_token), + base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback, + base::Unretained(this), object_path, callback, + error_callback)); + } + } + } else { + if (object_path == dbus::ObjectPath(kLegacyAutopairPath) || + object_path == dbus::ObjectPath(kConnectUnpairablePath) || + object_path == dbus::ObjectPath(kUnconnectableDevicePath) || + object_path == dbus::ObjectPath(kLowEnergyPath)) { + // No need to call anything on the pairing delegate, just wait 3 times + // the interval before acting as if the other end accepted it. + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, + base::Unretained(this), object_path, callback, + error_callback), + base::TimeDelta::FromMilliseconds(kSimulateNormalPairTimeMultiplier * + simulation_interval_ms_)); + + } else if (object_path == dbus::ObjectPath(kDisplayPinCodePath)) { + // Display a Pincode, and wait before acting as if the other end accepted + // it. + agent_service_provider->DisplayPinCode(object_path, kTestPinCode); + + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, + base::Unretained(this), object_path, callback, + error_callback), + base::TimeDelta::FromMilliseconds(kPinCodeDevicePairTimeMultiplier * + simulation_interval_ms_)); + + } else if (object_path == dbus::ObjectPath(kVanishingDevicePath)) { + // The vanishing device simulates being too far away, and thus times out. + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::TimeoutSimulatedPairing, + base::Unretained(this), object_path, error_callback), + base::TimeDelta::FromMilliseconds(kVanishingDevicePairTimeMultiplier * + simulation_interval_ms_)); + + } else if (object_path == dbus::ObjectPath(kDisplayPasskeyPath)) { + // Display a passkey, and each interval act as if another key was entered + // for it. + agent_service_provider->DisplayPasskey(object_path, kTestPassKey, 0); + + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress, + base::Unretained(this), 1, object_path, + callback, error_callback), + base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); + + } else if (object_path == dbus::ObjectPath(kRequestPinCodePath)) { + // Request a Pincode. + agent_service_provider->RequestPinCode( + object_path, base::Bind(&FakeBluetoothDeviceClient::PinCodeCallback, + base::Unretained(this), object_path, callback, + error_callback)); + + } else if (object_path == dbus::ObjectPath(kConfirmPasskeyPath) || + object_path == + dbus::ObjectPath(kConnectedTrustedNotPairedDevicePath)) { + // Request confirmation of a Passkey. + agent_service_provider->RequestConfirmation( + object_path, kTestPassKey, + base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback, + base::Unretained(this), object_path, callback, + error_callback)); + + } else if (object_path == dbus::ObjectPath(kRequestPasskeyPath)) { + // Request a Passkey from the user. + agent_service_provider->RequestPasskey( + object_path, base::Bind(&FakeBluetoothDeviceClient::PasskeyCallback, + base::Unretained(this), object_path, callback, + error_callback)); + + } else if (object_path == dbus::ObjectPath(kUnpairableDevicePath)) { + // Fails the pairing with an org.bluez.Error.Failed error. + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::FailSimulatedPairing, + base::Unretained(this), object_path, error_callback), + base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); + + } else if (object_path == dbus::ObjectPath(kJustWorksPath)) { + if (incoming_request) { + agent_service_provider->RequestAuthorization( + object_path, + base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback, + base::Unretained(this), object_path, callback, + error_callback)); + + } else { + // No need to call anything on the pairing delegate, just wait before + // acting as if the other end accepted it. + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, + base::Unretained(this), object_path, callback, + error_callback), + base::TimeDelta::FromMilliseconds( + kSimulateNormalPairTimeMultiplier * simulation_interval_ms_)); + } + + } else { + error_callback.Run(kNoResponseError, "No pairing fake"); + } + } +} + +void FakeBluetoothDeviceClient::CompleteSimulatedPairing( + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "CompleteSimulatedPairing: " << object_path.value(); + if (pairing_cancelled_) { + pairing_cancelled_ = false; + + error_callback.Run(bluetooth_device::kErrorAuthenticationCanceled, + "Cancelled"); + } else { + Properties* properties = GetProperties(object_path); + + properties->paired.ReplaceValue(true); + callback.Run(); + + AddInputDeviceIfNeeded(object_path, properties); + } +} + +void FakeBluetoothDeviceClient::TimeoutSimulatedPairing( + const dbus::ObjectPath& object_path, + const ErrorCallback& error_callback) { + VLOG(1) << "TimeoutSimulatedPairing: " << object_path.value(); + + error_callback.Run(bluetooth_device::kErrorAuthenticationTimeout, + "Timed out"); +} + +void FakeBluetoothDeviceClient::CancelSimulatedPairing( + const dbus::ObjectPath& object_path, + const ErrorCallback& error_callback) { + VLOG(1) << "CancelSimulatedPairing: " << object_path.value(); + + error_callback.Run(bluetooth_device::kErrorAuthenticationCanceled, + "Canceled"); +} + +void FakeBluetoothDeviceClient::RejectSimulatedPairing( + const dbus::ObjectPath& object_path, + const ErrorCallback& error_callback) { + VLOG(1) << "RejectSimulatedPairing: " << object_path.value(); + + error_callback.Run(bluetooth_device::kErrorAuthenticationRejected, + "Rejected"); +} + +void FakeBluetoothDeviceClient::FailSimulatedPairing( + const dbus::ObjectPath& object_path, + const ErrorCallback& error_callback) { + VLOG(1) << "FailSimulatedPairing: " << object_path.value(); + + error_callback.Run(bluetooth_device::kErrorFailed, "Failed"); +} + +void FakeBluetoothDeviceClient::AddInputDeviceIfNeeded( + const dbus::ObjectPath& object_path, + Properties* properties) { + // If the paired device is a HID device based on it's bluetooth class, + // simulate the Input interface. + FakeBluetoothInputClient* fake_bluetooth_input_client = + static_cast<FakeBluetoothInputClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothInputClient()); + + if ((properties->bluetooth_class.value() & 0x001f03) == 0x000500) + fake_bluetooth_input_client->AddInputDevice(object_path); +} + +void FakeBluetoothDeviceClient::UpdateDeviceRSSI( + const dbus::ObjectPath& object_path, + int16 rssi) { + PropertiesMap::const_iterator iter = properties_map_.find(object_path); + if (iter == properties_map_.end()) { + VLOG(2) << "Fake device does not exist: " << object_path.value(); + return; + } + Properties* properties = iter->second; + DCHECK(properties); + properties->rssi.ReplaceValue(rssi); +} + +void FakeBluetoothDeviceClient::UpdateConnectionInfo( + uint16 connection_rssi, + uint16 transmit_power, + uint16 max_transmit_power) { + connection_rssi_ = connection_rssi; + transmit_power_ = transmit_power; + max_transmit_power_ = max_transmit_power; +} + +void FakeBluetoothDeviceClient::PinCodeCallback( + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback, + BluetoothAgentServiceProvider::Delegate::Status status, + const std::string& pincode) { + VLOG(1) << "PinCodeCallback: " << object_path.value(); + + if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) { + PairingOptionsMap::const_iterator iter = + pairing_options_map_.find(object_path); + + bool success = true; + + // If the device has pairing options defined + if (iter != pairing_options_map_.end()) { + success = iter->second->pairing_auth_token == pincode; + } + + if (success) { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, + base::Unretained(this), object_path, callback, + error_callback), + base::TimeDelta::FromMilliseconds(kSimulateNormalPairTimeMultiplier * + simulation_interval_ms_)); + } else { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, + base::Unretained(this), object_path, error_callback), + base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); + } + + } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing, + base::Unretained(this), object_path, error_callback), + base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); + + } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, + base::Unretained(this), object_path, error_callback), + base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); + } +} + +void FakeBluetoothDeviceClient::PasskeyCallback( + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback, + BluetoothAgentServiceProvider::Delegate::Status status, + uint32 passkey) { + VLOG(1) << "PasskeyCallback: " << object_path.value(); + + if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) { + PairingOptionsMap::const_iterator iter = + pairing_options_map_.find(object_path); + bool success = true; + + if (iter != pairing_options_map_.end()) { + success = static_cast<uint32>( + std::stoi(iter->second->pairing_auth_token)) == passkey; + } + + if (success) { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, + base::Unretained(this), object_path, callback, + error_callback), + base::TimeDelta::FromMilliseconds(kSimulateNormalPairTimeMultiplier * + simulation_interval_ms_)); + } else { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, + base::Unretained(this), object_path, error_callback), + base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); + } + + } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing, + base::Unretained(this), object_path, error_callback), + base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); + + } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, + base::Unretained(this), object_path, error_callback), + base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); + } +} + +void FakeBluetoothDeviceClient::ConfirmationCallback( + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback, + BluetoothAgentServiceProvider::Delegate::Status status) { + VLOG(1) << "ConfirmationCallback: " << object_path.value(); + + if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, + base::Unretained(this), object_path, callback, + error_callback), + base::TimeDelta::FromMilliseconds(kSimulateNormalPairTimeMultiplier * + simulation_interval_ms_)); + + } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing, + base::Unretained(this), object_path, error_callback), + base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); + + } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, + base::Unretained(this), object_path, error_callback), + base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); + } +} + +void FakeBluetoothDeviceClient::SimulateKeypress( + uint16 entered, + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "SimulateKeypress " << entered << ": " << object_path.value(); + + FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client = + static_cast<FakeBluetoothAgentManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothAgentManagerClient()); + FakeBluetoothAgentServiceProvider* agent_service_provider = + fake_bluetooth_agent_manager_client->GetAgentServiceProvider(); + + // The agent service provider object could have been destroyed after the + // pairing is canceled. + if (!agent_service_provider) + return; + + agent_service_provider->DisplayPasskey(object_path, kTestPassKey, entered); + + if (entered < 7) { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress, + base::Unretained(this), entered + 1, object_path, + callback, error_callback), + base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); + + } else { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, + base::Unretained(this), object_path, callback, + error_callback), + base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); + } +} + +void FakeBluetoothDeviceClient::ConnectionCallback( + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback, + BluetoothProfileServiceProvider::Delegate::Status status) { + VLOG(1) << "ConnectionCallback: " << object_path.value(); + + if (status == BluetoothProfileServiceProvider::Delegate::SUCCESS) { + callback.Run(); + } else if (status == BluetoothProfileServiceProvider::Delegate::CANCELLED) { + // TODO(keybuk): tear down this side of the connection + error_callback.Run(bluetooth_device::kErrorFailed, "Canceled"); + } else if (status == BluetoothProfileServiceProvider::Delegate::REJECTED) { + // TODO(keybuk): tear down this side of the connection + error_callback.Run(bluetooth_device::kErrorFailed, "Rejected"); + } +} + +void FakeBluetoothDeviceClient::DisconnectionCallback( + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback, + BluetoothProfileServiceProvider::Delegate::Status status) { + VLOG(1) << "DisconnectionCallback: " << object_path.value(); + + if (status == BluetoothProfileServiceProvider::Delegate::SUCCESS) { + // TODO(keybuk): tear down this side of the connection + callback.Run(); + } else if (status == BluetoothProfileServiceProvider::Delegate::CANCELLED) { + error_callback.Run(bluetooth_device::kErrorFailed, "Canceled"); + } else if (status == BluetoothProfileServiceProvider::Delegate::REJECTED) { + error_callback.Run(bluetooth_device::kErrorFailed, "Rejected"); + } +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_device_client.h b/device/bluetooth/dbus/fake_bluetooth_device_client.h new file mode 100644 index 0000000..f8051b4 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_device_client.h
@@ -0,0 +1,321 @@ +// Copyright (c) 2013 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 DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_DEVICE_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_DEVICE_CLIENT_H_ + +#include <map> +#include <vector> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/containers/scoped_ptr_map.h" +#include "base/observer_list.h" +#include "dbus/object_path.h" +#include "dbus/property.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_agent_service_provider.h" +#include "device/bluetooth/dbus/bluetooth_device_client.h" +#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h" + +namespace bluez { + +// FakeBluetoothDeviceClient simulates the behavior of the Bluetooth Daemon +// device objects and is used both in test cases in place of a mock and on +// the Linux desktop. +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothDeviceClient + : public BluetoothDeviceClient { + public: + struct Properties : public BluetoothDeviceClient::Properties { + explicit Properties(const PropertyChangedCallback& callback); + ~Properties() override; + + // dbus::PropertySet override + void Get(dbus::PropertyBase* property, + dbus::PropertySet::GetCallback callback) override; + void GetAll() override; + void Set(dbus::PropertyBase* property, + dbus::PropertySet::SetCallback callback) override; + }; + + struct SimulatedPairingOptions { + SimulatedPairingOptions(); + ~SimulatedPairingOptions(); + + bool incoming = false; + std::string pairing_method; + std::string pairing_auth_token; + std::string pairing_action; + }; + + // Stores properties of a device that is about to be created. + struct IncomingDeviceProperties { + IncomingDeviceProperties(); + ~IncomingDeviceProperties(); + + std::string device_address; + std::string device_alias; + int device_class = 0; + std::string device_name; + std::string device_path; + bool is_trusted = true; + bool incoming = false; + std::string pairing_action; + std::string pairing_auth_token; + std::string pairing_method; + }; + + FakeBluetoothDeviceClient(); + ~FakeBluetoothDeviceClient() override; + + // BluetoothDeviceClient overrides + void Init(dbus::Bus* bus) override; + void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; + std::vector<dbus::ObjectPath> GetDevicesForAdapter( + const dbus::ObjectPath& adapter_path) override; + Properties* GetProperties(const dbus::ObjectPath& object_path) override; + void Connect(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void Disconnect(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void ConnectProfile(const dbus::ObjectPath& object_path, + const std::string& uuid, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void DisconnectProfile(const dbus::ObjectPath& object_path, + const std::string& uuid, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void Pair(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void CancelPairing(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void GetConnInfo(const dbus::ObjectPath& object_path, + const ConnInfoCallback& callback, + const ErrorCallback& error_callback) override; + + void SetSimulationIntervalMs(int interval_ms); + + // Simulates discovery of devices for the given adapter. + void BeginDiscoverySimulation(const dbus::ObjectPath& adapter_path); + void EndDiscoverySimulation(const dbus::ObjectPath& adapter_path); + + // Simulates incoming pairing of devices for the given adapter. + void BeginIncomingPairingSimulation(const dbus::ObjectPath& adapter_path); + void EndIncomingPairingSimulation(const dbus::ObjectPath& adapter_path); + + // Creates a device from the set we return for the given adapter. + void CreateDevice(const dbus::ObjectPath& adapter_path, + const dbus::ObjectPath& device_path); + + // Creates a device with the given properties. + void CreateDeviceWithProperties(const dbus::ObjectPath& adapter_path, + const IncomingDeviceProperties& props); + + // Creates and returns a list of scoped_ptr<base::DictionaryValue> + // objects, which contain all the data from the constants for devices with + // predefined behavior. + scoped_ptr<base::ListValue> GetBluetoothDevicesAsDictionaries() const; + + SimulatedPairingOptions* GetPairingOptions( + const dbus::ObjectPath& object_path); + + // Removes a device from the set we return for the given adapter. + void RemoveDevice(const dbus::ObjectPath& adapter_path, + const dbus::ObjectPath& device_path); + + // Simulates a pairing for the device with the given D-Bus object path, + // |object_path|. Set |incoming_request| to true if simulating an incoming + // pairing request, false for an outgoing one. On successful completion + // |callback| will be called, on failure, |error_callback| is called. + void SimulatePairing(const dbus::ObjectPath& object_path, + bool incoming_request, + const base::Closure& callback, + const ErrorCallback& error_callback); + + // Updates the connection properties of the fake device that will be returned + // by GetConnInfo. + void UpdateConnectionInfo(uint16 connection_rssi, + uint16 transmit_power, + uint16 max_transmit_power); + + static const char kTestPinCode[]; + static const int kTestPassKey; + + static const char kPairingMethodNone[]; + static const char kPairingMethodPinCode[]; + static const char kPairingMethodPassKey[]; + + static const char kPairingActionConfirmation[]; + static const char kPairingActionDisplay[]; + static const char kPairingActionFail[]; + static const char kPairingActionRequest[]; + + // Object paths, names, addresses and bluetooth classes of the devices + // we can emulate. + static const char kPairedDevicePath[]; + static const char kPairedDeviceName[]; + static const char kPairedDeviceAddress[]; + static const uint32 kPairedDeviceClass; + + static const char kLegacyAutopairPath[]; + static const char kLegacyAutopairName[]; + static const char kLegacyAutopairAddress[]; + static const uint32 kLegacyAutopairClass; + + static const char kDisplayPinCodePath[]; + static const char kDisplayPinCodeName[]; + static const char kDisplayPinCodeAddress[]; + static const uint32 kDisplayPinCodeClass; + + static const char kVanishingDevicePath[]; + static const char kVanishingDeviceName[]; + static const char kVanishingDeviceAddress[]; + static const uint32 kVanishingDeviceClass; + + static const char kConnectUnpairablePath[]; + static const char kConnectUnpairableName[]; + static const char kConnectUnpairableAddress[]; + static const uint32 kConnectUnpairableClass; + + static const char kDisplayPasskeyPath[]; + static const char kDisplayPasskeyName[]; + static const char kDisplayPasskeyAddress[]; + static const uint32 kDisplayPasskeyClass; + + static const char kRequestPinCodePath[]; + static const char kRequestPinCodeName[]; + static const char kRequestPinCodeAddress[]; + static const uint32 kRequestPinCodeClass; + + static const char kConfirmPasskeyPath[]; + static const char kConfirmPasskeyName[]; + static const char kConfirmPasskeyAddress[]; + static const uint32 kConfirmPasskeyClass; + + static const char kRequestPasskeyPath[]; + static const char kRequestPasskeyName[]; + static const char kRequestPasskeyAddress[]; + static const uint32 kRequestPasskeyClass; + + static const char kUnconnectableDevicePath[]; + static const char kUnconnectableDeviceName[]; + static const char kUnconnectableDeviceAddress[]; + static const uint32 kUnconnectableDeviceClass; + + static const char kUnpairableDevicePath[]; + static const char kUnpairableDeviceName[]; + static const char kUnpairableDeviceAddress[]; + static const uint32 kUnpairableDeviceClass; + + static const char kJustWorksPath[]; + static const char kJustWorksName[]; + static const char kJustWorksAddress[]; + static const uint32 kJustWorksClass; + + static const char kLowEnergyPath[]; + static const char kLowEnergyName[]; + static const char kLowEnergyAddress[]; + static const uint32 kLowEnergyClass; + + static const char kPairedUnconnectableDevicePath[]; + static const char kPairedUnconnectableDeviceName[]; + static const char kPairedUnconnectableDeviceAddress[]; + static const uint32 kPairedUnconnectableDeviceClass; + + static const char kConnectedTrustedNotPairedDevicePath[]; + static const char kConnectedTrustedNotPairedDeviceAddress[]; + static const char kConnectedTrustedNotPairedDeviceName[]; + static const uint32 kConnectedTrustedNotPairedDeviceClass; + + private: + // Property callback passed when we create Properties* structures. + void OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name); + + void DiscoverySimulationTimer(); + void IncomingPairingSimulationTimer(); + + void CompleteSimulatedPairing(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback); + void TimeoutSimulatedPairing(const dbus::ObjectPath& object_path, + const ErrorCallback& error_callback); + void CancelSimulatedPairing(const dbus::ObjectPath& object_path, + const ErrorCallback& error_callback); + void RejectSimulatedPairing(const dbus::ObjectPath& object_path, + const ErrorCallback& error_callback); + void FailSimulatedPairing(const dbus::ObjectPath& object_path, + const ErrorCallback& error_callback); + void AddInputDeviceIfNeeded(const dbus::ObjectPath& object_path, + Properties* properties); + + // Updates the inquiry RSSI property of fake device with object path + // |object_path| to |rssi|, if the fake device exists. + void UpdateDeviceRSSI(const dbus::ObjectPath& object_path, int16 rssi); + + void PinCodeCallback(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback, + BluetoothAgentServiceProvider::Delegate::Status status, + const std::string& pincode); + void PasskeyCallback(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback, + BluetoothAgentServiceProvider::Delegate::Status status, + uint32 passkey); + void ConfirmationCallback( + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback, + BluetoothAgentServiceProvider::Delegate::Status status); + void SimulateKeypress(uint16 entered, + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback); + + void ConnectionCallback( + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback, + BluetoothProfileServiceProvider::Delegate::Status status); + void DisconnectionCallback( + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback, + BluetoothProfileServiceProvider::Delegate::Status status); + + // List of observers interested in event notifications from us. + base::ObserverList<Observer> observers_; + + using PropertiesMap = + base::ScopedPtrMap<const dbus::ObjectPath, scoped_ptr<Properties>>; + PropertiesMap properties_map_; + std::vector<dbus::ObjectPath> device_list_; + + // Properties which are used to decied which method of pairing should + // be done on request. + using PairingOptionsMap = + base::ScopedPtrMap<const dbus::ObjectPath, + scoped_ptr<SimulatedPairingOptions>>; + PairingOptionsMap pairing_options_map_; + + int simulation_interval_ms_; + uint32_t discovery_simulation_step_; + uint32_t incoming_pairing_simulation_step_; + bool pairing_cancelled_; + + int16 connection_rssi_; + int16 transmit_power_; + int16 max_transmit_power_; +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_DEVICE_CLIENT_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc new file mode 100644 index 0000000..10f073a --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc
@@ -0,0 +1,562 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/rand_util.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" +#include "base/time/time.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +namespace { + +const int kStartNotifyResponseIntervalMs = 200; +const int kHeartRateMeasurementNotificationIntervalMs = 2000; + +} // namespace + +FakeBluetoothGattCharacteristicClient::DelayedCallback::DelayedCallback( + base::Closure callback, + size_t delay) + : callback_(callback), delay_(delay) {} + +FakeBluetoothGattCharacteristicClient::DelayedCallback::~DelayedCallback() {} + +// static +const char FakeBluetoothGattCharacteristicClient:: + kHeartRateMeasurementPathComponent[] = "char0000"; +const char + FakeBluetoothGattCharacteristicClient::kBodySensorLocationPathComponent[] = + "char0001"; +const char FakeBluetoothGattCharacteristicClient:: + kHeartRateControlPointPathComponent[] = "char0002"; + +// static +const char FakeBluetoothGattCharacteristicClient::kHeartRateMeasurementUUID[] = + "00002a37-0000-1000-8000-00805f9b34fb"; +const char FakeBluetoothGattCharacteristicClient::kBodySensorLocationUUID[] = + "00002a38-0000-1000-8000-00805f9b34fb"; +const char FakeBluetoothGattCharacteristicClient::kHeartRateControlPointUUID[] = + "00002a39-0000-1000-8000-00805f9b34fb"; + +FakeBluetoothGattCharacteristicClient::Properties::Properties( + const PropertyChangedCallback& callback) + : BluetoothGattCharacteristicClient::Properties( + NULL, + bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, + callback) {} + +FakeBluetoothGattCharacteristicClient::Properties::~Properties() {} + +void FakeBluetoothGattCharacteristicClient::Properties::Get( + dbus::PropertyBase* property, + dbus::PropertySet::GetCallback callback) { + VLOG(1) << "Get " << property->name(); + callback.Run(true); +} + +void FakeBluetoothGattCharacteristicClient::Properties::GetAll() { + VLOG(1) << "GetAll"; +} + +void FakeBluetoothGattCharacteristicClient::Properties::Set( + dbus::PropertyBase* property, + dbus::PropertySet::SetCallback callback) { + VLOG(1) << "Set " << property->name(); + callback.Run(false); +} + +FakeBluetoothGattCharacteristicClient::FakeBluetoothGattCharacteristicClient() + : heart_rate_visible_(false), + authorized_(true), + authenticated_(true), + calories_burned_(0), + extra_requests_(0), + weak_ptr_factory_(this) {} + +FakeBluetoothGattCharacteristicClient:: + ~FakeBluetoothGattCharacteristicClient() { + for (const auto& it : action_extra_requests_) { + delete it.second; + } + action_extra_requests_.clear(); +} + +void FakeBluetoothGattCharacteristicClient::Init(dbus::Bus* bus) {} + +void FakeBluetoothGattCharacteristicClient::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void FakeBluetoothGattCharacteristicClient::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +std::vector<dbus::ObjectPath> +FakeBluetoothGattCharacteristicClient::GetCharacteristics() { + std::vector<dbus::ObjectPath> paths; + if (IsHeartRateVisible()) { + paths.push_back(dbus::ObjectPath(heart_rate_measurement_path_)); + paths.push_back(dbus::ObjectPath(body_sensor_location_path_)); + paths.push_back(dbus::ObjectPath(heart_rate_control_point_path_)); + } + return paths; +} + +FakeBluetoothGattCharacteristicClient::Properties* +FakeBluetoothGattCharacteristicClient::GetProperties( + const dbus::ObjectPath& object_path) { + if (object_path.value() == heart_rate_measurement_path_) { + DCHECK(heart_rate_measurement_properties_.get()); + return heart_rate_measurement_properties_.get(); + } + if (object_path.value() == body_sensor_location_path_) { + DCHECK(body_sensor_location_properties_.get()); + return body_sensor_location_properties_.get(); + } + if (object_path.value() == heart_rate_control_point_path_) { + DCHECK(heart_rate_control_point_properties_.get()); + return heart_rate_control_point_properties_.get(); + } + return NULL; +} + +void FakeBluetoothGattCharacteristicClient::ReadValue( + const dbus::ObjectPath& object_path, + const ValueCallback& callback, + const ErrorCallback& error_callback) { + if (!authenticated_) { + error_callback.Run("org.bluez.Error.NotPaired", "Please login"); + return; + } + + if (!authorized_) { + error_callback.Run("org.bluez.Error.NotAuthorized", "Authorize first"); + return; + } + + if (object_path.value() == heart_rate_control_point_path_) { + error_callback.Run("org.bluez.Error.NotPermitted", + "Reads of this value are not allowed"); + return; + } + + if (object_path.value() == heart_rate_measurement_path_) { + error_callback.Run("org.bluez.Error.NotSupported", + "Action not supported on this characteristic"); + return; + } + + if (object_path.value() != body_sensor_location_path_) { + error_callback.Run(kUnknownCharacteristicError, ""); + return; + } + + if (action_extra_requests_.find("ReadValue") != + action_extra_requests_.end()) { + DelayedCallback* delayed = action_extra_requests_["ReadValue"]; + delayed->delay_--; + error_callback.Run("org.bluez.Error.InProgress", + "Another read is currenty in progress"); + if (delayed->delay_ == 0) { + delayed->callback_.Run(); + action_extra_requests_.erase("ReadValue"); + delete delayed; + } + return; + } + + base::Closure completed_callback; + if (!IsHeartRateVisible()) { + completed_callback = + base::Bind(error_callback, kUnknownCharacteristicError, ""); + } else { + std::vector<uint8> value = {0x06}; // Location is "foot". + completed_callback = base::Bind( + &FakeBluetoothGattCharacteristicClient::DelayedReadValueCallback, + weak_ptr_factory_.GetWeakPtr(), object_path, callback, value); + } + + if (extra_requests_ > 0) { + action_extra_requests_["ReadValue"] = + new DelayedCallback(completed_callback, extra_requests_); + return; + } + + completed_callback.Run(); +} + +void FakeBluetoothGattCharacteristicClient::WriteValue( + const dbus::ObjectPath& object_path, + const std::vector<uint8>& value, + const base::Closure& callback, + const ErrorCallback& error_callback) { + if (!authenticated_) { + error_callback.Run("org.bluez.Error.NotPaired", "Please login"); + return; + } + + if (!authorized_) { + error_callback.Run("org.bluez.Error.NotAuthorized", "Authorize first"); + return; + } + + if (!IsHeartRateVisible()) { + error_callback.Run(kUnknownCharacteristicError, ""); + return; + } + + if (object_path.value() == heart_rate_measurement_path_) { + error_callback.Run("org.bluez.Error.NotSupported", + "Action not supported on this characteristic"); + return; + } + + if (object_path.value() != heart_rate_control_point_path_) { + error_callback.Run("org.bluez.Error.NotPermitted", + "Writes of this value are not allowed"); + return; + } + + DCHECK(heart_rate_control_point_properties_.get()); + if (action_extra_requests_.find("WriteValue") != + action_extra_requests_.end()) { + DelayedCallback* delayed = action_extra_requests_["WriteValue"]; + delayed->delay_--; + error_callback.Run("org.bluez.Error.InProgress", + "Another write is in progress"); + if (delayed->delay_ == 0) { + delayed->callback_.Run(); + action_extra_requests_.erase("WriteValue"); + delete delayed; + } + return; + } + base::Closure completed_callback; + if (value.size() != 1) { + completed_callback = + base::Bind(error_callback, "org.bluez.Error.InvalidValueLength", + "Invalid length for write"); + } else if (value[0] > 1) { + completed_callback = base::Bind(error_callback, "org.bluez.Error.Failed", + "Invalid value given for write"); + } else if (value[0] == 1) { + // TODO(jamuraa): make this happen when the callback happens + calories_burned_ = 0; + completed_callback = callback; + } + + if (extra_requests_ > 0) { + action_extra_requests_["WriteValue"] = + new DelayedCallback(completed_callback, extra_requests_); + return; + } + completed_callback.Run(); +} + +void FakeBluetoothGattCharacteristicClient::StartNotify( + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + if (!IsHeartRateVisible()) { + error_callback.Run(kUnknownCharacteristicError, ""); + return; + } + + if (object_path.value() != heart_rate_measurement_path_) { + error_callback.Run("org.bluez.Error.NotSupported", + "This characteristic does not support notifications"); + return; + } + + if (heart_rate_measurement_properties_->notifying.value()) { + error_callback.Run("org.bluez.Error.InProgress", + "Characteristic already notifying"); + return; + } + + heart_rate_measurement_properties_->notifying.ReplaceValue(true); + ScheduleHeartRateMeasurementValueChange(); + + // Respond asynchronously. + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, callback, + base::TimeDelta::FromMilliseconds(kStartNotifyResponseIntervalMs)); +} + +void FakeBluetoothGattCharacteristicClient::StopNotify( + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + if (!IsHeartRateVisible()) { + error_callback.Run(kUnknownCharacteristicError, ""); + return; + } + + if (object_path.value() != heart_rate_measurement_path_) { + error_callback.Run("org.bluez.Error.NotSupported", + "This characteristic does not support notifications"); + return; + } + + if (!heart_rate_measurement_properties_->notifying.value()) { + error_callback.Run("org.bluez.Error.Failed", "Not notifying"); + return; + } + + heart_rate_measurement_properties_->notifying.ReplaceValue(false); + + callback.Run(); +} + +void FakeBluetoothGattCharacteristicClient::ExposeHeartRateCharacteristics( + const dbus::ObjectPath& service_path) { + if (IsHeartRateVisible()) { + VLOG(2) << "Fake Heart Rate characteristics are already visible."; + return; + } + + VLOG(2) << "Exposing fake Heart Rate characteristics."; + + std::vector<std::string> flags; + + // ==== Heart Rate Measurement Characteristic ==== + heart_rate_measurement_path_ = + service_path.value() + "/" + kHeartRateMeasurementPathComponent; + heart_rate_measurement_properties_.reset(new Properties( + base::Bind(&FakeBluetoothGattCharacteristicClient::OnPropertyChanged, + weak_ptr_factory_.GetWeakPtr(), + dbus::ObjectPath(heart_rate_measurement_path_)))); + heart_rate_measurement_properties_->uuid.ReplaceValue( + kHeartRateMeasurementUUID); + heart_rate_measurement_properties_->service.ReplaceValue(service_path); + flags.push_back(bluetooth_gatt_characteristic::kFlagNotify); + heart_rate_measurement_properties_->flags.ReplaceValue(flags); + + // ==== Body Sensor Location Characteristic ==== + body_sensor_location_path_ = + service_path.value() + "/" + kBodySensorLocationPathComponent; + body_sensor_location_properties_.reset(new Properties( + base::Bind(&FakeBluetoothGattCharacteristicClient::OnPropertyChanged, + weak_ptr_factory_.GetWeakPtr(), + dbus::ObjectPath(body_sensor_location_path_)))); + body_sensor_location_properties_->uuid.ReplaceValue(kBodySensorLocationUUID); + body_sensor_location_properties_->service.ReplaceValue(service_path); + flags.clear(); + flags.push_back(bluetooth_gatt_characteristic::kFlagRead); + body_sensor_location_properties_->flags.ReplaceValue(flags); + + // ==== Heart Rate Control Point Characteristic ==== + heart_rate_control_point_path_ = + service_path.value() + "/" + kHeartRateControlPointPathComponent; + heart_rate_control_point_properties_.reset(new Properties( + base::Bind(&FakeBluetoothGattCharacteristicClient::OnPropertyChanged, + weak_ptr_factory_.GetWeakPtr(), + dbus::ObjectPath(heart_rate_control_point_path_)))); + heart_rate_control_point_properties_->uuid.ReplaceValue( + kHeartRateControlPointUUID); + heart_rate_control_point_properties_->service.ReplaceValue(service_path); + flags.clear(); + flags.push_back(bluetooth_gatt_characteristic::kFlagWrite); + heart_rate_control_point_properties_->flags.ReplaceValue(flags); + + heart_rate_visible_ = true; + + NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_measurement_path_)); + NotifyCharacteristicAdded(dbus::ObjectPath(body_sensor_location_path_)); + NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_control_point_path_)); + + // Expose CCC descriptor for Heart Rate Measurement characteristic. + FakeBluetoothGattDescriptorClient* descriptor_client = + static_cast<FakeBluetoothGattDescriptorClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothGattDescriptorClient()); + dbus::ObjectPath ccc_path(descriptor_client->ExposeDescriptor( + dbus::ObjectPath(heart_rate_measurement_path_), + FakeBluetoothGattDescriptorClient:: + kClientCharacteristicConfigurationUUID)); + DCHECK(ccc_path.IsValid()); + heart_rate_measurement_ccc_desc_path_ = ccc_path.value(); + + std::vector<dbus::ObjectPath> desc_paths; + desc_paths.push_back(ccc_path); + + heart_rate_measurement_properties_->descriptors.ReplaceValue(desc_paths); +} + +void FakeBluetoothGattCharacteristicClient::HideHeartRateCharacteristics() { + VLOG(2) << "Hiding fake Heart Rate characteristics."; + + // Hide the descriptors. + FakeBluetoothGattDescriptorClient* descriptor_client = + static_cast<FakeBluetoothGattDescriptorClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothGattDescriptorClient()); + descriptor_client->HideDescriptor( + dbus::ObjectPath(heart_rate_measurement_ccc_desc_path_)); + + // Notify the observers before deleting the properties structures so that they + // can be accessed from the observer method. + NotifyCharacteristicRemoved(dbus::ObjectPath(heart_rate_measurement_path_)); + NotifyCharacteristicRemoved(dbus::ObjectPath(body_sensor_location_path_)); + NotifyCharacteristicRemoved(dbus::ObjectPath(heart_rate_control_point_path_)); + + heart_rate_measurement_properties_.reset(); + body_sensor_location_properties_.reset(); + heart_rate_control_point_properties_.reset(); + + heart_rate_measurement_path_.clear(); + body_sensor_location_path_.clear(); + heart_rate_control_point_path_.clear(); + heart_rate_visible_ = false; +} + +void FakeBluetoothGattCharacteristicClient::SetExtraProcessing( + size_t requests) { + extra_requests_ = requests; + if (extra_requests_ == 0) { + for (const auto& it : action_extra_requests_) { + it.second->callback_.Run(); + delete it.second; + } + action_extra_requests_.clear(); + return; + } + VLOG(2) << "Requests SLOW now, " << requests << " InProgress errors each."; +} + +size_t FakeBluetoothGattCharacteristicClient::GetExtraProcessing() const { + return extra_requests_; +} + +dbus::ObjectPath +FakeBluetoothGattCharacteristicClient::GetHeartRateMeasurementPath() const { + return dbus::ObjectPath(heart_rate_measurement_path_); +} + +dbus::ObjectPath +FakeBluetoothGattCharacteristicClient::GetBodySensorLocationPath() const { + return dbus::ObjectPath(body_sensor_location_path_); +} + +dbus::ObjectPath +FakeBluetoothGattCharacteristicClient::GetHeartRateControlPointPath() const { + return dbus::ObjectPath(heart_rate_control_point_path_); +} + +void FakeBluetoothGattCharacteristicClient::OnPropertyChanged( + const dbus::ObjectPath& object_path, + const std::string& property_name) { + VLOG(2) << "Characteristic property changed: " << object_path.value() << ": " + << property_name; + + FOR_EACH_OBSERVER( + BluetoothGattCharacteristicClient::Observer, observers_, + GattCharacteristicPropertyChanged(object_path, property_name)); +} + +void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicAdded( + const dbus::ObjectPath& object_path) { + VLOG(2) << "GATT characteristic added: " << object_path.value(); + FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, + GattCharacteristicAdded(object_path)); +} + +void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicRemoved( + const dbus::ObjectPath& object_path) { + VLOG(2) << "GATT characteristic removed: " << object_path.value(); + FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, + GattCharacteristicRemoved(object_path)); +} + +void FakeBluetoothGattCharacteristicClient:: + ScheduleHeartRateMeasurementValueChange() { + if (!IsHeartRateVisible()) + return; + + // Don't send updates if the characteristic is not notifying. + if (!heart_rate_measurement_properties_->notifying.value()) + return; + + VLOG(2) << "Updating heart rate value."; + std::vector<uint8> measurement = GetHeartRateMeasurementValue(); + heart_rate_measurement_properties_->value.ReplaceValue(measurement); + + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, base::Bind(&FakeBluetoothGattCharacteristicClient:: + ScheduleHeartRateMeasurementValueChange, + weak_ptr_factory_.GetWeakPtr()), + base::TimeDelta::FromMilliseconds( + kHeartRateMeasurementNotificationIntervalMs)); +} + +void FakeBluetoothGattCharacteristicClient::DelayedReadValueCallback( + const dbus::ObjectPath& object_path, + const ValueCallback& callback, + const std::vector<uint8_t>& value) { + Properties* properties = GetProperties(object_path); + DCHECK(properties); + + properties->value.ReplaceValue(value); + callback.Run(value); +} + +std::vector<uint8> +FakeBluetoothGattCharacteristicClient::GetHeartRateMeasurementValue() { + // TODO(armansito): We should make sure to properly pack this struct to ensure + // correct byte alignment and endianness. It doesn't matter too much right now + // as this is a fake and GCC on Linux seems to do the right thing. + struct { + uint8 flags; + uint8 bpm; + uint16 energy_expanded; + uint16 rr_interval; + } value; + + // Flags in LSB: 0 11 1 1 000 + // | | | | | + // 8-bit bpm format -- | | | | + // Sensor contact supported -- | | | + // Energy expanded field present -- | | + // RR-Interval values present ------- | + // Reserved for future use ------------ + value.flags = 0x0; + value.flags |= (0x03 << 1); + value.flags |= (0x01 << 3); + value.flags |= (0x01 << 4); + + // Pick a value between 117 bpm and 153 bpm for heart rate. + value.bpm = static_cast<uint8>(base::RandInt(117, 153)); + + // Total calories burned in kJoules since the last reset. Increment this by 1 + // every time. It's fine if it overflows: it becomes 0 when the user resets + // the heart rate monitor (or pretend that he had a lot of cheeseburgers). + value.energy_expanded = calories_burned_++; + + // Include one RR-Interval value, in seconds. + value.rr_interval = 60 / value.bpm; + + // Return the bytes in an array. + uint8* bytes = reinterpret_cast<uint8*>(&value); + std::vector<uint8> return_value; + return_value.assign(bytes, bytes + sizeof(value)); + return return_value; +} + +bool FakeBluetoothGattCharacteristicClient::IsHeartRateVisible() const { + DCHECK(heart_rate_visible_ != heart_rate_measurement_path_.empty()); + DCHECK(heart_rate_visible_ != body_sensor_location_path_.empty()); + DCHECK(heart_rate_visible_ != heart_rate_control_point_path_.empty()); + DCHECK(heart_rate_visible_ == !!heart_rate_measurement_properties_.get()); + DCHECK(heart_rate_visible_ == !!body_sensor_location_properties_.get()); + DCHECK(heart_rate_visible_ == !!heart_rate_control_point_properties_.get()); + return heart_rate_visible_; +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h new file mode 100644 index 0000000..89fefcc5 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h
@@ -0,0 +1,194 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "dbus/object_path.h" +#include "dbus/property.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h" + +namespace bluez { + +// FakeBluetoothGattCharacteristicClient simulates the behavior of the +// Bluetooth Daemon GATT characteristic objects and is used in test cases in +// place of a mock and on the Linux desktop. +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothGattCharacteristicClient + : public BluetoothGattCharacteristicClient { + public: + struct Properties : public BluetoothGattCharacteristicClient::Properties { + explicit Properties(const PropertyChangedCallback& callback); + ~Properties() override; + + // dbus::PropertySet override + void Get(dbus::PropertyBase* property, + dbus::PropertySet::GetCallback callback) override; + void GetAll() override; + void Set(dbus::PropertyBase* property, + dbus::PropertySet::SetCallback callback) override; + }; + + FakeBluetoothGattCharacteristicClient(); + ~FakeBluetoothGattCharacteristicClient() override; + + // DBusClient override. + void Init(dbus::Bus* bus) override; + + // BluetoothGattCharacteristicClient overrides. + void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; + std::vector<dbus::ObjectPath> GetCharacteristics() override; + Properties* GetProperties(const dbus::ObjectPath& object_path) override; + void ReadValue(const dbus::ObjectPath& object_path, + const ValueCallback& callback, + const ErrorCallback& error_callback) override; + void WriteValue(const dbus::ObjectPath& object_path, + const std::vector<uint8>& value, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void StartNotify(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void StopNotify(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + + // Makes the group of characteristics belonging to a particular GATT based + // profile available under the GATT service with object path |service_path|. + // Characteristic paths are hierarchical to service paths. + void ExposeHeartRateCharacteristics(const dbus::ObjectPath& service_path); + void HideHeartRateCharacteristics(); + + // Returns whether or not the heart rate characteristics are visible and + // performs the appropriate assertions. + bool IsHeartRateVisible() const; + + // Makes this characteristic client really slow. + // So slow, that it is guaranteed that |requests| requests will + // come in while the client is doing the previous request. + // Setting |requests| to zero will cause all delayed actions to + // complete immediately. + void SetExtraProcessing(size_t requests); + + size_t GetExtraProcessing() const; + + // Sets whether the client is authorized or not. + // Defaults to authorized. + void SetAuthorized(bool authorized) { authorized_ = authorized; } + + // Get the current Authorization state. + bool IsAuthorized() const { return authorized_; } + + // Whether the client is Authenticated + // Defaults to authenticated. + void SetAuthenticated(bool authenticated) { authenticated_ = authenticated; } + + // Get the current Authenticated state. + bool IsAuthenticated() const { return authenticated_; } + + // Returns the current object paths of exposed characteristics. If the + // characteristic is not visible, returns an invalid empty path. + dbus::ObjectPath GetHeartRateMeasurementPath() const; + dbus::ObjectPath GetBodySensorLocationPath() const; + dbus::ObjectPath GetHeartRateControlPointPath() const; + + // Object path components and UUIDs of GATT characteristics. + // Heart Rate Service: + static const char kHeartRateMeasurementPathComponent[]; + static const char kHeartRateMeasurementUUID[]; + static const char kBodySensorLocationPathComponent[]; + static const char kBodySensorLocationUUID[]; + static const char kHeartRateControlPointPathComponent[]; + static const char kHeartRateControlPointUUID[]; + + private: + // Property callback passed when we create Properties structures. + void OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name); + + // Notifies observers. + void NotifyCharacteristicAdded(const dbus::ObjectPath& object_path); + void NotifyCharacteristicRemoved(const dbus::ObjectPath& object_path); + + // Schedules a heart rate measurement value change, if the heart rate + // characteristics are visible. + void ScheduleHeartRateMeasurementValueChange(); + + // Returns a random Heart Rate Measurement value. All the fields of the value + // are populated according to the the fake behavior. The measurement value + // is a random value within a reasonable range. + std::vector<uint8> GetHeartRateMeasurementValue(); + + // Callback that executes a delayed ReadValue action by updating the + // appropriate "Value" property and invoking the ValueCallback. + void DelayedReadValueCallback(const dbus::ObjectPath& object_path, + const ValueCallback& callback, + const std::vector<uint8_t>& value); + + // If true, characteristics of the Heart Rate Service are visible. Use + // IsHeartRateVisible() to check the value. + bool heart_rate_visible_; + + // If true, the client is authorized to read and write. + bool authorized_; + + // If true, the client is authenticated. + bool authenticated_; + + // Total calories burned, used for the Heart Rate Measurement characteristic. + uint16 calories_burned_; + + // Static properties returned for simulated characteristics for the Heart + // Rate Service. These pointers are not NULL only if the characteristics are + // actually exposed. + scoped_ptr<Properties> heart_rate_measurement_properties_; + scoped_ptr<Properties> body_sensor_location_properties_; + scoped_ptr<Properties> heart_rate_control_point_properties_; + + // Object paths of the exposed characteristics. If a characteristic is not + // exposed, these will be empty. + std::string heart_rate_measurement_path_; + std::string heart_rate_measurement_ccc_desc_path_; + std::string body_sensor_location_path_; + std::string heart_rate_control_point_path_; + + // Number of extra requests that need to come in simulating slowness. + size_t extra_requests_; + + // Current countdowns for extra requests for various actions. + struct DelayedCallback { + public: + DelayedCallback(base::Closure callback, size_t delay); + ~DelayedCallback(); + + base::Closure callback_; + size_t delay_; + }; + + // Map of delayed callbacks. + std::map<std::string, DelayedCallback*> action_extra_requests_; + + // List of observers interested in event notifications from us. + base::ObserverList<Observer> observers_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<FakeBluetoothGattCharacteristicClient> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattCharacteristicClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.cc new file mode 100644 index 0000000..03f06d03 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.cc
@@ -0,0 +1,105 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.h" + +#include "base/logging.h" +#include "base/strings/string_util.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h" + +namespace bluez { + +FakeBluetoothGattCharacteristicServiceProvider:: + FakeBluetoothGattCharacteristicServiceProvider( + const dbus::ObjectPath& object_path, + Delegate* delegate, + const std::string& uuid, + const std::vector<std::string>& flags, + const std::vector<std::string>& permissions, + const dbus::ObjectPath& service_path) + : object_path_(object_path), + uuid_(uuid), + service_path_(service_path), + delegate_(delegate) { + VLOG(1) << "Creating Bluetooth GATT characteristic: " << object_path_.value(); + + DCHECK(object_path_.IsValid()); + DCHECK(service_path_.IsValid()); + DCHECK(!uuid.empty()); + DCHECK(delegate_); + DCHECK(base::StartsWith(object_path_.value(), service_path_.value() + "/", + base::CompareCase::SENSITIVE)); + + // TODO(armansito): Do something with |flags| and |permissions|. + + FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = + static_cast<FakeBluetoothGattManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient()); + fake_bluetooth_gatt_manager_client->RegisterCharacteristicServiceProvider( + this); +} + +FakeBluetoothGattCharacteristicServiceProvider:: + ~FakeBluetoothGattCharacteristicServiceProvider() { + VLOG(1) << "Cleaning up Bluetooth GATT characteristic: " + << object_path_.value(); + + FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = + static_cast<FakeBluetoothGattManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient()); + fake_bluetooth_gatt_manager_client->UnregisterCharacteristicServiceProvider( + this); +} + +void FakeBluetoothGattCharacteristicServiceProvider::SendValueChanged( + const std::vector<uint8>& value) { + VLOG(1) << "Sent characteristic value changed: " << object_path_.value() + << " UUID: " << uuid_; +} + +void FakeBluetoothGattCharacteristicServiceProvider::GetValue( + const Delegate::ValueCallback& callback, + const Delegate::ErrorCallback& error_callback) { + VLOG(1) << "GATT characteristic value Get request: " << object_path_.value() + << " UUID: " << uuid_; + + // Check if this characteristic is registered. + FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = + static_cast<FakeBluetoothGattManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient()); + if (!fake_bluetooth_gatt_manager_client->IsServiceRegistered(service_path_)) { + VLOG(1) << "GATT characteristic not registered."; + error_callback.Run(); + return; + } + + // Pass on to the delegate. + DCHECK(delegate_); + delegate_->GetCharacteristicValue(callback, error_callback); +} + +void FakeBluetoothGattCharacteristicServiceProvider::SetValue( + const std::vector<uint8>& value, + const base::Closure& callback, + const Delegate::ErrorCallback& error_callback) { + VLOG(1) << "GATT characteristic value Set request: " << object_path_.value() + << " UUID: " << uuid_; + + // Check if this characteristic is registered. + FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = + static_cast<FakeBluetoothGattManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient()); + if (!fake_bluetooth_gatt_manager_client->IsServiceRegistered(service_path_)) { + VLOG(1) << "GATT characteristic not registered."; + error_callback.Run(); + return; + } + + // Pass on to the delegate. + DCHECK(delegate_); + delegate_->SetCharacteristicValue(value, callback, error_callback); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.h b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.h new file mode 100644 index 0000000..675eba9 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.h
@@ -0,0 +1,67 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_ + +#include <string> +#include <vector> + +#include "base/macros.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.h" + +namespace bluez { + +// FakeBluetoothGattCharacteristicServiceProvider simulates behavior of a local +// GATT characteristic object and is used both in test cases in place of a mock +// and on the Linux desktop. +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothGattCharacteristicServiceProvider + : public BluetoothGattCharacteristicServiceProvider { + public: + FakeBluetoothGattCharacteristicServiceProvider( + const dbus::ObjectPath& object_path, + Delegate* delegate, + const std::string& uuid, + const std::vector<std::string>& flags, + const std::vector<std::string>& permissions, + const dbus::ObjectPath& service_path); + ~FakeBluetoothGattCharacteristicServiceProvider() override; + + // BluetoothGattCharacteristicServiceProvider override. + void SendValueChanged(const std::vector<uint8>& value) override; + + // Methods to simulate value get/set requests issued from a remote device. The + // methods do nothing, if the associated service was not registered with the + // GATT manager. + void GetValue(const Delegate::ValueCallback& callback, + const Delegate::ErrorCallback& error_callback); + void SetValue(const std::vector<uint8>& value, + const base::Closure& callback, + const Delegate::ErrorCallback& error_callback); + + const dbus::ObjectPath& object_path() const { return object_path_; } + const std::string& uuid() const { return uuid_; } + const dbus::ObjectPath& service_path() const { return service_path_; } + + private: + // D-Bus object path of the fake GATT characteristic. + dbus::ObjectPath object_path_; + + // 128-bit GATT characteristic UUID. + std::string uuid_; + + // Object path of the service that this characteristic belongs to. + dbus::ObjectPath service_path_; + + // The delegate that method calls are passed on to. + Delegate* delegate_; + + DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattCharacteristicServiceProvider); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.cc new file mode 100644 index 0000000..dcaf1ecd --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.cc
@@ -0,0 +1,209 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +const char FakeBluetoothGattDescriptorClient:: + kClientCharacteristicConfigurationPathComponent[] = "desc0000"; +const char FakeBluetoothGattDescriptorClient:: + kClientCharacteristicConfigurationUUID[] = + "00002902-0000-1000-8000-00805f9b34fb"; + +FakeBluetoothGattDescriptorClient::Properties::Properties( + const PropertyChangedCallback& callback) + : BluetoothGattDescriptorClient::Properties( + NULL, + bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface, + callback) {} + +FakeBluetoothGattDescriptorClient::Properties::~Properties() {} + +void FakeBluetoothGattDescriptorClient::Properties::Get( + dbus::PropertyBase* property, + dbus::PropertySet::GetCallback callback) { + VLOG(1) << "Get " << property->name(); + callback.Run(true); +} + +void FakeBluetoothGattDescriptorClient::Properties::GetAll() { + VLOG(1) << "GetAll"; +} + +void FakeBluetoothGattDescriptorClient::Properties::Set( + dbus::PropertyBase* property, + dbus::PropertySet::SetCallback callback) { + VLOG(1) << "Set " << property->name(); + callback.Run(false); +} + +FakeBluetoothGattDescriptorClient::DescriptorData::DescriptorData() {} + +FakeBluetoothGattDescriptorClient::DescriptorData::~DescriptorData() {} + +FakeBluetoothGattDescriptorClient::FakeBluetoothGattDescriptorClient() + : weak_ptr_factory_(this) {} + +FakeBluetoothGattDescriptorClient::~FakeBluetoothGattDescriptorClient() { + for (PropertiesMap::iterator iter = properties_.begin(); + iter != properties_.end(); iter++) + delete iter->second; +} + +void FakeBluetoothGattDescriptorClient::Init(dbus::Bus* bus) {} + +void FakeBluetoothGattDescriptorClient::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void FakeBluetoothGattDescriptorClient::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +std::vector<dbus::ObjectPath> +FakeBluetoothGattDescriptorClient::GetDescriptors() { + std::vector<dbus::ObjectPath> descriptors; + for (PropertiesMap::const_iterator iter = properties_.begin(); + iter != properties_.end(); ++iter) { + descriptors.push_back(iter->first); + } + return descriptors; +} + +FakeBluetoothGattDescriptorClient::Properties* +FakeBluetoothGattDescriptorClient::GetProperties( + const dbus::ObjectPath& object_path) { + PropertiesMap::const_iterator iter = properties_.find(object_path); + if (iter == properties_.end()) + return NULL; + return iter->second->properties.get(); +} + +void FakeBluetoothGattDescriptorClient::ReadValue( + const dbus::ObjectPath& object_path, + const ValueCallback& callback, + const ErrorCallback& error_callback) { + PropertiesMap::iterator iter = properties_.find(object_path); + if (iter == properties_.end()) { + error_callback.Run(kUnknownDescriptorError, ""); + return; + } + + // Assign the value of the descriptor as necessary + Properties* properties = iter->second->properties.get(); + if (properties->uuid.value() == kClientCharacteristicConfigurationUUID) { + BluetoothGattCharacteristicClient::Properties* chrc_props = + bluez::BluezDBusManager::Get() + ->GetBluetoothGattCharacteristicClient() + ->GetProperties(properties->characteristic.value()); + DCHECK(chrc_props); + + uint8_t value_byte = chrc_props->notifying.value() ? 0x01 : 0x00; + const std::vector<uint8_t>& cur_value = properties->value.value(); + + if (!cur_value.size() || cur_value[0] != value_byte) { + std::vector<uint8_t> value = {value_byte, 0x00}; + properties->value.ReplaceValue(value); + } + } + + callback.Run(iter->second->properties->value.value()); +} + +void FakeBluetoothGattDescriptorClient::WriteValue( + const dbus::ObjectPath& object_path, + const std::vector<uint8>& value, + const base::Closure& callback, + const ErrorCallback& error_callback) { + if (properties_.find(object_path) == properties_.end()) { + error_callback.Run(kUnknownDescriptorError, ""); + return; + } + + // Since the only fake descriptor is "Client Characteristic Configuration" + // and BlueZ doesn't allow writing to it, return failure. + error_callback.Run("org.bluez.Error.NotPermitted", + "Writing to the Client Characteristic Configuration " + "descriptor not allowed"); +} + +dbus::ObjectPath FakeBluetoothGattDescriptorClient::ExposeDescriptor( + const dbus::ObjectPath& characteristic_path, + const std::string& uuid) { + if (uuid != kClientCharacteristicConfigurationUUID) { + VLOG(2) << "Unsupported UUID: " << uuid; + return dbus::ObjectPath(); + } + + // CCC descriptor is the only one supported at the moment. + DCHECK(characteristic_path.IsValid()); + dbus::ObjectPath object_path(characteristic_path.value() + "/" + + kClientCharacteristicConfigurationPathComponent); + DCHECK(object_path.IsValid()); + PropertiesMap::const_iterator iter = properties_.find(object_path); + if (iter != properties_.end()) { + VLOG(1) << "Descriptor already exposed: " << object_path.value(); + return dbus::ObjectPath(); + } + + Properties* properties = new Properties( + base::Bind(&FakeBluetoothGattDescriptorClient::OnPropertyChanged, + weak_ptr_factory_.GetWeakPtr(), object_path)); + properties->uuid.ReplaceValue(uuid); + properties->characteristic.ReplaceValue(characteristic_path); + + DescriptorData* data = new DescriptorData(); + data->properties.reset(properties); + + properties_[object_path] = data; + + NotifyDescriptorAdded(object_path); + + return object_path; +} + +void FakeBluetoothGattDescriptorClient::HideDescriptor( + const dbus::ObjectPath& descriptor_path) { + PropertiesMap::iterator iter = properties_.find(descriptor_path); + if (iter == properties_.end()) { + VLOG(1) << "Descriptor not exposed: " << descriptor_path.value(); + return; + } + + NotifyDescriptorRemoved(descriptor_path); + + delete iter->second; + properties_.erase(iter); +} + +void FakeBluetoothGattDescriptorClient::OnPropertyChanged( + const dbus::ObjectPath& object_path, + const std::string& property_name) { + VLOG(2) << "Descriptor property changed: " << object_path.value() << ": " + << property_name; + + FOR_EACH_OBSERVER(BluetoothGattDescriptorClient::Observer, observers_, + GattDescriptorPropertyChanged(object_path, property_name)); +} + +void FakeBluetoothGattDescriptorClient::NotifyDescriptorAdded( + const dbus::ObjectPath& object_path) { + FOR_EACH_OBSERVER(BluetoothGattDescriptorClient::Observer, observers_, + GattDescriptorAdded(object_path)); +} + +void FakeBluetoothGattDescriptorClient::NotifyDescriptorRemoved( + const dbus::ObjectPath& object_path) { + FOR_EACH_OBSERVER(BluetoothGattDescriptorClient::Observer, observers_, + GattDescriptorRemoved(object_path)); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h new file mode 100644 index 0000000..0e8e8565 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h
@@ -0,0 +1,104 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_ + +#include <map> +#include <string> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h" + +namespace bluez { + +// FakeBluetoothGattDescriptorClient simulates the behavior of the Bluetooth +// Daemon GATT characteristic descriptor objects and is used in test cases in +// place of a mock and on the Linux desktop. +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothGattDescriptorClient + : public BluetoothGattDescriptorClient { + public: + struct Properties : public BluetoothGattDescriptorClient::Properties { + explicit Properties(const PropertyChangedCallback& callback); + ~Properties() override; + + // dbus::PropertySet override + void Get(dbus::PropertyBase* property, + dbus::PropertySet::GetCallback callback) override; + void GetAll() override; + void Set(dbus::PropertyBase* property, + dbus::PropertySet::SetCallback callback) override; + }; + + FakeBluetoothGattDescriptorClient(); + ~FakeBluetoothGattDescriptorClient() override; + + // DBusClient override. + void Init(dbus::Bus* bus) override; + + // BluetoothGattDescriptorClient overrides. + void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; + std::vector<dbus::ObjectPath> GetDescriptors() override; + Properties* GetProperties(const dbus::ObjectPath& object_path) override; + void ReadValue(const dbus::ObjectPath& object_path, + const ValueCallback& callback, + const ErrorCallback& error_callback) override; + void WriteValue(const dbus::ObjectPath& object_path, + const std::vector<uint8>& value, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + + // Makes the descriptor with the UUID |uuid| visible under the characteristic + // with object path |characteristic_path|. Descriptor object paths are + // hierarchical to their characteristics. |uuid| must belong to a descriptor + // for which there is a constant defined below, otherwise this method has no + // effect. Returns the object path of the created descriptor. In the no-op + // case, returns an invalid path. + dbus::ObjectPath ExposeDescriptor(const dbus::ObjectPath& characteristic_path, + const std::string& uuid); + void HideDescriptor(const dbus::ObjectPath& descriptor_path); + + // Object path components and UUIDs of GATT characteristic descriptors. + static const char kClientCharacteristicConfigurationPathComponent[]; + static const char kClientCharacteristicConfigurationUUID[]; + + private: + // Property callback passed when we create Properties structures. + void OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name); + + // Notifies observers. + void NotifyDescriptorAdded(const dbus::ObjectPath& object_path); + void NotifyDescriptorRemoved(const dbus::ObjectPath& object_path); + + // Mapping from object paths to Properties structures. + struct DescriptorData { + DescriptorData(); + ~DescriptorData(); + + scoped_ptr<Properties> properties; + }; + typedef std::map<dbus::ObjectPath, DescriptorData*> PropertiesMap; + PropertiesMap properties_; + + // List of observers interested in event notifications from us. + base::ObserverList<Observer> observers_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<FakeBluetoothGattDescriptorClient> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattDescriptorClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.cc new file mode 100644 index 0000000..4376ce98 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.cc
@@ -0,0 +1,121 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.h" + +#include "base/logging.h" +#include "base/strings/string_util.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h" + +namespace bluez { + +FakeBluetoothGattDescriptorServiceProvider:: + FakeBluetoothGattDescriptorServiceProvider( + const dbus::ObjectPath& object_path, + Delegate* delegate, + const std::string& uuid, + const std::vector<std::string>& permissions, + const dbus::ObjectPath& characteristic_path) + : object_path_(object_path), + uuid_(uuid), + characteristic_path_(characteristic_path), + delegate_(delegate) { + VLOG(1) << "Creating Bluetooth GATT descriptor: " << object_path_.value(); + + DCHECK(object_path_.IsValid()); + DCHECK(characteristic_path_.IsValid()); + DCHECK(!uuid.empty()); + DCHECK(delegate_); + DCHECK(base::StartsWith(object_path_.value(), + characteristic_path_.value() + "/", + base::CompareCase::SENSITIVE)); + + // TODO(armansito): Do something with |permissions|. + + FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = + static_cast<FakeBluetoothGattManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient()); + fake_bluetooth_gatt_manager_client->RegisterDescriptorServiceProvider(this); +} + +FakeBluetoothGattDescriptorServiceProvider:: + ~FakeBluetoothGattDescriptorServiceProvider() { + VLOG(1) << "Cleaning up Bluetooth GATT descriptor: " << object_path_.value(); + + FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = + static_cast<FakeBluetoothGattManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient()); + fake_bluetooth_gatt_manager_client->UnregisterDescriptorServiceProvider(this); +} + +void FakeBluetoothGattDescriptorServiceProvider::SendValueChanged( + const std::vector<uint8>& value) { + VLOG(1) << "Sent descriptor value changed: " << object_path_.value() + << " UUID: " << uuid_; +} + +void FakeBluetoothGattDescriptorServiceProvider::GetValue( + const Delegate::ValueCallback& callback, + const Delegate::ErrorCallback& error_callback) { + VLOG(1) << "GATT descriptor value Get request: " << object_path_.value() + << " UUID: " << uuid_; + + // Check if this descriptor is registered. + FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = + static_cast<FakeBluetoothGattManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient()); + FakeBluetoothGattCharacteristicServiceProvider* characteristic = + fake_bluetooth_gatt_manager_client->GetCharacteristicServiceProvider( + characteristic_path_); + if (!characteristic) { + VLOG(1) << "GATT characteristic for descriptor does not exist: " + << characteristic_path_.value(); + return; + } + if (!fake_bluetooth_gatt_manager_client->IsServiceRegistered( + characteristic->service_path())) { + VLOG(1) << "GATT descriptor not registered."; + error_callback.Run(); + return; + } + + // Pass on to the delegate. + DCHECK(delegate_); + delegate_->GetDescriptorValue(callback, error_callback); +} + +void FakeBluetoothGattDescriptorServiceProvider::SetValue( + const std::vector<uint8>& value, + const base::Closure& callback, + const Delegate::ErrorCallback& error_callback) { + VLOG(1) << "GATT descriptor value Set request: " << object_path_.value() + << " UUID: " << uuid_; + + // Check if this descriptor is registered. + FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = + static_cast<FakeBluetoothGattManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient()); + FakeBluetoothGattCharacteristicServiceProvider* characteristic = + fake_bluetooth_gatt_manager_client->GetCharacteristicServiceProvider( + characteristic_path_); + if (!characteristic) { + VLOG(1) << "GATT characteristic for descriptor does not exist: " + << characteristic_path_.value(); + return; + } + if (!fake_bluetooth_gatt_manager_client->IsServiceRegistered( + characteristic->service_path())) { + VLOG(1) << "GATT descriptor not registered."; + error_callback.Run(); + return; + } + + // Pass on to the delegate. + DCHECK(delegate_); + delegate_->SetDescriptorValue(value, callback, error_callback); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.h b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.h new file mode 100644 index 0000000..7640acc5 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.h
@@ -0,0 +1,68 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_ + +#include <string> +#include <vector> + +#include "base/macros.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.h" + +namespace bluez { + +// FakeBluetoothGattDescriptorServiceProvider simulates behavior of a local +// GATT descriptor object and is used both in test cases in place of a mock +// and on the Linux desktop. +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothGattDescriptorServiceProvider + : public BluetoothGattDescriptorServiceProvider { + public: + FakeBluetoothGattDescriptorServiceProvider( + const dbus::ObjectPath& object_path, + Delegate* delegate, + const std::string& uuid, + const std::vector<std::string>& permissions, + const dbus::ObjectPath& characteristic_path); + ~FakeBluetoothGattDescriptorServiceProvider() override; + + // BluetoothGattDescriptorServiceProvider override. + void SendValueChanged(const std::vector<uint8>& value) override; + + // Methods to simulate value get/set requests issued from a remote device. The + // methods do nothing, if the associated service was not registered with the + // GATT manager. + void GetValue(const Delegate::ValueCallback& callback, + const Delegate::ErrorCallback& error_callback); + void SetValue(const std::vector<uint8>& value, + const base::Closure& callback, + const Delegate::ErrorCallback& error_callback); + + const dbus::ObjectPath& object_path() const { return object_path_; } + const std::string& uuid() const { return uuid_; } + const dbus::ObjectPath& characteristic_path() const { + return characteristic_path_; + } + + private: + // D-Bus object path of the fake GATT descriptor. + dbus::ObjectPath object_path_; + + // 128-bit GATT descriptor UUID. + std::string uuid_; + + // Object path of the characteristic that this descriptor belongs to. + dbus::ObjectPath characteristic_path_; + + // The delegate that method calls are passed on to. + Delegate* delegate_; + + DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattDescriptorServiceProvider); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.cc new file mode 100644 index 0000000..284a17c7 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.cc
@@ -0,0 +1,169 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h" + +#include "base/logging.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +FakeBluetoothGattManagerClient::FakeBluetoothGattManagerClient() {} + +FakeBluetoothGattManagerClient::~FakeBluetoothGattManagerClient() {} + +// DBusClient override. +void FakeBluetoothGattManagerClient::Init(dbus::Bus* bus) {} + +// BluetoothGattManagerClient overrides. +void FakeBluetoothGattManagerClient::RegisterService( + const dbus::ObjectPath& service_path, + const Options& options, + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "Register GATT service: " << service_path.value(); + + // If a service provider wasn't created before, return error. + ServiceMap::iterator iter = service_map_.find(service_path); + if (iter == service_map_.end()) { + error_callback.Run(bluetooth_gatt_manager::kErrorInvalidArguments, + "GATT service doesn't exist: " + service_path.value()); + return; + } + + // Check to see if this GATT service was already registered. + ServiceProvider* provider = &iter->second; + if (provider->first) { + error_callback.Run( + bluetooth_gatt_manager::kErrorAlreadyExists, + "GATT service already registered: " + service_path.value()); + return; + } + + // Success! + provider->first = true; + callback.Run(); +} + +void FakeBluetoothGattManagerClient::UnregisterService( + const dbus::ObjectPath& service_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "Unregister GATT service: " << service_path.value(); + + // If a service provider wasn't created before, return error. + ServiceMap::iterator iter = service_map_.find(service_path); + if (iter == service_map_.end()) { + error_callback.Run(bluetooth_gatt_manager::kErrorInvalidArguments, + "GATT service doesn't exist: " + service_path.value()); + return; + } + + // Return error if the GATT service wasn't registered before. + ServiceProvider* provider = &iter->second; + if (!provider->first) { + error_callback.Run(bluetooth_gatt_manager::kErrorDoesNotExist, + "GATT service not registered: " + service_path.value()); + return; + } + + // Success! + provider->first = false; + callback.Run(); +} + +void FakeBluetoothGattManagerClient::RegisterServiceServiceProvider( + FakeBluetoothGattServiceServiceProvider* provider) { + // Ignore, if a service provider is already registered for the object path. + ServiceMap::iterator iter = service_map_.find(provider->object_path()); + if (iter != service_map_.end()) { + VLOG(1) << "GATT service service provider already registered for " + << "object path: " << provider->object_path().value(); + return; + } + service_map_[provider->object_path()] = std::make_pair(false, provider); +} + +void FakeBluetoothGattManagerClient::RegisterCharacteristicServiceProvider( + FakeBluetoothGattCharacteristicServiceProvider* provider) { + // Ignore, if a service provider is already registered for the object path. + CharacteristicMap::iterator iter = + characteristic_map_.find(provider->object_path()); + if (iter != characteristic_map_.end()) { + VLOG(1) << "GATT characteristic service provider already registered for " + << "object path: " << provider->object_path().value(); + return; + } + characteristic_map_[provider->object_path()] = provider; +} + +void FakeBluetoothGattManagerClient::RegisterDescriptorServiceProvider( + FakeBluetoothGattDescriptorServiceProvider* provider) { + // Ignore, if a service provider is already registered for the object path. + DescriptorMap::iterator iter = descriptor_map_.find(provider->object_path()); + if (iter != descriptor_map_.end()) { + VLOG(1) << "GATT descriptor service provider already registered for " + << "object path: " << provider->object_path().value(); + return; + } + descriptor_map_[provider->object_path()] = provider; +} + +void FakeBluetoothGattManagerClient::UnregisterServiceServiceProvider( + FakeBluetoothGattServiceServiceProvider* provider) { + ServiceMap::iterator iter = service_map_.find(provider->object_path()); + if (iter != service_map_.end() && iter->second.second == provider) + service_map_.erase(iter); +} + +void FakeBluetoothGattManagerClient::UnregisterCharacteristicServiceProvider( + FakeBluetoothGattCharacteristicServiceProvider* provider) { + characteristic_map_.erase(provider->object_path()); +} + +void FakeBluetoothGattManagerClient::UnregisterDescriptorServiceProvider( + FakeBluetoothGattDescriptorServiceProvider* provider) { + descriptor_map_.erase(provider->object_path()); +} + +FakeBluetoothGattServiceServiceProvider* +FakeBluetoothGattManagerClient::GetServiceServiceProvider( + const dbus::ObjectPath& object_path) const { + ServiceMap::const_iterator iter = service_map_.find(object_path); + if (iter == service_map_.end()) + return NULL; + return iter->second.second; +} + +FakeBluetoothGattCharacteristicServiceProvider* +FakeBluetoothGattManagerClient::GetCharacteristicServiceProvider( + const dbus::ObjectPath& object_path) const { + CharacteristicMap::const_iterator iter = + characteristic_map_.find(object_path); + if (iter == characteristic_map_.end()) + return NULL; + return iter->second; +} + +FakeBluetoothGattDescriptorServiceProvider* +FakeBluetoothGattManagerClient::GetDescriptorServiceProvider( + const dbus::ObjectPath& object_path) const { + DescriptorMap::const_iterator iter = descriptor_map_.find(object_path); + if (iter == descriptor_map_.end()) + return NULL; + return iter->second; +} + +bool FakeBluetoothGattManagerClient::IsServiceRegistered( + const dbus::ObjectPath& object_path) const { + ServiceMap::const_iterator iter = service_map_.find(object_path); + if (iter == service_map_.end()) + return false; + return iter->second.first; +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h b/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h new file mode 100644 index 0000000..65082ae9 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h
@@ -0,0 +1,101 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_MANAGER_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_MANAGER_CLIENT_H_ + +#include <map> +#include <string> +#include <utility> + +#include "base/callback.h" +#include "base/macros.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_gatt_manager_client.h" + +namespace bluez { + +class FakeBluetoothGattCharacteristicServiceProvider; +class FakeBluetoothGattDescriptorServiceProvider; +class FakeBluetoothGattServiceServiceProvider; + +// FakeBluetoothGattManagerClient simulates the behavior of the Bluetooth +// daemon's GATT manager object and is used both in test cases in place of a +// mock and on the Linux desktop. +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothGattManagerClient + : public BluetoothGattManagerClient { + public: + FakeBluetoothGattManagerClient(); + ~FakeBluetoothGattManagerClient() override; + + // DBusClient override. + void Init(dbus::Bus* bus) override; + + // BluetoothGattManagerClient overrides. + void RegisterService(const dbus::ObjectPath& service_path, + const Options& options, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void UnregisterService(const dbus::ObjectPath& service_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + + // Register, unregister, and retrieve pointers to service, characteristic, and + // descriptor service providers. Automatically called from the service + // provider constructor and destructors. + void RegisterServiceServiceProvider( + FakeBluetoothGattServiceServiceProvider* provider); + void RegisterCharacteristicServiceProvider( + FakeBluetoothGattCharacteristicServiceProvider* provider); + void RegisterDescriptorServiceProvider( + FakeBluetoothGattDescriptorServiceProvider* provider); + + void UnregisterServiceServiceProvider( + FakeBluetoothGattServiceServiceProvider* provider); + void UnregisterCharacteristicServiceProvider( + FakeBluetoothGattCharacteristicServiceProvider* provider); + void UnregisterDescriptorServiceProvider( + FakeBluetoothGattDescriptorServiceProvider* provider); + + // Return a pointer to the service provider that corresponds to the object + // path |object_path| if it exists. + FakeBluetoothGattServiceServiceProvider* GetServiceServiceProvider( + const dbus::ObjectPath& object_path) const; + FakeBluetoothGattCharacteristicServiceProvider* + GetCharacteristicServiceProvider(const dbus::ObjectPath& object_path) const; + FakeBluetoothGattDescriptorServiceProvider* GetDescriptorServiceProvider( + const dbus::ObjectPath& object_path) const; + + // Returns true, if a GATT service with object path |object_path| was + // registered with the GATT manager using RegisterService. + bool IsServiceRegistered(const dbus::ObjectPath& object_path) const; + + private: + // Mappings for GATT service, characteristic, and descriptor service + // providers. The fake GATT manager stores references to all instances + // created so that they can be obtained by tests. + typedef std::map<dbus::ObjectPath, + FakeBluetoothGattCharacteristicServiceProvider*> + CharacteristicMap; + typedef std::map<dbus::ObjectPath, + FakeBluetoothGattDescriptorServiceProvider*> DescriptorMap; + + // The mapping for services is from object paths to pairs of boolean and + // service provider pointer, where the boolean denotes whether or not the + // service is already registered. + typedef std::pair<bool, FakeBluetoothGattServiceServiceProvider*> + ServiceProvider; + typedef std::map<dbus::ObjectPath, ServiceProvider> ServiceMap; + + ServiceMap service_map_; + CharacteristicMap characteristic_map_; + DescriptorMap descriptor_map_; + + DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattManagerClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_MANAGER_CLIENT_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.cc new file mode 100644 index 0000000..2e7aa0a --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.cc
@@ -0,0 +1,189 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" +#include "base/time/time.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +namespace { + +const int kExposeCharacteristicsDelayIntervalMs = 100; + +} // namespace + +// static +const char FakeBluetoothGattServiceClient::kHeartRateServicePathComponent[] = + "service0000"; +const char FakeBluetoothGattServiceClient::kHeartRateServiceUUID[] = + "0000180d-0000-1000-8000-00805f9b34fb"; + +FakeBluetoothGattServiceClient::Properties::Properties( + const PropertyChangedCallback& callback) + : BluetoothGattServiceClient::Properties( + NULL, + bluetooth_gatt_service::kBluetoothGattServiceInterface, + callback) {} + +FakeBluetoothGattServiceClient::Properties::~Properties() {} + +void FakeBluetoothGattServiceClient::Properties::Get( + dbus::PropertyBase* property, + dbus::PropertySet::GetCallback callback) { + VLOG(1) << "Get " << property->name(); + callback.Run(false); +} + +void FakeBluetoothGattServiceClient::Properties::GetAll() { + VLOG(1) << "GetAll"; +} + +void FakeBluetoothGattServiceClient::Properties::Set( + dbus::PropertyBase* property, + dbus::PropertySet::GetCallback callback) { + VLOG(1) << "Set " << property->name(); + callback.Run(false); +} + +FakeBluetoothGattServiceClient::FakeBluetoothGattServiceClient() + : weak_ptr_factory_(this) {} + +FakeBluetoothGattServiceClient::~FakeBluetoothGattServiceClient() {} + +void FakeBluetoothGattServiceClient::Init(dbus::Bus* bus) {} + +void FakeBluetoothGattServiceClient::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void FakeBluetoothGattServiceClient::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +std::vector<dbus::ObjectPath> FakeBluetoothGattServiceClient::GetServices() { + std::vector<dbus::ObjectPath> paths; + if (heart_rate_service_properties_.get()) { + DCHECK(!heart_rate_service_path_.empty()); + paths.push_back(dbus::ObjectPath(heart_rate_service_path_)); + } + return paths; +} + +FakeBluetoothGattServiceClient::Properties* +FakeBluetoothGattServiceClient::GetProperties( + const dbus::ObjectPath& object_path) { + if (object_path.value() == heart_rate_service_path_) + return heart_rate_service_properties_.get(); + return NULL; +} + +void FakeBluetoothGattServiceClient::ExposeHeartRateService( + const dbus::ObjectPath& device_path) { + if (IsHeartRateVisible()) { + DCHECK(!heart_rate_service_path_.empty()); + VLOG(1) << "Fake Heart Rate Service already exposed."; + return; + } + VLOG(2) << "Exposing fake Heart Rate Service."; + heart_rate_service_path_ = + device_path.value() + "/" + kHeartRateServicePathComponent; + heart_rate_service_properties_.reset(new Properties(base::Bind( + &FakeBluetoothGattServiceClient::OnPropertyChanged, + base::Unretained(this), dbus::ObjectPath(heart_rate_service_path_)))); + heart_rate_service_properties_->uuid.ReplaceValue(kHeartRateServiceUUID); + heart_rate_service_properties_->device.ReplaceValue(device_path); + heart_rate_service_properties_->primary.ReplaceValue(true); + + NotifyServiceAdded(dbus::ObjectPath(heart_rate_service_path_)); + + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind( + &FakeBluetoothGattServiceClient::ExposeHeartRateCharacteristics, + weak_ptr_factory_.GetWeakPtr()), + base::TimeDelta::FromMilliseconds(kExposeCharacteristicsDelayIntervalMs)); +} + +void FakeBluetoothGattServiceClient::HideHeartRateService() { + if (!IsHeartRateVisible()) { + DCHECK(heart_rate_service_path_.empty()); + VLOG(1) << "Fake Heart Rate Service already hidden."; + return; + } + VLOG(2) << "Hiding fake Heart Rate Service."; + FakeBluetoothGattCharacteristicClient* char_client = + static_cast<FakeBluetoothGattCharacteristicClient*>( + bluez::BluezDBusManager::Get() + ->GetBluetoothGattCharacteristicClient()); + char_client->HideHeartRateCharacteristics(); + + // Notify observers before deleting the properties structure so that it + // can be accessed from the observer method. + NotifyServiceRemoved(dbus::ObjectPath(heart_rate_service_path_)); + + heart_rate_service_properties_.reset(); + heart_rate_service_path_.clear(); +} + +bool FakeBluetoothGattServiceClient::IsHeartRateVisible() const { + return !!heart_rate_service_properties_.get(); +} + +dbus::ObjectPath FakeBluetoothGattServiceClient::GetHeartRateServicePath() + const { + return dbus::ObjectPath(heart_rate_service_path_); +} + +void FakeBluetoothGattServiceClient::OnPropertyChanged( + const dbus::ObjectPath& object_path, + const std::string& property_name) { + VLOG(2) << "Fake GATT Service property changed: " << object_path.value() + << ": " << property_name; + FOR_EACH_OBSERVER(BluetoothGattServiceClient::Observer, observers_, + GattServicePropertyChanged(object_path, property_name)); +} + +void FakeBluetoothGattServiceClient::NotifyServiceAdded( + const dbus::ObjectPath& object_path) { + VLOG(2) << "GATT service added: " << object_path.value(); + FOR_EACH_OBSERVER(BluetoothGattServiceClient::Observer, observers_, + GattServiceAdded(object_path)); +} + +void FakeBluetoothGattServiceClient::NotifyServiceRemoved( + const dbus::ObjectPath& object_path) { + VLOG(2) << "GATT service removed: " << object_path.value(); + FOR_EACH_OBSERVER(BluetoothGattServiceClient::Observer, observers_, + GattServiceRemoved(object_path)); +} + +void FakeBluetoothGattServiceClient::ExposeHeartRateCharacteristics() { + if (!IsHeartRateVisible()) { + VLOG(2) << "Heart Rate service not visible. Not exposing characteristics."; + return; + } + FakeBluetoothGattCharacteristicClient* char_client = + static_cast<FakeBluetoothGattCharacteristicClient*>( + bluez::BluezDBusManager::Get() + ->GetBluetoothGattCharacteristicClient()); + char_client->ExposeHeartRateCharacteristics( + dbus::ObjectPath(heart_rate_service_path_)); + + std::vector<dbus::ObjectPath> char_paths; + char_paths.push_back(char_client->GetHeartRateMeasurementPath()); + char_paths.push_back(char_client->GetBodySensorLocationPath()); + char_paths.push_back(char_client->GetHeartRateControlPointPath()); + + heart_rate_service_properties_->characteristics.ReplaceValue(char_paths); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h b/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h new file mode 100644 index 0000000..faebb423 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h
@@ -0,0 +1,107 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_SERVICE_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_SERVICE_CLIENT_H_ + +#include <string> +#include <vector> + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "dbus/object_path.h" +#include "dbus/property.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h" + +namespace bluez { + +// FakeBluetoothGattServiceClient simulates the behavior of the Bluetooth Daemon +// GATT service objects and is used in test cases in place of a mock and on the +// Linux desktop. +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothGattServiceClient + : public BluetoothGattServiceClient { + public: + struct Properties : public BluetoothGattServiceClient::Properties { + explicit Properties(const PropertyChangedCallback& callback); + ~Properties() override; + + // dbus::PropertySet override + void Get(dbus::PropertyBase* property, + dbus::PropertySet::GetCallback callback) override; + void GetAll() override; + void Set(dbus::PropertyBase* property, + dbus::PropertySet::SetCallback callback) override; + }; + + FakeBluetoothGattServiceClient(); + ~FakeBluetoothGattServiceClient() override; + + // DBusClient override. + void Init(dbus::Bus* bus) override; + + // BluetoothGattServiceClient overrides. + void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; + std::vector<dbus::ObjectPath> GetServices() override; + Properties* GetProperties(const dbus::ObjectPath& object_path) override; + + // Makes a service visible for device with object path |device_path|. Note + // that only one instance of a specific service is simulated at a time. Hence, + // this method will fail, if the service is already visible. + void ExposeHeartRateService(const dbus::ObjectPath& device_path); + void HideHeartRateService(); + + // Returns whether or not the Heart Rate Service is visible. + bool IsHeartRateVisible() const; + + // Returns the current object path of the visible Heart Rate service. If the + // service is not visible, returns an invalid empty path. + dbus::ObjectPath GetHeartRateServicePath() const; + + // Final object path components and the corresponding UUIDs of the GATT + // services that we emulate. Service paths are hierarchical to Bluetooth + // device paths, so if the path component is "service0000", and the device + // path is "/org/foo/device0", the service path is + // "/org/foo/device0/service0000". + static const char kHeartRateServicePathComponent[]; + static const char kHeartRateServiceUUID[]; + + private: + // Property callback passed when we create Properties structures. + void OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name); + + // Notifies observers. + void NotifyServiceAdded(const dbus::ObjectPath& object_path); + void NotifyServiceRemoved(const dbus::ObjectPath& object_path); + + // Tells FakeBluetoothGattCharacteristicClient to expose GATT characteristics. + // This is scheduled from ExposeHeartRateService to simulate asynchronous + // retrieval of characteristics. If the Heart Rate Service is hidden at the + // time this method is called, then it does nothing. + void ExposeHeartRateCharacteristics(); + + // Static properties we return. As long as a service is exposed, this will be + // non-null. Otherwise it will be null. + scoped_ptr<Properties> heart_rate_service_properties_; + std::string heart_rate_service_path_; + + // List of observers interested in event notifications from us. + base::ObserverList<Observer> observers_; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<FakeBluetoothGattServiceClient> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattServiceClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_SERVICE_CLIENT_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.cc new file mode 100644 index 0000000..8d724058 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.cc
@@ -0,0 +1,37 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.h" + +#include "base/logging.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h" + +namespace bluez { + +FakeBluetoothGattServiceServiceProvider:: + FakeBluetoothGattServiceServiceProvider( + const dbus::ObjectPath& object_path, + const std::string& uuid, + const std::vector<dbus::ObjectPath>& includes) + : object_path_(object_path), uuid_(uuid), includes_(includes) { + VLOG(1) << "Creating Bluetooth GATT service: " << object_path_.value(); + + FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = + static_cast<FakeBluetoothGattManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient()); + fake_bluetooth_gatt_manager_client->RegisterServiceServiceProvider(this); +} + +FakeBluetoothGattServiceServiceProvider:: + ~FakeBluetoothGattServiceServiceProvider() { + VLOG(1) << "Cleaning up Bluetooth GATT service: " << object_path_.value(); + + FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client = + static_cast<FakeBluetoothGattManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient()); + fake_bluetooth_gatt_manager_client->UnregisterServiceServiceProvider(this); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.h b/device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.h new file mode 100644 index 0000000..ca8b52e0 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.h
@@ -0,0 +1,48 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_ + +#include <string> +#include <vector> + +#include "base/macros.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_gatt_service_service_provider.h" + +namespace bluez { + +// FakeBluetoothGattServiceServiceProvider simulates behavior of a local GATT +// service object and is used both in test cases in place of a mock and on the +// Linux desktop. +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothGattServiceServiceProvider + : public BluetoothGattServiceServiceProvider { + public: + FakeBluetoothGattServiceServiceProvider( + const dbus::ObjectPath& object_path, + const std::string& uuid, + const std::vector<dbus::ObjectPath>& includes); + ~FakeBluetoothGattServiceServiceProvider() override; + + const dbus::ObjectPath& object_path() const { return object_path_; } + const std::string& uuid() const { return uuid_; } + + private: + // D-Bus object path of the fake GATT service. + dbus::ObjectPath object_path_; + + // 128-bit GATT service UUID. + std::string uuid_; + + // List of included GATT services. + std::vector<dbus::ObjectPath> includes_; + + DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattServiceServiceProvider); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_input_client.cc b/device/bluetooth/dbus/fake_bluetooth_input_client.cc new file mode 100644 index 0000000..849c3be --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_input_client.cc
@@ -0,0 +1,123 @@ +// Copyright (c) 2013 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 "device/bluetooth/dbus/fake_bluetooth_input_client.h" + +#include <map> + +#include "base/logging.h" +#include "base/stl_util.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_manager.h" +#include "dbus/object_proxy.h" +#include "device/bluetooth/dbus/fake_bluetooth_device_client.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +FakeBluetoothInputClient::Properties::Properties( + const PropertyChangedCallback& callback) + : BluetoothInputClient::Properties( + NULL, + bluetooth_input::kBluetoothInputInterface, + callback) {} + +FakeBluetoothInputClient::Properties::~Properties() {} + +void FakeBluetoothInputClient::Properties::Get( + dbus::PropertyBase* property, + dbus::PropertySet::GetCallback callback) { + VLOG(1) << "Get " << property->name(); + callback.Run(false); +} + +void FakeBluetoothInputClient::Properties::GetAll() { + VLOG(1) << "GetAll"; +} + +void FakeBluetoothInputClient::Properties::Set( + dbus::PropertyBase* property, + dbus::PropertySet::SetCallback callback) { + VLOG(1) << "Set " << property->name(); + callback.Run(false); +} + +FakeBluetoothInputClient::FakeBluetoothInputClient() {} + +FakeBluetoothInputClient::~FakeBluetoothInputClient() { + // Clean up Properties structures + STLDeleteValues(&properties_map_); +} + +void FakeBluetoothInputClient::Init(dbus::Bus* bus) {} + +void FakeBluetoothInputClient::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void FakeBluetoothInputClient::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +FakeBluetoothInputClient::Properties* FakeBluetoothInputClient::GetProperties( + const dbus::ObjectPath& object_path) { + PropertiesMap::iterator iter = properties_map_.find(object_path); + if (iter != properties_map_.end()) + return iter->second; + return NULL; +} + +void FakeBluetoothInputClient::AddInputDevice( + const dbus::ObjectPath& object_path) { + if (properties_map_.find(object_path) != properties_map_.end()) + return; + + Properties* properties = + new Properties(base::Bind(&FakeBluetoothInputClient::OnPropertyChanged, + base::Unretained(this), object_path)); + + // The LegacyAutopair and DisplayPinCode devices represent a typical mouse + // and keyboard respectively, so mark them as ReconnectMode "any". The + // DisplayPasskey device represents a Bluetooth 2.1+ keyboard and the + // ConnectUnpairable device represents a pre-standardization mouse, so mark + // them as ReconnectMode "device". + if (object_path.value() == FakeBluetoothDeviceClient::kDisplayPasskeyPath || + object_path.value() == + FakeBluetoothDeviceClient::kConnectUnpairablePath) { + properties->reconnect_mode.ReplaceValue( + bluetooth_input::kDeviceReconnectModeProperty); + } else { + properties->reconnect_mode.ReplaceValue( + bluetooth_input::kAnyReconnectModeProperty); + } + + properties_map_[object_path] = properties; + + FOR_EACH_OBSERVER(BluetoothInputClient::Observer, observers_, + InputAdded(object_path)); +} + +void FakeBluetoothInputClient::RemoveInputDevice( + const dbus::ObjectPath& object_path) { + PropertiesMap::iterator it = properties_map_.find(object_path); + + if (it == properties_map_.end()) + return; + + FOR_EACH_OBSERVER(BluetoothInputClient::Observer, observers_, + InputRemoved(object_path)); + + delete it->second; + properties_map_.erase(it); +} + +void FakeBluetoothInputClient::OnPropertyChanged( + const dbus::ObjectPath& object_path, + const std::string& property_name) { + FOR_EACH_OBSERVER(BluetoothInputClient::Observer, observers_, + InputPropertyChanged(object_path, property_name)); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_input_client.h b/device/bluetooth/dbus/fake_bluetooth_input_client.h new file mode 100644 index 0000000..81139db --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_input_client.h
@@ -0,0 +1,66 @@ +// Copyright (c) 2013 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 DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_INPUT_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_INPUT_CLIENT_H_ + +#include "base/callback.h" +#include "base/macros.h" +#include "base/observer_list.h" +#include "dbus/object_path.h" +#include "dbus/property.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_input_client.h" + +namespace bluez { + +// FakeBluetoothInputClient simulates the behavior of the Bluetooth Daemon +// input device objects and is used both in test cases in place of a mock and on +// the Linux desktop. +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothInputClient + : public BluetoothInputClient { + public: + struct Properties : public BluetoothInputClient::Properties { + explicit Properties(const PropertyChangedCallback& callback); + ~Properties() override; + + // dbus::PropertySet override + void Get(dbus::PropertyBase* property, + dbus::PropertySet::GetCallback callback) override; + void GetAll() override; + void Set(dbus::PropertyBase* property, + dbus::PropertySet::SetCallback callback) override; + }; + + FakeBluetoothInputClient(); + ~FakeBluetoothInputClient() override; + + // BluetoothInputClient overrides + void Init(dbus::Bus* bus) override; + void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; + Properties* GetProperties(const dbus::ObjectPath& object_path) override; + + // Simulate device addition/removal + void AddInputDevice(const dbus::ObjectPath& object_path); + void RemoveInputDevice(const dbus::ObjectPath& object_path); + + private: + // Property callback passed when we create Properties* structures. + void OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name); + + // Static properties we return. + typedef std::map<const dbus::ObjectPath, Properties*> PropertiesMap; + PropertiesMap properties_map_; + + // List of observers interested in event notifications from us. + base::ObserverList<Observer> observers_; + + DISALLOW_COPY_AND_ASSIGN(FakeBluetoothInputClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_INPUT_CLIENT_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.cc b/device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.cc new file mode 100644 index 0000000..043df05c --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.cc
@@ -0,0 +1,46 @@ +// Copyright 2015 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 "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.h" +#include "device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.h" + +namespace bluez { + +FakeBluetoothLEAdvertisementServiceProvider:: + FakeBluetoothLEAdvertisementServiceProvider( + const dbus::ObjectPath& object_path, + Delegate* delegate) + : delegate_(delegate) { + object_path_ = object_path; + VLOG(1) << "Creating Bluetooth Advertisement: " << object_path_.value(); + + FakeBluetoothLEAdvertisingManagerClient* + fake_bluetooth_profile_manager_client = + static_cast<FakeBluetoothLEAdvertisingManagerClient*>( + bluez::BluezDBusManager::Get() + ->GetBluetoothLEAdvertisingManagerClient()); + fake_bluetooth_profile_manager_client->RegisterAdvertisementServiceProvider( + this); +} + +FakeBluetoothLEAdvertisementServiceProvider:: + ~FakeBluetoothLEAdvertisementServiceProvider() { + VLOG(1) << "Cleaning up Bluetooth Advertisement: " << object_path_.value(); + + FakeBluetoothLEAdvertisingManagerClient* + fake_bluetooth_profile_manager_client = + static_cast<FakeBluetoothLEAdvertisingManagerClient*>( + bluez::BluezDBusManager::Get() + ->GetBluetoothLEAdvertisingManagerClient()); + fake_bluetooth_profile_manager_client->UnregisterAdvertisementServiceProvider( + this); +} + +void FakeBluetoothLEAdvertisementServiceProvider::Release() { + VLOG(1) << object_path_.value() << ": Release"; + delegate_->Released(); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.h b/device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.h new file mode 100644 index 0000000..29c8133a --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.h
@@ -0,0 +1,50 @@ +// Copyright 2015 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 DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_ + +#include "base/bind.h" +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "dbus/file_descriptor.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.h" + +namespace bluez { + +// FakeBluetoothAdvertisementServiceProvider simulates the behavior of a local +// Bluetooth agent object and is used both in test cases in place of a +// mock and on the Linux desktop. +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothLEAdvertisementServiceProvider + : public BluetoothLEAdvertisementServiceProvider { + public: + FakeBluetoothLEAdvertisementServiceProvider( + const dbus::ObjectPath& object_path, + Delegate* delegate); + ~FakeBluetoothLEAdvertisementServiceProvider() override; + + // Each of these calls the equivalent + // BluetoothAdvertisementServiceProvider::Delegate method on the object passed + // on construction. + void Release(); + + const dbus::ObjectPath& object_path() { return object_path_; } + + private: + friend class FakeBluetoothLEAdvertisingManagerClient; + + // All incoming method calls are passed on to the Delegate and a callback + // passed to generate the reply. |delegate_| is generally the object that + // owns this one, and must outlive it. + Delegate* delegate_; + + DISALLOW_COPY_AND_ASSIGN(FakeBluetoothLEAdvertisementServiceProvider); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.cc b/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.cc new file mode 100644 index 0000000..2fcccd1 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.cc
@@ -0,0 +1,101 @@ +// Copyright 2015 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 "base/location.h" +#include "base/logging.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_proxy.h" +#include "device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.h" +#include "device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +const char FakeBluetoothLEAdvertisingManagerClient::kAdvertisingManagerPath[] = + "/fake/hci0"; + +FakeBluetoothLEAdvertisingManagerClient:: + FakeBluetoothLEAdvertisingManagerClient() {} + +FakeBluetoothLEAdvertisingManagerClient:: + ~FakeBluetoothLEAdvertisingManagerClient() {} + +void FakeBluetoothLEAdvertisingManagerClient::Init(dbus::Bus* bus) {} + +void FakeBluetoothLEAdvertisingManagerClient::AddObserver(Observer* observer) {} + +void FakeBluetoothLEAdvertisingManagerClient::RemoveObserver( + Observer* observer) {} + +void FakeBluetoothLEAdvertisingManagerClient::RegisterAdvertisement( + const dbus::ObjectPath& manager_object_path, + const dbus::ObjectPath& advertisement_object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "RegisterAdvertisment: " << advertisement_object_path.value(); + + if (manager_object_path != dbus::ObjectPath(kAdvertisingManagerPath)) { + error_callback.Run(kNoResponseError, "Invalid Advertising Manager path."); + return; + } + + ServiceProviderMap::iterator iter = + service_provider_map_.find(advertisement_object_path); + if (iter == service_provider_map_.end()) { + error_callback.Run(bluetooth_advertising_manager::kErrorInvalidArguments, + "Advertisement object not registered"); + } else if (!currently_registered_.value().empty()) { + error_callback.Run(bluetooth_advertising_manager::kErrorFailed, + "Maximum advertisements reached"); + } else { + currently_registered_ = advertisement_object_path; + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); + } +} + +void FakeBluetoothLEAdvertisingManagerClient::UnregisterAdvertisement( + const dbus::ObjectPath& manager_object_path, + const dbus::ObjectPath& advertisement_object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "UnregisterAdvertisment: " << advertisement_object_path.value(); + + if (manager_object_path != dbus::ObjectPath(kAdvertisingManagerPath)) { + error_callback.Run(kNoResponseError, "Invalid Advertising Manager path."); + return; + } + + ServiceProviderMap::iterator iter = + service_provider_map_.find(advertisement_object_path); + if (iter == service_provider_map_.end()) { + error_callback.Run(bluetooth_advertising_manager::kErrorDoesNotExist, + "Advertisement not registered"); + } else if (advertisement_object_path != currently_registered_) { + error_callback.Run(bluetooth_advertising_manager::kErrorDoesNotExist, + "Does not exist"); + } else { + currently_registered_ = dbus::ObjectPath(""); + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); + } +} + +void FakeBluetoothLEAdvertisingManagerClient:: + RegisterAdvertisementServiceProvider( + FakeBluetoothLEAdvertisementServiceProvider* service_provider) { + service_provider_map_[service_provider->object_path_] = service_provider; +} + +void FakeBluetoothLEAdvertisingManagerClient:: + UnregisterAdvertisementServiceProvider( + FakeBluetoothLEAdvertisementServiceProvider* service_provider) { + ServiceProviderMap::iterator iter = + service_provider_map_.find(service_provider->object_path_); + if (iter != service_provider_map_.end() && iter->second == service_provider) + service_provider_map_.erase(iter); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.h b/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.h new file mode 100644 index 0000000..ae0d914 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.h
@@ -0,0 +1,80 @@ +// Copyright 2015 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 DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_ + +#include <map> +#include <string> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/macros.h" +#include "base/observer_list.h" +#include "dbus/object_path.h" +#include "dbus/property.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h" + +namespace bluez { + +class FakeBluetoothLEAdvertisementServiceProvider; + +// FakeBluetoothAdvertisementManagerClient simulates the behavior of the +// Bluetooth +// Daemon's profile manager object and is used both in test cases in place of a +// mock and on the Linux desktop. +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothLEAdvertisingManagerClient + : public BluetoothLEAdvertisingManagerClient { + public: + FakeBluetoothLEAdvertisingManagerClient(); + ~FakeBluetoothLEAdvertisingManagerClient() override; + + // DBusClient overrides: + void Init(dbus::Bus* bus) override; + + // BluetoothAdvertisingManagerClient overrides: + void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; + void RegisterAdvertisement(const dbus::ObjectPath& manager_object_path, + const dbus::ObjectPath& advertisement_object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void UnregisterAdvertisement( + const dbus::ObjectPath& manager_object_path, + const dbus::ObjectPath& advertisement_object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + + // Register, unregister and retrieve pointers to profile server providers. + void RegisterAdvertisementServiceProvider( + FakeBluetoothLEAdvertisementServiceProvider* service_provider); + void UnregisterAdvertisementServiceProvider( + FakeBluetoothLEAdvertisementServiceProvider* service_provider); + FakeBluetoothLEAdvertisementServiceProvider* GetAdvertisementServiceProvider( + const std::string& uuid); + + // Advertising manager path that we simulate. + static const char kAdvertisingManagerPath[]; + + private: + // Map of a D-Bus object path to the FakeBluetoothAdvertisementServiceProvider + // registered for it; maintained by RegisterAdvertisementServiceProvider() and + // UnregisterProfileServiceProvicer() called by the constructor and + // destructor of FakeBluetoothAdvertisementServiceProvider. + typedef std::map<dbus::ObjectPath, + FakeBluetoothLEAdvertisementServiceProvider*> + ServiceProviderMap; + ServiceProviderMap service_provider_map_; + + // Holds the currently registered advertisement. If there is no advertisement + // registered, this path is empty. + dbus::ObjectPath currently_registered_; + + DISALLOW_COPY_AND_ASSIGN(FakeBluetoothLEAdvertisingManagerClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_media_client.cc b/device/bluetooth/dbus/fake_bluetooth_media_client.cc new file mode 100644 index 0000000..246a140 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_media_client.cc
@@ -0,0 +1,134 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/fake_bluetooth_media_client.h" + +#include <string> + +#include "base/stl_util.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h" +#include "device/bluetooth/dbus/fake_bluetooth_media_transport_client.h" + +using dbus::ObjectPath; + +namespace { + +// Except for |kFailedError|, the other error is defined in BlueZ D-Bus Media +// API. +const char kFailedError[] = "org.chromium.Error.Failed"; +const char kInvalidArgumentsError[] = "org.chromium.Error.InvalidArguments"; + +} // namespace + +namespace bluez { + +// static +const uint8_t FakeBluetoothMediaClient::kDefaultCodec = 0x00; + +FakeBluetoothMediaClient::FakeBluetoothMediaClient() + : visible_(true), + object_path_(ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)) {} + +FakeBluetoothMediaClient::~FakeBluetoothMediaClient() {} + +void FakeBluetoothMediaClient::Init(dbus::Bus* bus) {} + +void FakeBluetoothMediaClient::AddObserver( + BluetoothMediaClient::Observer* observer) { + DCHECK(observer); + observers_.AddObserver(observer); +} + +void FakeBluetoothMediaClient::RemoveObserver( + BluetoothMediaClient::Observer* observer) { + DCHECK(observer); + observers_.RemoveObserver(observer); +} + +void FakeBluetoothMediaClient::RegisterEndpoint( + const ObjectPath& object_path, + const ObjectPath& endpoint_path, + const EndpointProperties& properties, + const base::Closure& callback, + const ErrorCallback& error_callback) { + if (!visible_) + return; + + VLOG(1) << "RegisterEndpoint: " << endpoint_path.value(); + + // The media client and adapter client should have the same object path. + if (object_path != object_path_ || + properties.uuid != BluetoothMediaClient::kBluetoothAudioSinkUUID || + properties.codec != kDefaultCodec || properties.capabilities.empty()) { + error_callback.Run(kInvalidArgumentsError, ""); + return; + } + + callback.Run(); +} + +void FakeBluetoothMediaClient::UnregisterEndpoint( + const ObjectPath& object_path, + const ObjectPath& endpoint_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + // TODO(mcchou): Come up with some corresponding actions. + VLOG(1) << "UnregisterEndpoint: " << endpoint_path.value(); + + if (!ContainsKey(endpoints_, endpoint_path)) { + error_callback.Run(kFailedError, "Unknown media endpoint"); + return; + } + + SetEndpointRegistered(endpoints_[endpoint_path], false); + callback.Run(); +} + +void FakeBluetoothMediaClient::SetVisible(bool visible) { + visible_ = visible; + + if (visible_) + return; + + // If the media object becomes invisible, an update chain will unregister all + // endpoints and set the associated transport objects to be invalid. + // SetEndpointRegistered will remove the endpoint entry from |endpoints_|. + while (endpoints_.begin() != endpoints_.end()) + SetEndpointRegistered(endpoints_.begin()->second, false); + + // Notifies observers about the change on |visible_|. + FOR_EACH_OBSERVER(BluetoothMediaClient::Observer, observers_, + MediaRemoved(object_path_)); +} + +void FakeBluetoothMediaClient::SetEndpointRegistered( + FakeBluetoothMediaEndpointServiceProvider* endpoint, + bool registered) { + if (registered) { + endpoints_[endpoint->object_path()] = endpoint; + return; + } + + if (!IsRegistered(endpoint->object_path())) + return; + + // Once a media endpoint object becomes invalid, invalidate the associated + // transport. + FakeBluetoothMediaTransportClient* transport = + static_cast<FakeBluetoothMediaTransportClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient()); + transport->SetValid(endpoint, false); + + endpoints_.erase(endpoint->object_path()); + endpoint->Released(); +} + +bool FakeBluetoothMediaClient::IsRegistered( + const dbus::ObjectPath& endpoint_path) { + return ContainsKey(endpoints_, endpoint_path); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_media_client.h b/device/bluetooth/dbus/fake_bluetooth_media_client.h new file mode 100644 index 0000000..2049f43 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_media_client.h
@@ -0,0 +1,78 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_MEDIA_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_MEDIA_CLIENT_H_ + +#include <map> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/observer_list.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_media_client.h" + +namespace bluez { + +class FakeBluetoothMediaEndpointServiceProvider; + +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothMediaClient + : public BluetoothMediaClient { + public: + // The default codec is SBC(0x00). + static const uint8_t kDefaultCodec; + + FakeBluetoothMediaClient(); + ~FakeBluetoothMediaClient() override; + + // DBusClient override. + void Init(dbus::Bus* bus) override; + + // BluetoothMediaClient overrides. + void AddObserver(BluetoothMediaClient::Observer* observer) override; + void RemoveObserver(BluetoothMediaClient::Observer* observer) override; + void RegisterEndpoint(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& endpoint_path, + const EndpointProperties& properties, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void UnregisterEndpoint(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& endpoint_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + + // Makes the media object visible/invisible to emulate the addition/removal + // events. + void SetVisible(bool visible); + + // Sets the registration state for a given media endpoint. + void SetEndpointRegistered( + FakeBluetoothMediaEndpointServiceProvider* endpoint, + bool registered); + + // Indicates whether the given endpoint path is registered or not. + bool IsRegistered(const dbus::ObjectPath& endpoint_path); + + private: + // Indicates whether the media object is visible or not. + bool visible_; + + // The path of the media object. + dbus::ObjectPath object_path_; + + // Map of registered endpoints. Each pair is composed of an endpoint path as + // key and a pointer to the endpoint as value. + std::map<dbus::ObjectPath, FakeBluetoothMediaEndpointServiceProvider*> + endpoints_; + + // List of observers interested in event notifications from us. + base::ObserverList<BluetoothMediaClient::Observer> observers_; + + DISALLOW_COPY_AND_ASSIGN(FakeBluetoothMediaClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_MEDIA_CLIENT_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.cc b/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.cc new file mode 100644 index 0000000..83a0822e --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.cc
@@ -0,0 +1,65 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h" + +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_media_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_media_transport_client.h" + +using dbus::ObjectPath; + +namespace bluez { + +FakeBluetoothMediaEndpointServiceProvider:: + FakeBluetoothMediaEndpointServiceProvider(const ObjectPath& object_path, + Delegate* delegate) + : visible_(false), object_path_(object_path), delegate_(delegate) { + VLOG(1) << "Create Bluetooth Media Endpoint: " << object_path_.value(); +} + +FakeBluetoothMediaEndpointServiceProvider:: + ~FakeBluetoothMediaEndpointServiceProvider() { + VLOG(1) << "Cleaning up Bluetooth Media Endpoint: " << object_path_.value(); +} + +void FakeBluetoothMediaEndpointServiceProvider::SetConfiguration( + const ObjectPath& transport_path, + const Delegate::TransportProperties& properties) { + VLOG(1) << object_path_.value() << ": SetConfiguration for " + << transport_path.value(); + + delegate_->SetConfiguration(transport_path, properties); +} + +void FakeBluetoothMediaEndpointServiceProvider::SelectConfiguration( + const std::vector<uint8_t>& capabilities, + const Delegate::SelectConfigurationCallback& callback) { + VLOG(1) << object_path_.value() << ": SelectConfiguration"; + + delegate_->SelectConfiguration(capabilities, callback); + + // Makes the transport object valid for the given endpoint path. + FakeBluetoothMediaTransportClient* transport = + static_cast<FakeBluetoothMediaTransportClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient()); + DCHECK(transport); + transport->SetValid(this, true); +} + +void FakeBluetoothMediaEndpointServiceProvider::ClearConfiguration( + const ObjectPath& transport_path) { + VLOG(1) << object_path_.value() << ": ClearConfiguration on " + << transport_path.value(); + + delegate_->ClearConfiguration(transport_path); +} + +void FakeBluetoothMediaEndpointServiceProvider::Released() { + VLOG(1) << object_path_.value() << ": Released"; + + delegate_->Released(); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h b/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h new file mode 100644 index 0000000..2e6b18a --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h
@@ -0,0 +1,58 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_ + +#include <vector> + +#include "base/logging.h" +#include "base/macros.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.h" +#include "testing/gtest/include/gtest/gtest_prod.h" + +namespace bluez { + +// FakeBluetoothMediaEndpointServiceProvider simulates the behavior of a local +// Bluetooth Media Endpoint object. +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothMediaEndpointServiceProvider + : public BluetoothMediaEndpointServiceProvider { + public: + FakeBluetoothMediaEndpointServiceProvider(const dbus::ObjectPath& object_path, + Delegate* delegate); + ~FakeBluetoothMediaEndpointServiceProvider() override; + + // Each of these calls the equivalent BluetoothMediaEnpointServiceProvider:: + // Delegate method on the object passed on construction. + void SetConfiguration(const dbus::ObjectPath& transport_path, + const Delegate::TransportProperties& properties); + void SelectConfiguration( + const std::vector<uint8_t>& capabilities, + const Delegate::SelectConfigurationCallback& callback); + void ClearConfiguration(const dbus::ObjectPath& transport_path); + void Released(); + + // Gets the path of the media endpoint object. + const dbus::ObjectPath& object_path() const { return object_path_; } + + private: + // Indicates whether the endpoint object is visible or not. + bool visible_; + + // The path of the media endpoint object. + dbus::ObjectPath object_path_; + + // All incoming method calls are passed to |delegate_|. |callback| passed to + // |delegate_| will generate the response for those methods which have + // non-void return. + Delegate* delegate_; + + DISALLOW_COPY_AND_ASSIGN(FakeBluetoothMediaEndpointServiceProvider); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_media_transport_client.cc b/device/bluetooth/dbus/fake_bluetooth_media_transport_client.cc new file mode 100644 index 0000000..1a0a106 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_media_transport_client.cc
@@ -0,0 +1,328 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/dbus/fake_bluetooth_media_transport_client.h" + +#include <unistd.h> +#include <sys/socket.h> + +#include <sstream> + +#include "base/bind.h" +#include "base/stl_util.h" +#include "dbus/file_descriptor.h" +#include "device/bluetooth/dbus/bluetooth_media_client.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_media_client.h" +#include "device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h" + +using dbus::ObjectPath; + +namespace { + +// TODO(mcchou): Remove this constants once it is in cros_system_api. +const char kBluetoothMediaTransportInterface[] = "org.bluez.MediaTransport1"; +const char kNotImplemented[] = "org.bluez.NotImplemented"; +const char kNotAuthorized[] = "org.bluez.NotAuthorized"; +const char kFailed[] = "org.bluez.Failed"; +const char kNotAvailable[] = "org.bluez.NotAvailable"; + +const int kInvalidFd = -1; + +ObjectPath GenerateTransportPath() { + static unsigned int sequence_number = 0; + ++sequence_number; + std::stringstream path; + path << bluez::FakeBluetoothAdapterClient::kAdapterPath + << bluez::FakeBluetoothMediaTransportClient::kTransportDevicePath + << "/fd" << sequence_number; + return ObjectPath(path.str()); +} + +#define UINT8_VECTOR_FROM_ARRAY(array) \ + std::vector<uint8_t>(array, array + arraysize(array)) + +} // namespace + +namespace bluez { + +// static +const char FakeBluetoothMediaTransportClient::kTransportDevicePath[] = + "/fake_audio_source"; +const uint8_t FakeBluetoothMediaTransportClient::kTransportCodec = 0x00; +const uint8_t FakeBluetoothMediaTransportClient::kTransportConfiguration[] = { + 0x21, 0x15, 0x33, 0x2C}; +const uint8_t FakeBluetoothMediaTransportClient::kTransportConfigurationLength = + arraysize(FakeBluetoothMediaTransportClient::kTransportConfiguration); +const uint16_t FakeBluetoothMediaTransportClient::kTransportDelay = 5; +const uint16_t FakeBluetoothMediaTransportClient::kTransportVolume = 50; +const uint16_t FakeBluetoothMediaTransportClient::kDefaultReadMtu = 20; +const uint16_t FakeBluetoothMediaTransportClient::kDefaultWriteMtu = 25; + +FakeBluetoothMediaTransportClient::Properties::Properties( + const PropertyChangedCallback& callback) + : BluetoothMediaTransportClient::Properties( + nullptr, + kBluetoothMediaTransportInterface, + callback) {} + +FakeBluetoothMediaTransportClient::Properties::~Properties() {} + +void FakeBluetoothMediaTransportClient::Properties::Get( + dbus::PropertyBase* property, + dbus::PropertySet::GetCallback callback) { + VLOG(1) << "Get " << property->name(); + callback.Run(false); +} + +void FakeBluetoothMediaTransportClient::Properties::GetAll() { + VLOG(1) << "GetAll called."; +} + +void FakeBluetoothMediaTransportClient::Properties::Set( + dbus::PropertyBase* property, + dbus::PropertySet::SetCallback callback) { + VLOG(1) << "Set " << property->name(); + callback.Run(false); +} + +FakeBluetoothMediaTransportClient::Transport::Transport( + const ObjectPath& transport_path, + Properties* transport_properties) + : path(transport_path) { + properties.reset(transport_properties); +} + +FakeBluetoothMediaTransportClient::Transport::~Transport() {} + +FakeBluetoothMediaTransportClient::FakeBluetoothMediaTransportClient() {} + +FakeBluetoothMediaTransportClient::~FakeBluetoothMediaTransportClient() { + STLDeleteValues(&endpoint_to_transport_map_); +} + +// DBusClient override. +void FakeBluetoothMediaTransportClient::Init(dbus::Bus* bus) {} + +void FakeBluetoothMediaTransportClient::AddObserver( + BluetoothMediaTransportClient::Observer* observer) { + observers_.AddObserver(observer); +} + +void FakeBluetoothMediaTransportClient::RemoveObserver( + BluetoothMediaTransportClient::Observer* observer) { + observers_.RemoveObserver(observer); +} + +FakeBluetoothMediaTransportClient::Properties* +FakeBluetoothMediaTransportClient::GetProperties( + const ObjectPath& object_path) { + const ObjectPath& endpoint_path = GetEndpointPath(object_path); + Transport* transport = GetTransport(endpoint_path); + if (!transport) + return nullptr; + return transport->properties.get(); +} + +void FakeBluetoothMediaTransportClient::Acquire( + const ObjectPath& object_path, + const AcquireCallback& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "Acquire - transport path: " << object_path.value(); + AcquireInternal(false, object_path, callback, error_callback); +} + +void FakeBluetoothMediaTransportClient::TryAcquire( + const ObjectPath& object_path, + const AcquireCallback& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "TryAcquire - transport path: " << object_path.value(); + AcquireInternal(true, object_path, callback, error_callback); +} + +void FakeBluetoothMediaTransportClient::Release( + const ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + error_callback.Run(kNotImplemented, ""); +} + +void FakeBluetoothMediaTransportClient::SetValid( + FakeBluetoothMediaEndpointServiceProvider* endpoint, + bool valid) { + FakeBluetoothMediaClient* media = static_cast<FakeBluetoothMediaClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothMediaClient()); + DCHECK(media); + + ObjectPath endpoint_path(endpoint->object_path()); + if (!media->IsRegistered(endpoint_path)) + return; + + if (valid) { + ObjectPath transport_path = GenerateTransportPath(); + VLOG(1) << "New transport, " << transport_path.value() + << " is created for endpoint " << endpoint_path.value(); + + // Sets the fake property set with default values. + scoped_ptr<Properties> properties(new Properties( + base::Bind(&FakeBluetoothMediaTransportClient::OnPropertyChanged, + base::Unretained(this)))); + properties->device.ReplaceValue(ObjectPath(kTransportDevicePath)); + properties->uuid.ReplaceValue( + BluetoothMediaClient::kBluetoothAudioSinkUUID); + properties->codec.ReplaceValue(kTransportCodec); + properties->configuration.ReplaceValue( + UINT8_VECTOR_FROM_ARRAY(kTransportConfiguration)); + properties->state.ReplaceValue(BluetoothMediaTransportClient::kStateIdle); + properties->delay.ReplaceValue(kTransportDelay); + properties->volume.ReplaceValue(kTransportVolume); + + endpoint_to_transport_map_[endpoint_path] = + new Transport(transport_path, properties.release()); + transport_to_endpoint_map_[transport_path] = endpoint_path; + return; + } + + Transport* transport = GetTransport(endpoint_path); + if (!transport) + return; + ObjectPath transport_path = transport->path; + + // Notifies observers about the state change of the transport. + FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, + MediaTransportRemoved(transport_path)); + + endpoint->ClearConfiguration(transport_path); + delete transport; + endpoint_to_transport_map_.erase(endpoint_path); + transport_to_endpoint_map_.erase(transport_path); +} + +void FakeBluetoothMediaTransportClient::SetState( + const ObjectPath& endpoint_path, + const std::string& state) { + VLOG(1) << "SetState - state: " << state; + + Transport* transport = GetTransport(endpoint_path); + if (!transport) + return; + + transport->properties->state.ReplaceValue(state); + FOR_EACH_OBSERVER( + BluetoothMediaTransportClient::Observer, observers_, + MediaTransportPropertyChanged( + transport->path, BluetoothMediaTransportClient::kStateProperty)); +} + +void FakeBluetoothMediaTransportClient::SetVolume( + const ObjectPath& endpoint_path, + const uint16_t& volume) { + Transport* transport = GetTransport(endpoint_path); + if (!transport) + return; + + transport->properties->volume.ReplaceValue(volume); + FOR_EACH_OBSERVER( + BluetoothMediaTransportClient::Observer, observers_, + MediaTransportPropertyChanged( + transport->path, BluetoothMediaTransportClient::kVolumeProperty)); +} + +void FakeBluetoothMediaTransportClient::WriteData( + const ObjectPath& endpoint_path, + const std::vector<char>& bytes) { + VLOG(1) << "WriteData - write " << bytes.size() << " bytes"; + + Transport* transport = GetTransport(endpoint_path); + + if (!transport || transport->properties->state.value() != "active") { + VLOG(1) << "WriteData - write operation rejected, since the state isn't " + "active for endpoint: " + << endpoint_path.value(); + return; + } + + if (!transport->input_fd.get()) { + VLOG(1) << "WriteData - invalid input file descriptor"; + return; + } + + ssize_t written_len = + write(transport->input_fd->GetPlatformFile(), bytes.data(), bytes.size()); + if (written_len < 0) { + VLOG(1) << "WriteData - failed to write to the socket"; + return; + } + + VLOG(1) << "WriteData - wrote " << written_len << " bytes to the socket"; +} + +ObjectPath FakeBluetoothMediaTransportClient::GetTransportPath( + const ObjectPath& endpoint_path) { + Transport* transport = GetTransport(endpoint_path); + return transport ? transport->path : ObjectPath(""); +} + +void FakeBluetoothMediaTransportClient::OnPropertyChanged( + const std::string& property_name) { + VLOG(1) << "Property " << property_name << " changed"; +} + +ObjectPath FakeBluetoothMediaTransportClient::GetEndpointPath( + const ObjectPath& transport_path) { + const auto& it = transport_to_endpoint_map_.find(transport_path); + return it != transport_to_endpoint_map_.end() ? it->second : ObjectPath(""); +} + +FakeBluetoothMediaTransportClient::Transport* +FakeBluetoothMediaTransportClient::GetTransport( + const ObjectPath& endpoint_path) { + const auto& it = endpoint_to_transport_map_.find(endpoint_path); + return (it != endpoint_to_transport_map_.end()) ? it->second : nullptr; +} + +FakeBluetoothMediaTransportClient::Transport* +FakeBluetoothMediaTransportClient::GetTransportByPath( + const dbus::ObjectPath& transport_path) { + return GetTransport(GetEndpointPath(transport_path)); +} + +void FakeBluetoothMediaTransportClient::AcquireInternal( + bool try_flag, + const ObjectPath& object_path, + const AcquireCallback& callback, + const ErrorCallback& error_callback) { + const ObjectPath& endpoint_path = GetEndpointPath(object_path); + Transport* transport = GetTransport(endpoint_path); + if (!transport) { + error_callback.Run(kFailed, ""); + return; + } + + std::string state = transport->properties->state.value(); + if (state == "active") { + error_callback.Run(kNotAuthorized, ""); + return; + } + if (state != "pending") { + error_callback.Run(try_flag ? kNotAvailable : kFailed, ""); + return; + } + + int fds[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { + transport->input_fd.reset(); + error_callback.Run(kFailed, ""); + return; + } + DCHECK((fds[0] > kInvalidFd) && (fds[1] > kInvalidFd)); + transport->input_fd.reset(new base::File(fds[0])); + + dbus::FileDescriptor out_fd(fds[1]); + callback.Run(&out_fd, kDefaultReadMtu, kDefaultWriteMtu); + SetState(endpoint_path, "active"); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_media_transport_client.h b/device/bluetooth/dbus/fake_bluetooth_media_transport_client.h new file mode 100644 index 0000000..8ad3bb9 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_media_transport_client.h
@@ -0,0 +1,149 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_ + +#include <map> +#include <string> +#include <vector> + +#include "base/files/file.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/observer_list.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_media_transport_client.h" + +namespace bluez { + +class FakeBluetoothMediaEndpointServiceProvider; + +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothMediaTransportClient + : public BluetoothMediaTransportClient { + public: + struct Properties : public BluetoothMediaTransportClient::Properties { + explicit Properties(const PropertyChangedCallback& callback); + ~Properties() override; + + void Get(dbus::PropertyBase* property, + dbus::PropertySet::GetCallback callback) override; + void GetAll() override; + void Set(dbus::PropertyBase* property, + dbus::PropertySet::SetCallback callback) override; + }; + + // The default path of the transport object. + static const char kTransportPath[]; + + // The default properties including device, codec, configuration, state, delay + // and volume, owned by a fake media transport object we emulate. + static const char kTransportDevicePath[]; + static const uint8_t kTransportCodec; + static const uint8_t kTransportConfiguration[]; + static const uint8_t kTransportConfigurationLength; + static const uint16_t kTransportDelay; + static const uint16_t kTransportVolume; + + // The default MTUs for read and write. + static const uint16_t kDefaultReadMtu; + static const uint16_t kDefaultWriteMtu; + + FakeBluetoothMediaTransportClient(); + ~FakeBluetoothMediaTransportClient() override; + + // DBusClient override. + void Init(dbus::Bus* bus) override; + + // BluetoothMediaTransportClient override. + void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; + Properties* GetProperties(const dbus::ObjectPath& object_path) override; + void Acquire(const dbus::ObjectPath& object_path, + const AcquireCallback& callback, + const ErrorCallback& error_callback) override; + void TryAcquire(const dbus::ObjectPath& object_path, + const AcquireCallback& callback, + const ErrorCallback& error_callback) override; + void Release(const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + + // Makes the transport valid/invalid for a given media endpoint. The transport + // object is assigned to the given endpoint if valid is true, false + // otherwise. + void SetValid(FakeBluetoothMediaEndpointServiceProvider* endpoint, + bool valid); + + // Set state/volume property to a certain value. + void SetState(const dbus::ObjectPath& endpoint_path, + const std::string& state); + void SetVolume(const dbus::ObjectPath& endpoint_path, const uint16_t& volume); + + // Writes bytes to the input file descriptor, |input_fd|, associated with a + // transport object which is bound to |endpoint_path|. + void WriteData(const dbus::ObjectPath& endpoint_path, + const std::vector<char>& bytes); + + // Retrieves the transport object path bound to |endpoint_path|. + dbus::ObjectPath GetTransportPath(const dbus::ObjectPath& endpoint_path); + + private: + // This class is used for simulating the scenario where each media endpoint + // has a corresponding transport path and properties. Once an endpoint is + // assigned with a transport path, an object of Transport is created. + struct Transport { + Transport(const dbus::ObjectPath& transport_path, + Properties* transport_properties); + ~Transport(); + + // An unique transport path. + dbus::ObjectPath path; + + // The property set bound with |path|. + scoped_ptr<Properties> properties; + + // This is the internal end of socketpair created for simulation purposes. + // |input_fd| will be initialized when Acquire/TryAcquire is called. + scoped_ptr<base::File> input_fd; + }; + + // Property callback passed while a Properties structure is created. + void OnPropertyChanged(const std::string& property_name); + + // Gets the endpoint path associated with the given transport_path. + dbus::ObjectPath GetEndpointPath(const dbus::ObjectPath& transport_path); + + // Retrieves the transport structure bound to |endpoint_path|. + Transport* GetTransport(const dbus::ObjectPath& endpoint_path); + + // Retrieves the transport structure with |transport_path|. + Transport* GetTransportByPath(const dbus::ObjectPath& transport_path); + + // Helper function used by Acquire and TryAcquire to set up the sockpair and + // invoke callback/error_callback. + void AcquireInternal(bool try_flag, + const dbus::ObjectPath& object_path, + const AcquireCallback& callback, + const ErrorCallback& error_callback); + + // Map of endpoints with valid transport. Each pair is composed of an endpoint + // path and a Transport structure containing a transport path and its + // properties. + std::map<dbus::ObjectPath, Transport*> endpoint_to_transport_map_; + + // Map of valid transports. Each pair is composed of a transport path as the + // key and an endpoint path as the value. This map is used to get the + // corresponding endpoint path when GetProperties() is called. + std::map<dbus::ObjectPath, dbus::ObjectPath> transport_to_endpoint_map_; + + base::ObserverList<BluetoothMediaTransportClient::Observer> observers_; + + DISALLOW_COPY_AND_ASSIGN(FakeBluetoothMediaTransportClient); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.cc b/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.cc new file mode 100644 index 0000000..96254a5 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.cc
@@ -0,0 +1,111 @@ +// Copyright (c) 2013 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 "device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h" + +#include "base/location.h" +#include "base/logging.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_proxy.h" +#include "device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace bluez { + +const char FakeBluetoothProfileManagerClient::kL2capUuid[] = + "4d995052-33cc-4fdf-b446-75f32942a076"; +const char FakeBluetoothProfileManagerClient::kRfcommUuid[] = + "3f6d6dbf-a6ad-45fc-9653-47dc912ef70e"; +const char FakeBluetoothProfileManagerClient::kUnregisterableUuid[] = + "00000000-0000-0000-0000-000000000000"; + +FakeBluetoothProfileManagerClient::FakeBluetoothProfileManagerClient() {} + +FakeBluetoothProfileManagerClient::~FakeBluetoothProfileManagerClient() {} + +void FakeBluetoothProfileManagerClient::Init(dbus::Bus* bus) {} + +void FakeBluetoothProfileManagerClient::RegisterProfile( + const dbus::ObjectPath& profile_path, + const std::string& uuid, + const Options& options, + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "RegisterProfile: " << profile_path.value() << ": " << uuid; + + if (uuid == kUnregisterableUuid) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(error_callback, + bluetooth_profile_manager::kErrorInvalidArguments, + "Can't register this UUID")); + return; + } + + // TODO(jamuraa): check options for channel & psm + + ServiceProviderMap::iterator iter = service_provider_map_.find(profile_path); + if (iter == service_provider_map_.end()) { + error_callback.Run(bluetooth_profile_manager::kErrorInvalidArguments, + "No profile created"); + } else { + ProfileMap::iterator piter = profile_map_.find(uuid); + if (piter != profile_map_.end()) { + error_callback.Run(bluetooth_profile_manager::kErrorAlreadyExists, + "Profile already registered"); + } else { + profile_map_[uuid] = profile_path; + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); + } + } +} + +void FakeBluetoothProfileManagerClient::UnregisterProfile( + const dbus::ObjectPath& profile_path, + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "UnregisterProfile: " << profile_path.value(); + + ServiceProviderMap::iterator iter = service_provider_map_.find(profile_path); + if (iter == service_provider_map_.end()) { + error_callback.Run(bluetooth_profile_manager::kErrorInvalidArguments, + "Profile not registered"); + } else { + for (ProfileMap::iterator piter = profile_map_.begin(); + piter != profile_map_.end(); ++piter) { + if (piter->second == profile_path) { + profile_map_.erase(piter); + break; + } + } + + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); + } +} + +void FakeBluetoothProfileManagerClient::RegisterProfileServiceProvider( + FakeBluetoothProfileServiceProvider* service_provider) { + service_provider_map_[service_provider->object_path_] = service_provider; +} + +void FakeBluetoothProfileManagerClient::UnregisterProfileServiceProvider( + FakeBluetoothProfileServiceProvider* service_provider) { + ServiceProviderMap::iterator iter = + service_provider_map_.find(service_provider->object_path_); + if (iter != service_provider_map_.end() && iter->second == service_provider) + service_provider_map_.erase(iter); +} + +FakeBluetoothProfileServiceProvider* +FakeBluetoothProfileManagerClient::GetProfileServiceProvider( + const std::string& uuid) { + ProfileMap::iterator iter = profile_map_.find(uuid); + if (iter == profile_map_.end()) + return nullptr; + return service_provider_map_[iter->second]; +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h b/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h new file mode 100644 index 0000000..8ed7826d --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h
@@ -0,0 +1,74 @@ +// Copyright (c) 2013 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 DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_ + +#include <map> +#include <string> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/observer_list.h" +#include "dbus/object_path.h" +#include "dbus/property.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h" + +namespace bluez { + +class FakeBluetoothProfileServiceProvider; + +// FakeBluetoothProfileManagerClient simulates the behavior of the Bluetooth +// Daemon's profile manager object and is used both in test cases in place of a +// mock and on the Linux desktop. +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothProfileManagerClient + : public BluetoothProfileManagerClient { + public: + FakeBluetoothProfileManagerClient(); + ~FakeBluetoothProfileManagerClient() override; + + // BluetoothProfileManagerClient overrides + void Init(dbus::Bus* bus) override; + void RegisterProfile(const dbus::ObjectPath& profile_path, + const std::string& uuid, + const Options& options, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void UnregisterProfile(const dbus::ObjectPath& profile_path, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + + // Register, unregister and retrieve pointers to profile server providers. + void RegisterProfileServiceProvider( + FakeBluetoothProfileServiceProvider* service_provider); + void UnregisterProfileServiceProvider( + FakeBluetoothProfileServiceProvider* service_provider); + FakeBluetoothProfileServiceProvider* GetProfileServiceProvider( + const std::string& uuid); + + // UUIDs recognised for testing. + static const char kL2capUuid[]; + static const char kRfcommUuid[]; + static const char kUnregisterableUuid[]; + + private: + // Map of a D-Bus object path to the FakeBluetoothProfileServiceProvider + // registered for it; maintained by RegisterProfileServiceProvider() and + // UnregisterProfileServiceProvicer() called by the constructor and + // destructor of FakeBluetoothProfileServiceProvider. + typedef std::map<dbus::ObjectPath, FakeBluetoothProfileServiceProvider*> + ServiceProviderMap; + ServiceProviderMap service_provider_map_; + + // Map of Profile UUID to the D-Bus object path of the service provider + // in |service_provider_map_|. Maintained by RegisterProfile() and + // UnregisterProfile() in response to BluetoothProfile methods. + typedef std::map<std::string, dbus::ObjectPath> ProfileMap; + ProfileMap profile_map_; +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_
diff --git a/device/bluetooth/dbus/fake_bluetooth_profile_service_provider.cc b/device/bluetooth/dbus/fake_bluetooth_profile_service_provider.cc new file mode 100644 index 0000000..1089501 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_profile_service_provider.cc
@@ -0,0 +1,61 @@ +// Copyright (c) 2013 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 "device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h" + +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h" + +namespace bluez { + +FakeBluetoothProfileServiceProvider::FakeBluetoothProfileServiceProvider( + const dbus::ObjectPath& object_path, + Delegate* delegate) + : object_path_(object_path), delegate_(delegate) { + VLOG(1) << "Creating Bluetooth Profile: " << object_path_.value(); + + FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = + static_cast<FakeBluetoothProfileManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothProfileManagerClient()); + fake_bluetooth_profile_manager_client->RegisterProfileServiceProvider(this); +} + +FakeBluetoothProfileServiceProvider::~FakeBluetoothProfileServiceProvider() { + VLOG(1) << "Cleaning up Bluetooth Profile: " << object_path_.value(); + + FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = + static_cast<FakeBluetoothProfileManagerClient*>( + bluez::BluezDBusManager::Get()->GetBluetoothProfileManagerClient()); + fake_bluetooth_profile_manager_client->UnregisterProfileServiceProvider(this); +} + +void FakeBluetoothProfileServiceProvider::Released() { + VLOG(1) << object_path_.value() << ": Released"; + delegate_->Released(); +} + +void FakeBluetoothProfileServiceProvider::NewConnection( + const dbus::ObjectPath& device_path, + scoped_ptr<dbus::FileDescriptor> fd, + const Delegate::Options& options, + const Delegate::ConfirmationCallback& callback) { + VLOG(1) << object_path_.value() << ": NewConnection for " + << device_path.value(); + delegate_->NewConnection(device_path, fd.Pass(), options, callback); +} + +void FakeBluetoothProfileServiceProvider::RequestDisconnection( + const dbus::ObjectPath& device_path, + const Delegate::ConfirmationCallback& callback) { + VLOG(1) << object_path_.value() << ": RequestDisconnection for " + << device_path.value(); + delegate_->RequestDisconnection(device_path, callback); +} + +void FakeBluetoothProfileServiceProvider::Cancel() { + VLOG(1) << object_path_.value() << ": Cancel"; + delegate_->Cancel(); +} + +} // namespace bluez
diff --git a/device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h b/device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h new file mode 100644 index 0000000..5d7af8d17 --- /dev/null +++ b/device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h
@@ -0,0 +1,61 @@ +// Copyright (c) 2013 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 DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_ +#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_ + +#include "base/bind.h" +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "dbus/file_descriptor.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h" + +namespace bluez { + +// FakeBluetoothProfileServiceProvider simulates the behavior of a local +// Bluetooth agent object and is used both in test cases in place of a +// mock and on the Linux desktop. +// +// This class is only called from the dbus origin thread and is not thread-safe. +class DEVICE_BLUETOOTH_EXPORT FakeBluetoothProfileServiceProvider + : public BluetoothProfileServiceProvider { + public: + FakeBluetoothProfileServiceProvider(const dbus::ObjectPath& object_path, + Delegate* delegate); + ~FakeBluetoothProfileServiceProvider() override; + + // Each of these calls the equivalent + // BluetoothProfileServiceProvider::Delegate method on the object passed on + // construction. + void Released(); + void NewConnection(const dbus::ObjectPath& device_path, + scoped_ptr<dbus::FileDescriptor> fd, + const Delegate::Options& options, + const Delegate::ConfirmationCallback& callback); + void RequestDisconnection(const dbus::ObjectPath& device_path, + const Delegate::ConfirmationCallback& callback); + void Cancel(); + + const dbus::ObjectPath& object_path() const { return object_path_; } + + private: + friend class FakeBluetoothProfileManagerClient; + + // D-Bus object path we are faking. + dbus::ObjectPath object_path_; + + // All incoming method calls are passed on to the Delegate and a callback + // passed to generate the reply. |delegate_| is generally the object that + // owns this one, and must outlive it. + Delegate* delegate_; + + DISALLOW_COPY_AND_ASSIGN(FakeBluetoothProfileServiceProvider); +}; + +} // namespace bluez + +#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_
diff --git a/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java b/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java index 443da83..a38f749 100644 --- a/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java +++ b/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java
@@ -189,7 +189,7 @@ final FakeBluetoothAdapter mAdapter; private String mAddress; private String mName; - private final FakeBluetoothGatt mGatt; + final FakeBluetoothGatt mGatt; private Wrappers.BluetoothGattCallbackWrapper mGattCallback; public FakeBluetoothDevice(FakeBluetoothAdapter adapter, String address, String name) { @@ -225,8 +225,8 @@ Integer previousId = uuidsToInstanceIdMap.get(uuid); int instanceId = (previousId == null) ? 0 : previousId + 1; uuidsToInstanceIdMap.put(uuid, instanceId); - fakeDevice.mGatt.mServices.add( - new FakeBluetoothGattService(UUID.fromString(uuid), instanceId)); + fakeDevice.mGatt.mServices.add(new FakeBluetoothGattService( + fakeDevice, UUID.fromString(uuid), instanceId)); } } @@ -271,14 +271,16 @@ } /** - * Fakes android.bluetooth.BluetoothDevice. + * Fakes android.bluetooth.BluetoothGatt. */ static class FakeBluetoothGatt extends Wrappers.BluetoothGattWrapper { final FakeBluetoothDevice mDevice; final ArrayList<Wrappers.BluetoothGattServiceWrapper> mServices; + boolean mReadCharacteristicWillFailSynchronouslyOnce = false; + boolean mWriteCharacteristicWillFailSynchronouslyOnce = false; public FakeBluetoothGatt(FakeBluetoothDevice device) { - super(null); + super(null, null); mDevice = device; mServices = new ArrayList<Wrappers.BluetoothGattServiceWrapper>(); } @@ -297,18 +299,42 @@ public List<Wrappers.BluetoothGattServiceWrapper> getServices() { return mServices; } + + @Override + boolean readCharacteristic(Wrappers.BluetoothGattCharacteristicWrapper characteristic) { + if (mReadCharacteristicWillFailSynchronouslyOnce) { + mReadCharacteristicWillFailSynchronouslyOnce = false; + return false; + } + nativeOnFakeBluetoothGattReadCharacteristic( + mDevice.mAdapter.mNativeBluetoothTestAndroid); + return true; + } + + @Override + boolean writeCharacteristic(Wrappers.BluetoothGattCharacteristicWrapper characteristic) { + if (mWriteCharacteristicWillFailSynchronouslyOnce) { + mWriteCharacteristicWillFailSynchronouslyOnce = false; + return false; + } + nativeOnFakeBluetoothGattWriteCharacteristic( + mDevice.mAdapter.mNativeBluetoothTestAndroid, characteristic.getValue()); + return true; + } } /** * Fakes android.bluetooth.BluetoothGattService. */ static class FakeBluetoothGattService extends Wrappers.BluetoothGattServiceWrapper { + final FakeBluetoothDevice mDevice; final int mInstanceId; final UUID mUuid; final ArrayList<Wrappers.BluetoothGattCharacteristicWrapper> mCharacteristics; - public FakeBluetoothGattService(UUID uuid, int instanceId) { - super(null); + public FakeBluetoothGattService(FakeBluetoothDevice device, UUID uuid, int instanceId) { + super(null, null); + mDevice = device; mUuid = uuid; mInstanceId = instanceId; mCharacteristics = new ArrayList<Wrappers.BluetoothGattCharacteristicWrapper>(); @@ -329,7 +355,7 @@ countOfDuplicateUUID++; } } - fakeService.mCharacteristics.add(new FakeBluetoothGattCharacteristic( + fakeService.mCharacteristics.add(new FakeBluetoothGattCharacteristic(fakeService, /* instanceId */ countOfDuplicateUUID, properties, uuid)); } @@ -357,17 +383,70 @@ */ static class FakeBluetoothGattCharacteristic extends Wrappers.BluetoothGattCharacteristicWrapper { + final FakeBluetoothGattService mService; final int mInstanceId; final int mProperties; final UUID mUuid; + byte[] mValue; - public FakeBluetoothGattCharacteristic(int instanceId, int properties, UUID uuid) { + public FakeBluetoothGattCharacteristic( + FakeBluetoothGattService service, int instanceId, int properties, UUID uuid) { super(null); + mService = service; mInstanceId = instanceId; mProperties = properties; mUuid = uuid; + mValue = new byte[0]; } + // Simulate a value being read from a characteristic. + @CalledByNative("FakeBluetoothGattCharacteristic") + private static void valueRead(ChromeBluetoothRemoteGattCharacteristic chromeCharacteristic, + int status, byte[] value) { + FakeBluetoothGattCharacteristic fakeCharacteristic = + (FakeBluetoothGattCharacteristic) chromeCharacteristic.mCharacteristic; + + fakeCharacteristic.mValue = value; + fakeCharacteristic.mService.mDevice.mGattCallback.onCharacteristicRead( + fakeCharacteristic, status); + } + + // Simulate a value being written to a characteristic. + @CalledByNative("FakeBluetoothGattCharacteristic") + private static void valueWrite( + ChromeBluetoothRemoteGattCharacteristic chromeCharacteristic, int status) { + FakeBluetoothGattCharacteristic fakeCharacteristic = + (FakeBluetoothGattCharacteristic) chromeCharacteristic.mCharacteristic; + + fakeCharacteristic.mService.mDevice.mGattCallback.onCharacteristicWrite( + fakeCharacteristic, status); + } + + // Cause subsequent value reads of a characteristic to fail synchronously. + @CalledByNative("FakeBluetoothGattCharacteristic") + private static void setReadCharacteristicWillFailSynchronouslyOnce( + ChromeBluetoothRemoteGattCharacteristic chromeCharacteristic) { + FakeBluetoothGattCharacteristic fakeCharacteristic = + (FakeBluetoothGattCharacteristic) chromeCharacteristic.mCharacteristic; + + fakeCharacteristic.mService.mDevice.mGatt.mReadCharacteristicWillFailSynchronouslyOnce = + true; + } + + // Cause subsequent value writes of a characteristic to fail synchronously. + @CalledByNative("FakeBluetoothGattCharacteristic") + private static void setWriteCharacteristicWillFailSynchronouslyOnce( + ChromeBluetoothRemoteGattCharacteristic chromeCharacteristic) { + FakeBluetoothGattCharacteristic fakeCharacteristic = + (FakeBluetoothGattCharacteristic) chromeCharacteristic.mCharacteristic; + + fakeCharacteristic.mService.mDevice.mGatt + .mWriteCharacteristicWillFailSynchronouslyOnce = true; + } + + // ----------------------------------------------------------------------------------------- + // Wrappers.BluetoothGattCharacteristicWrapper overrides: + @Override public int getInstanceId() { return mInstanceId; @@ -382,6 +461,17 @@ public UUID getUuid() { return mUuid; } + + @Override + public byte[] getValue() { + return mValue; + } + + @Override + public boolean setValue(byte[] value) { + mValue = value; + return true; + } } // --------------------------------------------------------------------------------------------- @@ -397,4 +487,12 @@ // Binds to BluetoothAdapterAndroid::OnFakeBluetoothGattDiscoverServices. private static native void nativeOnFakeBluetoothGattDiscoverServices( long nativeBluetoothTestAndroid); + + // Binds to BluetoothAdapterAndroid::OnFakeBluetoothGattReadCharacteristic. + private static native void nativeOnFakeBluetoothGattReadCharacteristic( + long nativeBluetoothTestAndroid); + + // Binds to BluetoothAdapterAndroid::OnFakeBluetoothGattWriteCharacteristic. + private static native void nativeOnFakeBluetoothGattWriteCharacteristic( + long nativeBluetoothTestAndroid, byte[] value); }
diff --git a/device/bluetooth/test/bluetooth_test.cc b/device/bluetooth/test/bluetooth_test.cc index c5368ec8..e35ee87cc 100644 --- a/device/bluetooth/test/bluetooth_test.cc +++ b/device/bluetooth/test/bluetooth_test.cc
@@ -64,6 +64,11 @@ gatt_connections_.push_back(connection.release()); } +void BluetoothTestBase::ReadValueCallback(const std::vector<uint8>& value) { + ++callback_count_; + last_read_value_ = value; +} + void BluetoothTestBase::ErrorCallback() { ++error_callback_count_; } @@ -74,6 +79,12 @@ last_connect_error_code_ = error_code; } +void BluetoothTestBase::GattErrorCallback( + BluetoothGattService::GattErrorCode error_code) { + ++error_callback_count_; + last_gatt_error_code_ = error_code; +} + base::Closure BluetoothTestBase::GetCallback() { return base::Bind(&BluetoothTestBase::Callback, weak_factory_.GetWeakPtr()); } @@ -90,6 +101,12 @@ weak_factory_.GetWeakPtr()); } +BluetoothGattCharacteristic::ValueCallback +BluetoothTestBase::GetReadValueCallback() { + return base::Bind(&BluetoothTestBase::ReadValueCallback, + weak_factory_.GetWeakPtr()); +} + BluetoothAdapter::ErrorCallback BluetoothTestBase::GetErrorCallback() { return base::Bind(&BluetoothTestBase::ErrorCallback, weak_factory_.GetWeakPtr()); @@ -101,6 +118,12 @@ weak_factory_.GetWeakPtr()); } +base::Callback<void(BluetoothGattService::GattErrorCode)> +BluetoothTestBase::GetGattErrorCallback() { + return base::Bind(&BluetoothTestBase::GattErrorCallback, + weak_factory_.GetWeakPtr()); +} + void BluetoothTestBase::ResetEventCounts() { last_connect_error_code_ = BluetoothDevice::ERROR_UNKNOWN; callback_count_ = 0; @@ -108,6 +131,8 @@ gatt_connection_attempts_ = 0; gatt_disconnection_attempts_ = 0; gatt_discovery_attempts_ = 0; + gatt_read_characteristic_attempts_ = 0; + gatt_write_characteristic_attempts_ = 0; } } // namespace device
diff --git a/device/bluetooth/test/bluetooth_test.h b/device/bluetooth/test/bluetooth_test.h index 4b84e75..81de2b7 100644 --- a/device/bluetooth/test/bluetooth_test.h +++ b/device/bluetooth/test/bluetooth_test.h
@@ -11,7 +11,9 @@ #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_device.h" #include "device/bluetooth/bluetooth_discovery_session.h" +#include "device/bluetooth/bluetooth_gatt_characteristic.h" #include "device/bluetooth/bluetooth_gatt_connection.h" +#include "device/bluetooth/bluetooth_gatt_service.h" #include "testing/gtest/include/gtest/gtest.h" namespace device { @@ -99,6 +101,35 @@ const std::string& uuid, int properties) {} + // Simulates a Characteristic Read operation succeeding, returning |value|. + virtual void SimulateGattCharacteristicRead( + BluetoothGattCharacteristic* characteristic, + const std::vector<uint8>& value) {} + + // Simulates a Characteristic Read operation failing with a GattErrorCode. + virtual void SimulateGattCharacteristicReadError( + BluetoothGattCharacteristic* characteristic, + BluetoothGattService::GattErrorCode) {} + + // Simulates a Characteristic Read operation failing synchronously once for an + // unknown reason. + virtual void SimulateGattCharacteristicReadWillFailSynchronouslyOnce( + BluetoothGattCharacteristic* characteristic) {} + + // Simulates a Characteristic Write operation succeeding, returning |value|. + virtual void SimulateGattCharacteristicWrite( + BluetoothGattCharacteristic* characteristic) {} + + // Simulates a Characteristic Write operation failing with a GattErrorCode. + virtual void SimulateGattCharacteristicWriteError( + BluetoothGattCharacteristic* characteristic, + BluetoothGattService::GattErrorCode) {} + + // Simulates a Characteristic Write operation failing synchronously once for + // an unknown reason. + virtual void SimulateGattCharacteristicWriteWillFailSynchronouslyOnce( + BluetoothGattCharacteristic* characteristic) {} + // Remove the device from the adapter and delete it. virtual void DeleteDevice(BluetoothDevice* device); @@ -106,15 +137,20 @@ void Callback(); void DiscoverySessionCallback(scoped_ptr<BluetoothDiscoverySession>); void GattConnectionCallback(scoped_ptr<BluetoothGattConnection>); + void ReadValueCallback(const std::vector<uint8>& value); void ErrorCallback(); void ConnectErrorCallback(enum BluetoothDevice::ConnectErrorCode); + void GattErrorCallback(BluetoothGattService::GattErrorCode); // Accessors to get callbacks bound to this fixture: base::Closure GetCallback(); BluetoothAdapter::DiscoverySessionCallback GetDiscoverySessionCallback(); BluetoothDevice::GattConnectionCallback GetGattConnectionCallback(); + BluetoothGattCharacteristic::ValueCallback GetReadValueCallback(); BluetoothAdapter::ErrorCallback GetErrorCallback(); BluetoothDevice::ConnectErrorCallback GetConnectErrorCallback(); + base::Callback<void(BluetoothGattService::GattErrorCode)> + GetGattErrorCallback(); // Reset all event count members to 0. void ResetEventCounts(); @@ -128,11 +164,16 @@ ScopedVector<BluetoothGattConnection> gatt_connections_; enum BluetoothDevice::ConnectErrorCode last_connect_error_code_ = BluetoothDevice::ERROR_UNKNOWN; + std::vector<uint8> last_read_value_; + std::vector<uint8> last_write_value_; + BluetoothGattService::GattErrorCode last_gatt_error_code_; int callback_count_ = 0; int error_callback_count_ = 0; int gatt_connection_attempts_ = 0; int gatt_disconnection_attempts_ = 0; int gatt_discovery_attempts_ = 0; + int gatt_read_characteristic_attempts_ = 0; + int gatt_write_characteristic_attempts_ = 0; base::WeakPtrFactory<BluetoothTestBase> weak_factory_; };
diff --git a/device/bluetooth/test/bluetooth_test_android.cc b/device/bluetooth/test/bluetooth_test_android.cc index 5610722..5cd0674 100644 --- a/device/bluetooth/test/bluetooth_test_android.cc +++ b/device/bluetooth/test/bluetooth_test_android.cc
@@ -7,11 +7,13 @@ #include <iterator> #include <sstream> +#include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/logging.h" #include "device/bluetooth/android/wrappers.h" #include "device/bluetooth/bluetooth_adapter_android.h" #include "device/bluetooth/bluetooth_device_android.h" +#include "device/bluetooth/bluetooth_remote_gatt_characteristic_android.h" #include "device/bluetooth/bluetooth_remote_gatt_service_android.h" #include "device/bluetooth/test/test_bluetooth_adapter_observer.h" #include "jni/Fakes_jni.h" @@ -154,6 +156,75 @@ base::android::ConvertUTF8ToJavaString(env, uuid).obj(), properties); } +void BluetoothTestAndroid::SimulateGattCharacteristicRead( + BluetoothGattCharacteristic* characteristic, + const std::vector<uint8>& value) { + BluetoothRemoteGattCharacteristicAndroid* characteristic_android = + static_cast<BluetoothRemoteGattCharacteristicAndroid*>(characteristic); + JNIEnv* env = base::android::AttachCurrentThread(); + + Java_FakeBluetoothGattCharacteristic_valueRead( + env, characteristic_android->GetJavaObject().obj(), + 0, // android.bluetooth.BluetoothGatt.GATT_SUCCESS + base::android::ToJavaByteArray(env, value).obj()); +} + +void BluetoothTestAndroid::SimulateGattCharacteristicReadError( + BluetoothGattCharacteristic* characteristic, + BluetoothGattService::GattErrorCode error_code) { + BluetoothRemoteGattCharacteristicAndroid* characteristic_android = + static_cast<BluetoothRemoteGattCharacteristicAndroid*>(characteristic); + JNIEnv* env = base::android::AttachCurrentThread(); + std::vector<uint8> empty_value; + + Java_FakeBluetoothGattCharacteristic_valueRead( + env, characteristic_android->GetJavaObject().obj(), + BluetoothRemoteGattServiceAndroid::GetAndroidErrorCode(error_code), + base::android::ToJavaByteArray(env, empty_value).obj()); +} + +void BluetoothTestAndroid:: + SimulateGattCharacteristicReadWillFailSynchronouslyOnce( + BluetoothGattCharacteristic* characteristic) { + BluetoothRemoteGattCharacteristicAndroid* characteristic_android = + static_cast<BluetoothRemoteGattCharacteristicAndroid*>(characteristic); + JNIEnv* env = base::android::AttachCurrentThread(); + + Java_FakeBluetoothGattCharacteristic_setReadCharacteristicWillFailSynchronouslyOnce( + env, characteristic_android->GetJavaObject().obj()); +} + +void BluetoothTestAndroid::SimulateGattCharacteristicWrite( + BluetoothGattCharacteristic* characteristic) { + BluetoothRemoteGattCharacteristicAndroid* characteristic_android = + static_cast<BluetoothRemoteGattCharacteristicAndroid*>(characteristic); + Java_FakeBluetoothGattCharacteristic_valueWrite( + base::android::AttachCurrentThread(), + characteristic_android->GetJavaObject().obj(), + 0); // android.bluetooth.BluetoothGatt.GATT_SUCCESS +} + +void BluetoothTestAndroid::SimulateGattCharacteristicWriteError( + BluetoothGattCharacteristic* characteristic, + BluetoothGattService::GattErrorCode error_code) { + BluetoothRemoteGattCharacteristicAndroid* characteristic_android = + static_cast<BluetoothRemoteGattCharacteristicAndroid*>(characteristic); + Java_FakeBluetoothGattCharacteristic_valueWrite( + base::android::AttachCurrentThread(), + characteristic_android->GetJavaObject().obj(), + BluetoothRemoteGattServiceAndroid::GetAndroidErrorCode(error_code)); +} + +void BluetoothTestAndroid:: + SimulateGattCharacteristicWriteWillFailSynchronouslyOnce( + BluetoothGattCharacteristic* characteristic) { + BluetoothRemoteGattCharacteristicAndroid* characteristic_android = + static_cast<BluetoothRemoteGattCharacteristicAndroid*>(characteristic); + Java_FakeBluetoothGattCharacteristic_setWriteCharacteristicWillFailSynchronouslyOnce( + base::android::AttachCurrentThread(), + characteristic_android->GetJavaObject().obj()); +} + void BluetoothTestAndroid::OnFakeBluetoothDeviceConnectGattCalled( JNIEnv* env, jobject caller) { @@ -170,4 +241,18 @@ gatt_discovery_attempts_++; } +void BluetoothTestAndroid::OnFakeBluetoothGattReadCharacteristic( + JNIEnv* env, + jobject caller) { + gatt_read_characteristic_attempts_++; +} + +void BluetoothTestAndroid::OnFakeBluetoothGattWriteCharacteristic( + JNIEnv* env, + jobject caller, + jbyteArray value) { + gatt_write_characteristic_attempts_++; + base::android::JavaByteArrayToByteVector(env, value, &last_write_value_); +} + } // namespace device
diff --git a/device/bluetooth/test/bluetooth_test_android.h b/device/bluetooth/test/bluetooth_test_android.h index 99b807d87..48939b37 100644 --- a/device/bluetooth/test/bluetooth_test_android.h +++ b/device/bluetooth/test/bluetooth_test_android.h
@@ -38,6 +38,21 @@ void SimulateGattCharacteristic(BluetoothGattService* service, const std::string& uuid, int properties) override; + void SimulateGattCharacteristicRead( + BluetoothGattCharacteristic* characteristic, + const std::vector<uint8>& value) override; + void SimulateGattCharacteristicReadError( + BluetoothGattCharacteristic* characteristic, + BluetoothGattService::GattErrorCode) override; + void SimulateGattCharacteristicReadWillFailSynchronouslyOnce( + BluetoothGattCharacteristic* characteristic) override; + void SimulateGattCharacteristicWrite( + BluetoothGattCharacteristic* characteristic) override; + void SimulateGattCharacteristicWriteError( + BluetoothGattCharacteristic* characteristic, + BluetoothGattService::GattErrorCode) override; + void SimulateGattCharacteristicWriteWillFailSynchronouslyOnce( + BluetoothGattCharacteristic* characteristic) override; // Records that Java FakeBluetoothDevice connectGatt was called. void OnFakeBluetoothDeviceConnectGattCalled(JNIEnv* env, jobject caller); @@ -48,6 +63,14 @@ // Records that Java FakeBluetoothGatt discoverServices was called. void OnFakeBluetoothGattDiscoverServices(JNIEnv* env, jobject caller); + // Records that Java FakeBluetoothGatt discoverServices was called. + void OnFakeBluetoothGattReadCharacteristic(JNIEnv* env, jobject caller); + + // Records that Java FakeBluetoothGatt discoverServices was called. + void OnFakeBluetoothGattWriteCharacteristic(JNIEnv* env, + jobject caller, + jbyteArray value); + base::android::ScopedJavaGlobalRef<jobject> j_fake_bluetooth_adapter_; };
diff --git a/device/serial/buffer.cc b/device/serial/buffer.cc index 2756d9f..b5bf8883 100644 --- a/device/serial/buffer.cc +++ b/device/serial/buffer.cc
@@ -2,7 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/numerics/safe_conversions.h" +#include "base/stl_util.h" #include "device/serial/buffer.h" +#include "net/base/io_buffer.h" namespace device { @@ -12,4 +15,52 @@ WritableBuffer::~WritableBuffer() { } +SendBuffer::SendBuffer( + const std::vector<char>& data, + const base::Callback<void(int, device::serial::SendError)>& callback) + : data_(data), callback_(callback) {} + +SendBuffer::~SendBuffer() {} + +const char* SendBuffer::GetData() { + return vector_as_array(&data_); +} + +uint32_t SendBuffer::GetSize() { + return base::checked_cast<uint32_t>(data_.size()); +} + +void SendBuffer::Done(uint32_t bytes_read) { + callback_.Run(bytes_read, device::serial::SEND_ERROR_NONE); +} + +void SendBuffer::DoneWithError(uint32_t bytes_read, int32_t error) { + callback_.Run(bytes_read, static_cast<device::serial::SendError>(error)); +} + +ReceiveBuffer::ReceiveBuffer( + scoped_refptr<net::IOBuffer> buffer, + uint32_t size, + const base::Callback<void(int, device::serial::ReceiveError)>& callback) + : buffer_(buffer), size_(size), callback_(callback) {} + +ReceiveBuffer::~ReceiveBuffer() {} + +char* ReceiveBuffer::GetData() { + return buffer_->data(); +} + +uint32_t ReceiveBuffer::GetSize() { + return size_; +} + +void ReceiveBuffer::Done(uint32_t bytes_written) { + callback_.Run(bytes_written, device::serial::RECEIVE_ERROR_NONE); +} + +void ReceiveBuffer::DoneWithError(uint32_t bytes_written, int32_t error) { + callback_.Run(bytes_written, + static_cast<device::serial::ReceiveError>(error)); +} + } // namespace device
diff --git a/device/serial/buffer.h b/device/serial/buffer.h index 49169d7..44436a5 100644 --- a/device/serial/buffer.h +++ b/device/serial/buffer.h
@@ -6,6 +6,9 @@ #define DEVICE_SERIAL_BUFFER_H_ #include "base/basictypes.h" +#include "base/callback.h" +#include "device/serial/serial.mojom.h" +#include "net/base/io_buffer.h" namespace device { @@ -35,6 +38,46 @@ virtual void DoneWithError(uint32_t bytes_written, int32_t error) = 0; }; +// A useful basic implementation of a ReadOnlyBuffer in which the data is +// initialized via a character vector. +class SendBuffer : public device::ReadOnlyBuffer { + public: + SendBuffer( + const std::vector<char>& data, + const base::Callback<void(int, device::serial::SendError)>& callback); + ~SendBuffer() override; + + const char* GetData() override; + uint32_t GetSize() override; + void Done(uint32_t bytes_read) override; + void DoneWithError(uint32_t bytes_read, int32_t error) override; + + private: + const std::vector<char> data_; + const base::Callback<void(int, device::serial::SendError)> callback_; +}; + +// A useful basic implementation of a WritableBuffer in which the data is +// stored in a net::IOBuffer. +class ReceiveBuffer : public device::WritableBuffer { + public: + ReceiveBuffer( + scoped_refptr<net::IOBuffer> buffer, + uint32_t size, + const base::Callback<void(int, device::serial::ReceiveError)>& callback); + ~ReceiveBuffer() override; + + char* GetData() override; + uint32_t GetSize() override; + void Done(uint32_t bytes_written) override; + void DoneWithError(uint32_t bytes_written, int32_t error) override; + + private: + scoped_refptr<net::IOBuffer> buffer_; + const uint32_t size_; + const base::Callback<void(int, device::serial::ReceiveError)> callback_; +}; + } // namespace device #endif // DEVICE_SERIAL_BUFFER_H_
diff --git a/extensions/browser/api/serial/serial_connection.cc b/extensions/browser/api/serial/serial_connection.cc index 65b27a12..edf6a0d 100644 --- a/extensions/browser/api/serial/serial_connection.cc +++ b/extensions/browser/api/serial/serial_connection.cc
@@ -10,7 +10,7 @@ #include "base/files/file_path.h" #include "base/lazy_instance.h" #include "base/message_loop/message_loop.h" -#include "base/stl_util.h" +#include "device/serial/buffer.h" #include "extensions/browser/api/api_resource_manager.h" #include "extensions/common/api/serial.h" @@ -141,51 +141,6 @@ return device::serial::STOP_BITS_NONE; } -class SendBuffer : public device::ReadOnlyBuffer { - public: - SendBuffer( - const std::vector<char>& data, - const base::Callback<void(int, device::serial::SendError)>& callback) - : data_(data), callback_(callback) {} - ~SendBuffer() override {} - const char* GetData() override { return vector_as_array(&data_); } - uint32_t GetSize() override { return static_cast<uint32_t>(data_.size()); } - void Done(uint32_t bytes_read) override { - callback_.Run(bytes_read, device::serial::SEND_ERROR_NONE); - } - void DoneWithError(uint32_t bytes_read, int32_t error) override { - callback_.Run(bytes_read, static_cast<device::serial::SendError>(error)); - } - - private: - const std::vector<char> data_; - const base::Callback<void(int, device::serial::SendError)> callback_; -}; - -class ReceiveBuffer : public device::WritableBuffer { - public: - ReceiveBuffer( - scoped_refptr<net::IOBuffer> buffer, - uint32_t size, - const base::Callback<void(int, device::serial::ReceiveError)>& callback) - : buffer_(buffer), size_(size), callback_(callback) {} - ~ReceiveBuffer() override {} - char* GetData() override { return buffer_->data(); } - uint32_t GetSize() override { return size_; } - void Done(uint32_t bytes_written) override { - callback_.Run(bytes_written, device::serial::RECEIVE_ERROR_NONE); - } - void DoneWithError(uint32_t bytes_written, int32_t error) override { - callback_.Run(bytes_written, - static_cast<device::serial::ReceiveError>(error)); - } - - private: - scoped_refptr<net::IOBuffer> buffer_; - const uint32_t size_; - const base::Callback<void(int, device::serial::ReceiveError)> callback_; -}; - } // namespace static base::LazyInstance< @@ -267,9 +222,8 @@ return false; receive_complete_ = callback; receive_buffer_ = new net::IOBuffer(buffer_size_); - io_handler_->Read(scoped_ptr<device::WritableBuffer>(new ReceiveBuffer( - receive_buffer_, - buffer_size_, + io_handler_->Read(make_scoped_ptr(new device::ReceiveBuffer( + receive_buffer_, buffer_size_, base::Bind(&SerialConnection::OnAsyncReadComplete, AsWeakPtr())))); receive_timeout_task_.reset(); if (receive_timeout_ > 0) { @@ -286,7 +240,7 @@ if (!send_complete_.is_null()) return false; send_complete_ = callback; - io_handler_->Write(scoped_ptr<device::ReadOnlyBuffer>(new SendBuffer( + io_handler_->Write(make_scoped_ptr(new device::SendBuffer( data, base::Bind(&SerialConnection::OnAsyncWriteComplete, AsWeakPtr())))); send_timeout_task_.reset(); if (send_timeout_ > 0) {
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn index c0bff59..45e86dfe 100644 --- a/extensions/common/BUILD.gn +++ b/extensions/common/BUILD.gn
@@ -72,6 +72,15 @@ "//url", ] + if (is_android) { + deps -= [ "//device/usb" ] + sources -= [ + "api/printer_provider/usb_printer_manifest_data.cc", + "api/printer_provider/usb_printer_manifest_data.h", + "api/printer_provider/usb_printer_manifest_handler.cc", + ] + } + if (enable_nacl) { nacl_sources = rebase_path(extensions_gypi_values.extensions_common_sources_nacl,
diff --git a/extensions/common/api/printer_provider/usb_printer_manifest_handler_android.cc b/extensions/common/api/printer_provider/usb_printer_manifest_handler_android.cc new file mode 100644 index 0000000..88861c4b --- /dev/null +++ b/extensions/common/api/printer_provider/usb_printer_manifest_handler_android.cc
@@ -0,0 +1,26 @@ +// Copyright 2015 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 "extensions/common/api/printer_provider/usb_printer_manifest_handler.h" + +#include "extensions/common/extension.h" + +namespace extensions { + +UsbPrinterManifestHandler::UsbPrinterManifestHandler() { +} + +UsbPrinterManifestHandler::~UsbPrinterManifestHandler() { +} + +bool UsbPrinterManifestHandler::Parse(Extension* extension, + base::string16* error) { + return false; +} + +const std::vector<std::string> UsbPrinterManifestHandler::Keys() const { + return std::vector<std::string>(); +} + +} // namespace extensions
diff --git a/extensions/extensions.gypi b/extensions/extensions.gypi index d730681..2397230 100644 --- a/extensions/extensions.gypi +++ b/extensions/extensions.gypi
@@ -27,6 +27,7 @@ 'common/api/printer_provider/usb_printer_manifest_data.cc', 'common/api/printer_provider/usb_printer_manifest_data.h', 'common/api/printer_provider/usb_printer_manifest_handler.cc', + 'common/api/printer_provider/usb_printer_manifest_handler_android.cc', 'common/api/printer_provider/usb_printer_manifest_handler.h', 'common/api/sockets/sockets_manifest_data.cc', 'common/api/sockets/sockets_manifest_data.h',
diff --git a/gin/v8_initializer.cc b/gin/v8_initializer.cc index 810225c..8bcc78d 100644 --- a/gin/v8_initializer.cc +++ b/gin/v8_initializer.cc
@@ -53,8 +53,19 @@ base::MemoryMappedFile::Region g_natives_region; base::MemoryMappedFile::Region g_snapshot_region; +#if defined(OS_ANDROID) +#ifdef __LP64__ +const char kNativesFileName[] = "natives_blob_64.bin"; +const char kSnapshotFileName[] = "snapshot_blob_64.bin"; +#else +const char kNativesFileName[] = "natives_blob_32.bin"; +const char kSnapshotFileName[] = "snapshot_blob_32.bin"; +#endif // __LP64__ + +#else // defined(OS_ANDROID) const char kNativesFileName[] = "natives_blob.bin"; const char kSnapshotFileName[] = "snapshot_blob.bin"; +#endif // defined(OS_ANDROID) void GetV8FilePath(const char* file_name, base::FilePath* path_out) { #if !defined(OS_MACOSX)
diff --git a/gpu/GLES2/gl2extchromium.h b/gpu/GLES2/gl2extchromium.h index 9e152497..7939bc7 100644 --- a/gpu/GLES2/gl2extchromium.h +++ b/gpu/GLES2/gl2extchromium.h
@@ -681,14 +681,12 @@ #ifdef GL_GLEXT_PROTOTYPES GL_APICALL GLuint GL_APIENTRY glInsertSyncPointCHROMIUM(); -GL_APICALL void GL_APIENTRY glWaitSyncPointCHROMIUM(GLuint sync_point); GL_APICALL GLuint64 GL_APIENTRY glInsertFenceSyncCHROMIUM(); GL_APICALL void GL_APIENTRY glGenSyncTokenCHROMIUM(GLuint64 fence_sync, GLbyte* sync_token); GL_APICALL void GL_APIENTRY glWaitSyncTokenCHROMIUM(const GLbyte* sync_token); #endif typedef GLuint (GL_APIENTRYP PFNGLINSERTSYNCPOINTCHROMIUMPROC) (); -typedef void (GL_APIENTRYP PFNGLWAITSYNCPOINTCHROMIUMPROC) (GLuint sync_point); typedef GLuint64 (GL_APIENTRYP PFNGLINSERTFENCESYNCCHROMIUMPROC) (); typedef void (GL_APIENTRYP PFNGLGENSYNCTOKENCHROMIUMPROC) (GLuint64 fence_sync, GLbyte* sync_token);
diff --git a/gpu/blink/webgraphicscontext3d_impl.cc b/gpu/blink/webgraphicscontext3d_impl.cc index ae7b160..040d7e1 100644 --- a/gpu/blink/webgraphicscontext3d_impl.cc +++ b/gpu/blink/webgraphicscontext3d_impl.cc
@@ -11,6 +11,7 @@ #include "gpu/command_buffer/client/gles2_implementation.h" #include "gpu/command_buffer/client/gles2_lib.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/common/sync_token.h" #include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h" #include "third_party/khronos/GLES2/gl2.h" @@ -213,7 +214,15 @@ return flush_id_; } -DELEGATE_TO_GL_R(insertSyncPoint, InsertSyncPointCHROMIUM, unsigned int) +bool WebGraphicsContext3DImpl::insertSyncPoint(WGC3Dbyte* sync_token) { + const uint32_t sync_point = gl_->InsertSyncPointCHROMIUM(); + if (!sync_point) + return false; + + gpu::SyncToken sync_token_data(sync_point); + memcpy(sync_token, &sync_token_data, sizeof(sync_token_data)); + return true; +} DELEGATE_TO_GL_3(reshapeWithScaleFactor, ResizeCHROMIUM, int, int, float) @@ -880,7 +889,7 @@ gl_->ShallowFinishCHROMIUM(); } -DELEGATE_TO_GL_1(waitSyncPoint, WaitSyncPointCHROMIUM, GLuint) +DELEGATE_TO_GL_1(waitSyncToken, WaitSyncTokenCHROMIUM, const WGC3Dbyte*) void WebGraphicsContext3DImpl::loseContextCHROMIUM( WGC3Denum current, WGC3Denum other) {
diff --git a/gpu/blink/webgraphicscontext3d_impl.h b/gpu/blink/webgraphicscontext3d_impl.h index e0cd53b..a7cc2907 100644 --- a/gpu/blink/webgraphicscontext3d_impl.h +++ b/gpu/blink/webgraphicscontext3d_impl.h
@@ -37,8 +37,8 @@ uint32_t lastFlushID() override; - unsigned int insertSyncPoint() override; - void waitSyncPoint(unsigned int sync_point) override; + bool insertSyncPoint(blink::WGC3Dbyte* sync_token) override; + void waitSyncToken(const blink::WGC3Dbyte* sync_token) override; void loseContextCHROMIUM(blink::WGC3Denum current, blink::WGC3Denum other) override;
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 8be8c4b..03dad41 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -4118,7 +4118,9 @@ }, 'WaitSyncPointCHROMIUM': { 'type': 'Custom', - 'impl_func': True, + 'impl_func': False, + 'unit_test': False, + 'client_test': False, 'extension': "CHROMIUM_sync_point", 'chromium': True, 'trace_level': 1,
diff --git a/gpu/command_buffer/client/fenced_allocator.cc b/gpu/command_buffer/client/fenced_allocator.cc index 726fe7d..7f34e58 100644 --- a/gpu/command_buffer/client/fenced_allocator.cc +++ b/gpu/command_buffer/client/fenced_allocator.cc
@@ -27,11 +27,6 @@ } // namespace -#ifndef _MSC_VER -const FencedAllocator::Offset FencedAllocator::kInvalidOffset; -const unsigned int FencedAllocator::kAllocAlignment; -#endif - FencedAllocator::FencedAllocator(unsigned int size, CommandBufferHelper* helper) : helper_(helper), bytes_in_use_(0) { Block block = { FREE, 0, RoundDown(size), kUnusedToken };
diff --git a/gpu/command_buffer/client/fenced_allocator.h b/gpu/command_buffer/client/fenced_allocator.h index 95dccce..45b4dfd 100644 --- a/gpu/command_buffer/client/fenced_allocator.h +++ b/gpu/command_buffer/client/fenced_allocator.h
@@ -33,10 +33,10 @@ public: typedef unsigned int Offset; // Invalid offset, returned by Alloc in case of failure. - static const Offset kInvalidOffset = 0xffffffffU; + enum : Offset { kInvalidOffset = 0xffffffffU }; // Allocation alignment, must be a power of two. - static const unsigned int kAllocAlignment = 16; + enum : unsigned int { kAllocAlignment = 16 }; // Creates a FencedAllocator. Note that the size of the buffer is passed, but // not its base address: everything is handled as offsets into the buffer.
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 45b52d9..4fcb0b3 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -5366,6 +5366,11 @@ return gpu_control_->InsertSyncPoint(); } +void GLES2Implementation::WaitSyncPointCHROMIUM(GLuint sync_point) { + // This should no longer be called. + NOTREACHED(); +} + GLuint GLES2Implementation::InsertFutureSyncPointCHROMIUM() { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertFutureSyncPointCHROMIUM"); @@ -5437,25 +5442,34 @@ } void GLES2Implementation::WaitSyncTokenCHROMIUM(const GLbyte* sync_token) { - if (!sync_token) { - SetGLError(GL_INVALID_VALUE, "glWaitSyncTokenCHROMIUM", "empty sync_token"); - return; - }; + if (sync_token) { + // Copy the data over before data access to ensure alignment. + SyncToken sync_token_data; + memcpy(&sync_token_data, sync_token, sizeof(SyncToken)); + if (sync_token_data.HasData()) { + if (!sync_token_data.verified_flush() && + !gpu_control_->CanWaitUnverifiedSyncToken(&sync_token_data)) { + SetGLError(GL_INVALID_VALUE, "glWaitSyncTokenCHROMIUM", + "Cannot wait on sync_token which has not been verified"); + return; + } - // Copy the data over before data access to ensure alignment. - SyncToken sync_token_data; - memcpy(&sync_token_data, sync_token, sizeof(SyncToken)); + // TODO(dyen): Temporarily support old sync points, remove once all old + // sync points have been removed. + const gpu::CommandBufferNamespace namespace_id = + sync_token_data.namespace_id(); + if (namespace_id == gpu::CommandBufferNamespace::OLD_SYNC_POINTS) { + const uint32_t sync_point = + static_cast<uint32_t>(sync_token_data.release_count()); + helper_->WaitSyncPointCHROMIUM(sync_point); + return; + } - if (!sync_token_data.verified_flush() && - !gpu_control_->CanWaitUnverifiedSyncToken(&sync_token_data)) { - SetGLError(GL_INVALID_VALUE, "glWaitSyncTokenCHROMIUM", - "Cannot wait on sync_token which has not been verified"); - return; + helper_->WaitSyncTokenCHROMIUM( + static_cast<GLuint>(sync_token_data.namespace_id()), + sync_token_data.command_buffer_id(), sync_token_data.release_count()); + } } - - helper_->WaitSyncTokenCHROMIUM(sync_token_data.namespace_id(), - sync_token_data.command_buffer_id(), - sync_token_data.release_count()); } namespace {
diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h index 9f8bfba..0fa8726 100644 --- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
@@ -3446,14 +3446,6 @@ CheckGLError(); } -void GLES2Implementation::WaitSyncPointCHROMIUM(GLuint sync_point) { - GPU_CLIENT_SINGLE_THREAD_CHECK(); - GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitSyncPointCHROMIUM(" - << sync_point << ")"); - helper_->WaitSyncPointCHROMIUM(sync_point); - CheckGLError(); -} - void GLES2Implementation::DrawBuffersEXT(GLsizei count, const GLenum* bufs) { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawBuffersEXT(" << count << ", "
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index 62f108b..ef2efeb 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -3884,6 +3884,36 @@ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +TEST_F(GLES2ImplementationTest, WaitSyncTokenCHROMIUMErrors) { + ExpectedMemoryInfo result = + GetExpectedResultMemory(sizeof(cmds::GetError::Result)); + EXPECT_CALL(*command_buffer(), OnFlush()) + .WillRepeatedly(SetMemory(result.ptr, GLuint(GL_NO_ERROR))) + .RetiresOnSaturation(); + + // Empty sync tokens should be produce no error and be a nop. + ClearCommands(); + gl_->WaitSyncTokenCHROMIUM(nullptr); + EXPECT_TRUE(NoCommandsWritten()); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError()); + + // Invalid sync tokens should produce no error and be a nop. + ClearCommands(); + gpu::SyncToken invalid_sync_token(CommandBufferNamespace::INVALID, 0, 0); + gl_->WaitSyncTokenCHROMIUM(invalid_sync_token.GetConstData()); + EXPECT_TRUE(NoCommandsWritten()); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError()); + + // Unverified sync token should produce INVALID_OPERATION. + ClearCommands(); + gpu::SyncToken unverified_sync_token(CommandBufferNamespace::GPU_IO, 0, 0); + EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(_)) + .WillOnce(testing::Return(false)); + gl_->WaitSyncTokenCHROMIUM(unverified_sync_token.GetConstData()); + EXPECT_TRUE(NoCommandsWritten()); + EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); +} + TEST_F(GLES2ImplementationTest, IsEnabled) { // If we use a valid enum, its state is cached on client side, so no command // is actually generated, and this test will fail.
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h index ed373833..c587367 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -3044,17 +3044,6 @@ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } -TEST_F(GLES2ImplementationTest, WaitSyncPointCHROMIUM) { - struct Cmds { - cmds::WaitSyncPointCHROMIUM cmd; - }; - Cmds expected; - expected.cmd.Init(1); - - gl_->WaitSyncPointCHROMIUM(1); - EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); -} - TEST_F(GLES2ImplementationTest, DrawBuffersEXT) { GLenum data[1][1] = {{0}}; struct Cmds {
diff --git a/gpu/command_buffer/common/constants.h b/gpu/command_buffer/common/constants.h index e14c06d..fade0a54 100644 --- a/gpu/command_buffer/common/constants.h +++ b/gpu/command_buffer/common/constants.h
@@ -73,11 +73,11 @@ GPU_IO, IN_PROCESS, MOJO, + OLD_SYNC_POINTS, NUM_COMMAND_BUFFER_NAMESPACES }; - } // namespace gpu #endif // GPU_COMMAND_BUFFER_COMMON_CONSTANTS_H_
diff --git a/gpu/command_buffer/common/mailbox_holder.cc b/gpu/command_buffer/common/mailbox_holder.cc index 87dec36fe..f496e6600 100644 --- a/gpu/command_buffer/common/mailbox_holder.cc +++ b/gpu/command_buffer/common/mailbox_holder.cc
@@ -6,13 +6,13 @@ namespace gpu { -MailboxHolder::MailboxHolder() : texture_target(0), sync_point(0) {} +MailboxHolder::MailboxHolder() : texture_target(0) {} -MailboxHolder::MailboxHolder(const Mailbox& mailbox, - uint32_t texture_target, - uint32_t sync_point) +MailboxHolder::MailboxHolder(const gpu::Mailbox& mailbox, + const gpu::SyncToken& sync_token, + uint32_t texture_target) : mailbox(mailbox), - texture_target(texture_target), - sync_point(sync_point) {} + sync_token(sync_token), + texture_target(texture_target) {} } // namespace gpu
diff --git a/gpu/command_buffer/common/mailbox_holder.h b/gpu/command_buffer/common/mailbox_holder.h index 51c377d..b1cc3df 100644 --- a/gpu/command_buffer/common/mailbox_holder.h +++ b/gpu/command_buffer/common/mailbox_holder.h
@@ -9,6 +9,7 @@ #include <string.h> #include "gpu/command_buffer/common/mailbox.h" +#include "gpu/command_buffer/common/sync_token.h" #include "gpu/gpu_export.h" namespace gpu { @@ -23,11 +24,12 @@ struct GPU_EXPORT MailboxHolder { MailboxHolder(); MailboxHolder(const gpu::Mailbox& mailbox, - uint32_t texture_target, - uint32_t sync_point); + const gpu::SyncToken& sync_token, + uint32_t texture_target); + gpu::Mailbox mailbox; + gpu::SyncToken sync_token; uint32_t texture_target; - uint32_t sync_point; }; } // namespace gpu
diff --git a/gpu/command_buffer/common/sync_token.h b/gpu/command_buffer/common/sync_token.h index cceb44e..11af396 100644 --- a/gpu/command_buffer/common/sync_token.h +++ b/gpu/command_buffer/common/sync_token.h
@@ -29,6 +29,16 @@ command_buffer_id_(0), release_count_(0) {} + // TODO(dyen): This is an intermediate conversion constructor while we + // are converting from the old sync point system. Remove once conversion + // is finished. + explicit SyncToken(uint32_t sync_point) + : verified_flush_(sync_point ? true : false), + namespace_id_(sync_point ? gpu::CommandBufferNamespace::OLD_SYNC_POINTS + : gpu::CommandBufferNamespace::INVALID), + command_buffer_id_(0), + release_count_(sync_point) {} + SyncToken(CommandBufferNamespace namespace_id, uint64_t command_buffer_id, uint64_t release_count) @@ -45,10 +55,21 @@ release_count_ = release_count; } + void Clear() { + verified_flush_ = false; + namespace_id_ = CommandBufferNamespace::INVALID; + command_buffer_id_ = 0; + release_count_ = 0; + } + void SetVerifyFlush() { verified_flush_ = true; } + bool HasData() const { + return namespace_id_ != CommandBufferNamespace::INVALID; + } + int8_t* GetData() { return reinterpret_cast<int8_t*>(this); } const int8_t* GetConstData() const { @@ -70,6 +91,15 @@ (release_count_ < other.release_count())))); } + bool operator==(const SyncToken& other) const { + return verified_flush_ == other.verified_flush() && + namespace_id_ == other.namespace_id() && + command_buffer_id_ == other.command_buffer_id() && + release_count_ == other.release_count(); + } + + bool operator!=(const SyncToken& other) const { return !(*this == other); } + private: bool verified_flush_; CommandBufferNamespace namespace_id_;
diff --git a/gpu/ipc/gpu_command_buffer_traits.cc b/gpu/ipc/gpu_command_buffer_traits.cc index 6a77984f..a1932eed 100644 --- a/gpu/ipc/gpu_command_buffer_traits.cc +++ b/gpu/ipc/gpu_command_buffer_traits.cc
@@ -32,19 +32,17 @@ const param_type& p) { WriteParam(m, p.get_offset); WriteParam(m, p.token); - WriteParam(m, static_cast<int32>(p.error)); + WriteParam(m, p.error); WriteParam(m, p.generation); } bool ParamTraits<gpu::CommandBuffer::State> ::Read(const Message* m, base::PickleIterator* iter, param_type* p) { - int32 temp; if (ReadParam(m, iter, &p->get_offset) && ReadParam(m, iter, &p->token) && - ReadParam(m, iter, &temp) && + ReadParam(m, iter, &p->error) && ReadParam(m, iter, &p->generation)) { - p->error = static_cast<gpu::error::Error>(temp); return true; } else { return false; @@ -57,33 +55,37 @@ } void ParamTraits<gpu::SyncToken>::Write(Message* m, const param_type& p) { - const int namespace_id = static_cast<int>(p.namespace_id()); - const uint64_t command_buffer_id = p.command_buffer_id(); - const uint64_t release_count = p.release_count(); + DCHECK(!p.HasData() || p.verified_flush()); - m->WriteBytes(&namespace_id, sizeof(namespace_id)); - m->WriteBytes(&command_buffer_id, sizeof(command_buffer_id)); - m->WriteBytes(&release_count, sizeof(release_count)); + WriteParam(m, p.verified_flush()); + WriteParam(m, p.namespace_id()); + WriteParam(m, p.command_buffer_id()); + WriteParam(m, p.release_count()); } bool ParamTraits<gpu::SyncToken>::Read(const Message* m, base::PickleIterator* iter, param_type* p) { - int namespace_id = -1; - if (!iter->ReadInt(&namespace_id)) - return false; - + bool verified_flush = false; + gpu::CommandBufferNamespace namespace_id = + gpu::CommandBufferNamespace::INVALID; uint64_t command_buffer_id = 0; - if (!iter->ReadUInt64(&command_buffer_id)) - return false; - uint64_t release_count = 0; - if (!iter->ReadUInt64(&release_count)) - return false; - p->Set(static_cast<gpu::CommandBufferNamespace>(namespace_id), - command_buffer_id, - release_count); + if (!ReadParam(m, iter, &verified_flush) || + !ReadParam(m, iter, &namespace_id) || + !ReadParam(m, iter, &command_buffer_id) || + !ReadParam(m, iter, &release_count)) { + return false; + } + + p->Set(namespace_id, command_buffer_id, release_count); + if (p->HasData()) { + if (!verified_flush) + return false; + p->SetVerifyFlush(); + } + return true; } @@ -116,23 +118,23 @@ void ParamTraits<gpu::MailboxHolder>::Write(Message* m, const param_type& p) { WriteParam(m, p.mailbox); + WriteParam(m, p.sync_token); WriteParam(m, p.texture_target); - WriteParam(m, p.sync_point); } bool ParamTraits<gpu::MailboxHolder> ::Read(const Message* m, base::PickleIterator* iter, param_type* p) { - if (!ReadParam(m, iter, &p->mailbox) || - !ReadParam(m, iter, &p->texture_target) || - !ReadParam(m, iter, &p->sync_point)) + if (!ReadParam(m, iter, &p->mailbox) || !ReadParam(m, iter, &p->sync_token) || + !ReadParam(m, iter, &p->texture_target)) return false; return true; } void ParamTraits<gpu::MailboxHolder>::Log(const param_type& p, std::string* l) { - ParamTraits<gpu::Mailbox>::Log(p.mailbox, l); - *l += base::StringPrintf(":%04x@%d", p.texture_target, p.sync_point); + LogParam(p.mailbox, l); + LogParam(p.sync_token, l); + *l += base::StringPrintf(":%04x@", p.texture_target); } void ParamTraits<gpu::ValueState>::Write(Message* m, const param_type& p) {
diff --git a/gpu/ipc/gpu_command_buffer_traits_multi.h b/gpu/ipc/gpu_command_buffer_traits_multi.h index 1c69e8ef..d82ee5c 100644 --- a/gpu/ipc/gpu_command_buffer_traits_multi.h +++ b/gpu/ipc/gpu_command_buffer_traits_multi.h
@@ -4,6 +4,7 @@ // Multiply-included message file, hence no include guard here. #include "gpu/command_buffer/common/capabilities.h" +#include "gpu/command_buffer/common/constants.h" #include "gpu/gpu_export.h" #include "ipc/ipc_message_utils.h" #include "ipc/param_traits_macros.h" @@ -11,6 +12,12 @@ #undef IPC_MESSAGE_EXPORT #define IPC_MESSAGE_EXPORT GPU_EXPORT +IPC_ENUM_TRAITS_MAX_VALUE(gpu::error::Error, gpu::error::kErrorLast) +IPC_ENUM_TRAITS_MIN_MAX_VALUE( + gpu::CommandBufferNamespace, + gpu::CommandBufferNamespace::INVALID, + gpu::CommandBufferNamespace::NUM_COMMAND_BUFFER_NAMESPACES) + IPC_STRUCT_TRAITS_BEGIN(gpu::Capabilities::ShaderPrecision) IPC_STRUCT_TRAITS_MEMBER(min_range) IPC_STRUCT_TRAITS_MEMBER(max_range)
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg index 014cf086..01674866 100644 --- a/infra/config/cq.cfg +++ b/infra/config/cq.cfg
@@ -60,14 +60,8 @@ } buckets { name: "tryserver.chromium.mac" - builders { - name: "ios_dbg_simulator_ninja" - experiment_percentage: 10 - } - builders { - name: "ios_rel_device_ninja" - experiment_percentage: 10 - } + builders { name: "ios_dbg_simulator_ninja" } + builders { name: "ios_rel_device_ninja" } builders { name: "mac_chromium_compile_dbg_ng" } builders { name: "mac_chromium_gn_rel" } builders { name: "mac_chromium_rel_ng" }
diff --git a/ios/build/bots/tests/common_tests.json b/ios/build/bots/tests/common_tests.json index b9ae41ab..4a63145 100644 --- a/ios/build/bots/tests/common_tests.json +++ b/ios/build/bots/tests/common_tests.json
@@ -7,9 +7,6 @@ "app": "components_unittests" }, { - "app": "content_unittests" - }, - { "app": "crypto_unittests" }, {
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS index 013c6682..fcfd9f15 100644 --- a/ios/chrome/browser/DEPS +++ b/ios/chrome/browser/DEPS
@@ -35,6 +35,7 @@ "+components/password_manager/core/browser", "+components/policy/core", "+components/pref_registry", + "+components/profile_metrics", "+components/proxy_config", "+components/rappor", "+components/rlz",
diff --git a/ios/chrome/browser/browser_state_metrics/OWNERS b/ios/chrome/browser/browser_state_metrics/OWNERS new file mode 100644 index 0000000..367bb85d --- /dev/null +++ b/ios/chrome/browser/browser_state_metrics/OWNERS
@@ -0,0 +1,3 @@ +anthonyvd@chromium.org +erg@chromium.org +mlerman@chromium.org
diff --git a/ios/chrome/browser/browser_state_metrics/browser_state_metrics.cc b/ios/chrome/browser/browser_state_metrics/browser_state_metrics.cc new file mode 100644 index 0000000..3d91c63 --- /dev/null +++ b/ios/chrome/browser/browser_state_metrics/browser_state_metrics.cc
@@ -0,0 +1,35 @@ +// Copyright 2015 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 "ios/chrome/browser/browser_state_metrics/browser_state_metrics.h" + +#include "components/profile_metrics/counts.h" +#include "ios/chrome/browser/browser_state/browser_state_info_cache.h" +#include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state_manager.h" + +bool CountBrowserStateInformation(ios::ChromeBrowserStateManager* manager, + profile_metrics::Counts* counts) { + BrowserStateInfoCache* info_cache = manager->GetBrowserStateInfoCache(); + size_t number_of_browser_states = info_cache->GetNumberOfBrowserStates(); + counts->total = number_of_browser_states; + + // Ignore other metrics if we have no browser states. + if (!number_of_browser_states) + return false; + + for (size_t i = 0; i < number_of_browser_states; ++i) { + if (info_cache->BrowserStateIsAuthenticatedAtIndex(i)) { + counts->signedin++; + if (info_cache->BrowserStateIsAuthErrorAtIndex(i)) + counts->auth_errors++; + } + } + return true; +} + +void LogNumberOfBrowserStates(ios::ChromeBrowserStateManager* manager) { + profile_metrics::Counts counts; + CountBrowserStateInformation(manager, &counts); + profile_metrics::LogProfileMetricsCounts(counts); +}
diff --git a/ios/chrome/browser/browser_state_metrics/browser_state_metrics.h b/ios/chrome/browser/browser_state_metrics/browser_state_metrics.h new file mode 100644 index 0000000..dc3e048 --- /dev/null +++ b/ios/chrome/browser/browser_state_metrics/browser_state_metrics.h
@@ -0,0 +1,24 @@ +// Copyright 2015 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 IOS_CHROME_BROWSER_BROWSER_STATE_METRICS_BROWSER_STATE_METRICS_H_ +#define IOS_CHROME_BROWSER_BROWSER_STATE_METRICS_BROWSER_STATE_METRICS_H_ + +namespace ios { +class ChromeBrowserStateManager; +} + +namespace profile_metrics { +struct Counts; +} + +// Counts and returns summary information about the browser states currently in +// the |manager|. This information is returned in the output variable +// |counts|. Assumes that all field of |counts| are set to zero before the call. +bool CountBrowserStateInformation(ios::ChromeBrowserStateManager* manager, + profile_metrics::Counts* counts); + +void LogNumberOfBrowserStates(ios::ChromeBrowserStateManager* manager); + +#endif // IOS_CHROME_BROWSER_BROWSER_STATE_BROWSER_STATE_METRICS_H_
diff --git a/ios/chrome/browser/updatable_config/updatable_config_base.mm b/ios/chrome/browser/updatable_config/updatable_config_base.mm index 0fa0873..49a793d 100644 --- a/ios/chrome/browser/updatable_config/updatable_config_base.mm +++ b/ios/chrome/browser/updatable_config/updatable_config_base.mm
@@ -132,8 +132,8 @@ // two phases and is probably not MT safe. However, // initWithAppId:version:plist: is called from a singleton's // initialization loop and thus will not be called more than once. - // TODO(pkl): -loadDefaults accesses the file system to load in the - // plist. This should be done via PostBlockingPoolTask. + // TODO(crbug/545309): -loadDefaults accesses the file system to load in + // the plist. This should be done via PostBlockingPoolTask. [_updatableResource loadDefaults]; NSString* notificationName = ios::GetChromeBrowserProvider()
diff --git a/ios/chrome/ios_chrome.gyp b/ios/chrome/ios_chrome.gyp index e49a211c6..285c8633 100644 --- a/ios/chrome/ios_chrome.gyp +++ b/ios/chrome/ios_chrome.gyp
@@ -179,6 +179,8 @@ 'browser/browser_state/browser_state_keyed_service_factories.mm', 'browser/browser_state/browser_state_otr_helper.cc', 'browser/browser_state/browser_state_otr_helper.h', + 'browser/browser_state_metrics/browser_state_metrics.cc', + 'browser/browser_state_metrics/browser_state_metrics.h', 'browser/browsing_data_change_listening.h', 'browser/chrome_paths.h', 'browser/chrome_paths.mm',
diff --git a/ios/crnet/crnet_environment.mm b/ios/crnet/crnet_environment.mm index 2baf841..e281a7f 100644 --- a/ios/crnet/crnet_environment.mm +++ b/ios/crnet/crnet_environment.mm
@@ -462,7 +462,8 @@ // Cookies scoped_refptr<net::CookieStore> cookie_store = - net::CookieStoreIOS::CreateCookieStoreFromNSHTTPCookieStorage(); + net::CookieStoreIOS::CreateCookieStore( + [NSHTTPCookieStorage sharedHTTPCookieStorage]); main_context_->set_cookie_store(cookie_store.get()); net::URLRequestJobFactoryImpl* job_factory =
diff --git a/ios/net/cookies/cookie_store_ios.h b/ios/net/cookies/cookie_store_ios.h index ad56bb51..9b33415 100644 --- a/ios/net/cookies/cookie_store_ios.h +++ b/ios/net/cookies/cookie_store_ios.h
@@ -22,9 +22,11 @@ #if defined(__OBJC__) @class NSHTTPCookie; +@class NSHTTPCookieStorage; @class NSArray; #else class NSHTTPCookie; +class NSHTTPCookieStorage; class NSArray; #endif @@ -32,12 +34,14 @@ class CookieCreationTimeManager; -// Observer for system cookie notifications. +// Observer for changes on |NSHTTPCookieStorge sharedHTTPCookieStorage|. class CookieNotificationObserver { public: - // Called when any cookie is added, deleted or changed in the system store. + // Called when any cookie is added, deleted or changed in + // |NSHTTPCookieStorge sharedHTTPCookieStorage|. virtual void OnSystemCookiesChanged() = 0; - // Called when the cookie policy changes. + // Called when the cookie policy changes on + // |NSHTTPCookieStorge sharedHTTPCookieStorage|. virtual void OnSystemCookiePolicyChanged() = 0; }; @@ -64,27 +68,38 @@ class CookieStoreIOS : public net::CookieStore, public CookieNotificationObserver { public: + // Creates a CookieStoreIOS with a default value of + // |NSHTTPCookieStorage sharedCookieStorage| as the system's cookie store. explicit CookieStoreIOS( net::CookieMonster::PersistentCookieStore* persistent_store); + explicit CookieStoreIOS( + net::CookieMonster::PersistentCookieStore* persistent_store, + NSHTTPCookieStorage* system_store); + enum CookiePolicy { ALLOW, BLOCK }; // Must be called on the thread where CookieStoreIOS instances live. + // Affects only those CookieStoreIOS instances that are backed by + // |NSHTTPCookieStorage sharedHTTPCookieStorage|. static void SetCookiePolicy(CookiePolicy setting); // Create an instance of CookieStoreIOS that is generated from the cookies - // stored in the system NSHTTPCookieStorage. The caller is responsible for - // deleting the cookie store. - // Apple does not persist the cookies' creation dates in the system store, + // stored in |cookie_storage|. The CookieStoreIOS uses the |cookie_storage| + // as its default backend and is initially synchronized with it. + // Apple does not persist the cookies' creation dates in NSHTTPCookieStorage, // so callers should not expect these values to be populated. - static CookieStoreIOS* CreateCookieStoreFromNSHTTPCookieStorage(); + static CookieStoreIOS* CreateCookieStore(NSHTTPCookieStorage* cookie_storage); // As there is only one system store, only one CookieStoreIOS at a time may // be synchronized with it. static void SwitchSynchronizedStore(CookieStoreIOS* old_store, CookieStoreIOS* new_store); - // Must be called when the state of the system cookie store changes. + // Must be called when the state of + // |NSHTTPCookieStorage sharedHTTPCookieStorage| changes. + // Affects only those CookieStoreIOS instances that are backed by + // |NSHTTPCookieStorage sharedHTTPCookieStorage|. static void NotifySystemCookiesChanged(); // Saves the cookies to the cookie monster. @@ -175,6 +190,7 @@ const DeleteCallback& callback); scoped_refptr<net::CookieMonster> cookie_monster_; + NSHTTPCookieStorage* system_store_; scoped_ptr<CookieCreationTimeManager> creation_time_manager_; bool metrics_enabled_; base::TimeDelta flush_delay_;
diff --git a/ios/net/cookies/cookie_store_ios.mm b/ios/net/cookies/cookie_store_ios.mm index be242f8..b353fea4 100644 --- a/ios/net/cookies/cookie_store_ios.mm +++ b/ios/net/cookies/cookie_store_ios.mm
@@ -200,9 +200,9 @@ } // Gets the cookies for |url| from the system cookie store. -NSArray* GetCookiesForURL(const GURL& url, CookieCreationTimeManager* manager) { - NSArray* cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] - cookiesForURL:net::NSURLWithGURL(url)]; +NSArray* GetCookiesForURL(NSHTTPCookieStorage* system_store, + const GURL& url, CookieCreationTimeManager* manager) { + NSArray* cookies = [system_store cookiesForURL:net::NSURLWithGURL(url)]; // Sort cookies by decreasing path length, then creation time, as per RFC6265. return [cookies sortedArrayUsingFunction:CompareCookies context:manager]; @@ -274,11 +274,21 @@ CookieStoreIOS::CookieStoreIOS( net::CookieMonster::PersistentCookieStore* persistent_store) - : creation_time_manager_(new CookieCreationTimeManager), + : CookieStoreIOS(persistent_store, + [NSHTTPCookieStorage sharedHTTPCookieStorage]) { +} + +CookieStoreIOS::CookieStoreIOS( + net::CookieMonster::PersistentCookieStore* persistent_store, + NSHTTPCookieStorage* system_store) + : system_store_(system_store), + creation_time_manager_(new CookieCreationTimeManager), metrics_enabled_(false), flush_delay_(base::TimeDelta::FromSeconds(10)), synchronization_state_(NOT_SYNCHRONIZED), cookie_cache_(new CookieCache()) { + DCHECK(system_store); + NotificationTrampoline::GetInstance()->AddObserver(this); cookie_monster_ = new net::CookieMonster(persistent_store, nullptr); cookie_monster_->SetPersistSessionCookies(true); @@ -298,14 +308,16 @@ NotificationTrampoline::GetInstance()->NotifyCookiePolicyChanged(); } -CookieStoreIOS* CookieStoreIOS::CreateCookieStoreFromNSHTTPCookieStorage() { +// static +CookieStoreIOS* CookieStoreIOS::CreateCookieStore( + NSHTTPCookieStorage* cookie_storage) { + DCHECK(cookie_storage); // TODO(huey): Update this when CrNet supports multiple cookie jars. - [[NSHTTPCookieStorage sharedHTTPCookieStorage] - setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways]; + [cookie_storage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways]; // Create a cookie store with no persistent store backing. Then, populate // it from the system's cookie jar. - CookieStoreIOS* cookie_store = new CookieStoreIOS(nullptr); + CookieStoreIOS* cookie_store = new CookieStoreIOS(nullptr, cookie_storage); cookie_store->synchronization_state_ = SYNCHRONIZED; cookie_store->Flush(base::Closure()); return cookie_store; @@ -332,8 +344,7 @@ if (SystemCookiesAllowed()) { // If cookies are disabled, the system store is empty, and the cookies are // stashed on disk. Do not delete the cookies on the disk in this case. - WriteToCookieMonster( - [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]); + WriteToCookieMonster([system_store_ cookies]); } cookie_monster_->FlushStore(closure); flush_closure_.Cancel(); @@ -408,7 +419,7 @@ (!has_explicit_domain || has_valid_domain); if (success) { - [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie]; + [system_store_ setCookie:cookie]; creation_time_manager_->SetCreationTime( cookie, creation_time_manager_->MakeUniqueCreationTime(base::Time::Now())); @@ -443,7 +454,8 @@ // engine. DCHECK(!options.exclude_httponly()); - NSArray* cookies = GetCookiesForURL(url, creation_time_manager_.get()); + NSArray* cookies = GetCookiesForURL(system_store_, + url, creation_time_manager_.get()); if (!callback.is_null()) callback.Run(BuildCookieLine(cookies, options)); break; @@ -471,7 +483,8 @@ return; } - NSArray* cookies = GetCookiesForURL(url, creation_time_manager_.get()); + NSArray* cookies = GetCookiesForURL(system_store_, + url, creation_time_manager_.get()); net::CookieList cookie_list; cookie_list.reserve([cookies count]); for (NSHTTPCookie* cookie in cookies) { @@ -500,11 +513,12 @@ WrapClosure(callback))); break; case SYNCHRONIZED: - NSArray* cookies = GetCookiesForURL(url, creation_time_manager_.get()); + NSArray* cookies = GetCookiesForURL(system_store_, + url, creation_time_manager_.get()); for (NSHTTPCookie* cookie in cookies) { if ([[cookie name] isEqualToString:base::SysUTF8ToNSString(cookie_name)]) { - [[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie]; + [system_store_ deleteCookie:cookie]; creation_time_manager_->DeleteCreationTime(cookie); } } @@ -613,27 +627,29 @@ void CookieStoreIOS::ClearSystemStore() { DCHECK(thread_checker_.CalledOnValidThread()); - NSHTTPCookieStorage* cookie_storage = - [NSHTTPCookieStorage sharedHTTPCookieStorage]; base::scoped_nsobject<NSArray> copy( - [[NSArray alloc] initWithArray:[cookie_storage cookies]]); + [[NSArray alloc] initWithArray:[system_store_ cookies]]); for (NSHTTPCookie* cookie in copy.get()) - [cookie_storage deleteCookie:cookie]; - DCHECK_EQ(0u, [[cookie_storage cookies] count]); + [system_store_ deleteCookie:cookie]; + DCHECK_EQ(0u, [[system_store_ cookies] count]); creation_time_manager_->Clear(); } void CookieStoreIOS::OnSystemCookiePolicyChanged() { DCHECK(thread_checker_.CalledOnValidThread()); - if (synchronization_state_ == NOT_SYNCHRONIZED) + // If the CookieStoreIOS is not synchronized or is not backed by + // |NSHTTPCookieStorage sharedHTTPCookieStorage| this callback is irrelevant. + if (synchronization_state_ == NOT_SYNCHRONIZED || + system_store_ != [NSHTTPCookieStorage sharedHTTPCookieStorage]) { return; + } NSHTTPCookieAcceptPolicy policy = - [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookieAcceptPolicy]; + [system_store_ cookieAcceptPolicy]; if (policy == NSHTTPCookieAcceptPolicyAlways) { // If cookies are disabled, the system cookie store should be empty. - DCHECK(![[[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies] count]); + DCHECK(![[system_store_ cookies] count]); DCHECK(synchronization_state_ != SYNCHRONIZING); synchronization_state_ = SYNCHRONIZING; cookie_monster_->GetAllCookiesAsync( @@ -642,8 +658,7 @@ DCHECK_EQ(NSHTTPCookieAcceptPolicyNever, policy); // Flush() does not write the cookies to disk when they are disabled. // Explicitly copy them. - WriteToCookieMonster( - [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]); + WriteToCookieMonster([system_store_ cookies]); Flush(base::Closure()); ClearSystemStore(); if (synchronization_state_ == SYNCHRONIZING) { @@ -677,13 +692,13 @@ #endif NSHTTPCookieAcceptPolicy policy = - [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookieAcceptPolicy]; + [system_store_ cookieAcceptPolicy]; DCHECK(policy == NSHTTPCookieAcceptPolicyAlways || policy == NSHTTPCookieAcceptPolicyNever); // If cookies are disabled, the system cookie store should be empty. DCHECK(policy == NSHTTPCookieAcceptPolicyAlways || - ![[[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies] count]); + ![[system_store_ cookies] count]); // If cookies are disabled, nothing is done now, the work will be done when // cookies are re-enabled. @@ -710,7 +725,7 @@ bool CookieStoreIOS::SystemCookiesAllowed() { DCHECK(thread_checker_.CalledOnValidThread()); - return [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookieAcceptPolicy] == + return [system_store_ cookieAcceptPolicy] == NSHTTPCookieAcceptPolicyAlways; } @@ -738,7 +753,7 @@ // invalid characters. if (!system_cookie) continue; - [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:system_cookie]; + [system_store_ setCookie:system_cookie]; creation_time_manager_->SetCreationTime(system_cookie, net_cookie.CreationDate()); } @@ -783,7 +798,7 @@ const DeleteCallback& callback) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_EQ(SYNCHRONIZED, synchronization_state_); - NSArray* cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]; + NSArray* cookies = [system_store_ cookies]; // Collect the cookies to delete. base::scoped_nsobject<NSMutableArray> to_delete( @@ -796,7 +811,7 @@ // Delete them. for (NSHTTPCookie* cookie in to_delete.get()) { - [[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie]; + [system_store_ deleteCookie:cookie]; creation_time_manager_->DeleteCreationTime(cookie); } @@ -807,9 +822,12 @@ void CookieStoreIOS::OnSystemCookiesChanged() { DCHECK(thread_checker_.CalledOnValidThread()); - // If the CookieStoreIOS is not synchronized, system cookies are irrelevant. - if (synchronization_state_ != SYNCHRONIZED) + // If the CookieStoreIOS is not synchronized or is not backed by + // |NSHTTPCookieStorage sharedHTTPCookieStorage| this callback is irrelevant. + if (synchronization_state_ != SYNCHRONIZED || + system_store_ != [NSHTTPCookieStorage sharedHTTPCookieStorage]) { return; + } for (const auto& hook_map_entry : hook_map_) { std::pair<GURL, std::string> key = hook_map_entry.first; @@ -885,8 +903,7 @@ std::vector<net::CanonicalCookie>* cookies) { DCHECK(thread_checker_.CalledOnValidThread()); NSURL* url = net::NSURLWithGURL(gurl); - NSHTTPCookieStorage* storage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; - NSArray* nscookies = [storage cookiesForURL:url]; + NSArray* nscookies = [system_store_ cookiesForURL:url]; bool found_cookies = false; for (NSHTTPCookie* nscookie in nscookies) { if (nscookie.name.UTF8String == name) {
diff --git a/ios/testing/ios_testing.gyp b/ios/testing/ios_testing.gyp index 8f941f01..80f09ab 100644 --- a/ios/testing/ios_testing.gyp +++ b/ios/testing/ios_testing.gyp
@@ -22,6 +22,9 @@ 'include_dirs': [ '../..', ], + 'export_dependent_settings': [ + '../../third_party/google_toolbox_for_mac/google_toolbox_for_mac.gyp:google_toolbox_for_mac', + ], }, { # GN version: //ios/testing:ocmock_support_unittest
diff --git a/ios/web/app/web_main_loop.mm b/ios/web/app/web_main_loop.mm index fd7ddcc3..eede96b 100644 --- a/ios/web/app/web_main_loop.mm +++ b/ios/web/app/web_main_loop.mm
@@ -49,10 +49,8 @@ parts_->PreEarlyInitialization(); } -#if !defined(USE_OPENSSL) // We want to be sure to init NSPR on the main thread. crypto::EnsureNSPRInit(); -#endif // !defined(USE_OPENSSL) if (parts_) { parts_->PostEarlyInitialization(); @@ -115,11 +113,8 @@ } int WebMainLoop::CreateThreads() { - base::Thread::Options default_options; base::Thread::Options io_message_loop_options; io_message_loop_options.message_loop_type = base::MessageLoop::TYPE_IO; - base::Thread::Options ui_message_loop_options; - ui_message_loop_options.message_loop_type = base::MessageLoop::TYPE_UI; // Start threads in the order they occur in the WebThread::ID // enumeration, except for WebThread::UI which is the main @@ -129,28 +124,31 @@ for (size_t thread_id = WebThread::UI + 1; thread_id < WebThread::ID_COUNT; ++thread_id) { scoped_ptr<WebThreadImpl>* thread_to_start = nullptr; - base::Thread::Options* options = &default_options; + base::Thread::Options options; switch (thread_id) { // TODO(rohitrao): We probably do not need all of these threads. Remove // the ones that serve no purpose. http://crbug.com/365909 case WebThread::DB: thread_to_start = &db_thread_; + options.timer_slack = base::TIMER_SLACK_MAXIMUM; break; case WebThread::FILE_USER_BLOCKING: thread_to_start = &file_user_blocking_thread_; break; case WebThread::FILE: thread_to_start = &file_thread_; - options = &io_message_loop_options; + options = io_message_loop_options; + options.timer_slack = base::TIMER_SLACK_MAXIMUM; break; case WebThread::CACHE: thread_to_start = &cache_thread_; - options = &io_message_loop_options; + options = io_message_loop_options; + options.timer_slack = base::TIMER_SLACK_MAXIMUM; break; case WebThread::IO: thread_to_start = &io_thread_; - options = &io_message_loop_options; + options = io_message_loop_options; break; case WebThread::UI: case WebThread::ID_COUNT: @@ -163,7 +161,7 @@ if (thread_to_start) { (*thread_to_start).reset(new WebThreadImpl(id)); - (*thread_to_start)->StartWithOptions(*options); + (*thread_to_start)->StartWithOptions(options); } else { NOTREACHED(); }
diff --git a/ios/web/app/web_main_runner.mm b/ios/web/app/web_main_runner.mm index 6563881..fb47d5f 100644 --- a/ios/web/app/web_main_runner.mm +++ b/ios/web/app/web_main_runner.mm
@@ -51,10 +51,6 @@ if (!GetWebClient()) SetWebClient(&empty_web_client_); -#if defined(USE_NSS) - crypto::EarlySetupForNSSInit(); -#endif - // TODO(rohitrao): Desktop calls content::RegisterContentSchemes(true) here. // Do we need similar scheme registration on iOS? ui::RegisterPathProvider();
diff --git a/ipc/ipc_channel.h b/ipc/ipc_channel.h index 142f3d59..5345112 100644 --- a/ipc/ipc_channel.h +++ b/ipc/ipc_channel.h
@@ -97,6 +97,11 @@ // Amount of data to read at once from the pipe. static const size_t kReadBufferSize = 4 * 1024; + // Maximum persistent read buffer size. Read buffer can grow larger to + // accommodate large messages, but it's recommended to shrink back to this + // value because it fits 99.9% of all messages (see issue 529940 for data). + static const size_t kMaximumReadBufferSize = 64 * 1024; + // Initialize a Channel. // // |channel_handle| identifies the communication Channel. For POSIX, if
diff --git a/ipc/ipc_channel_reader.cc b/ipc/ipc_channel_reader.cc index a82093e8..335852f 100644 --- a/ipc/ipc_channel_reader.cc +++ b/ipc/ipc_channel_reader.cc
@@ -15,7 +15,9 @@ namespace IPC { namespace internal { -ChannelReader::ChannelReader(Listener* listener) : listener_(listener) { +ChannelReader::ChannelReader(Listener* listener) + : listener_(listener), + max_input_buffer_size_(Channel::kMaximumReadBufferSize) { memset(input_buf_, 0, sizeof(input_buf_)); } @@ -114,6 +116,11 @@ } } + // Account for the case where last message's byte is in the next data chunk. + size_t next_message_buffer_size = next_message_size ? + next_message_size + Channel::kReadBufferSize - 1: + 0; + // Save any partial data in the overflow buffer. input_overflow_buf_.assign(p, end - p); @@ -122,12 +129,30 @@ // append the next data chunk (instead of parsing it directly). So we // resize the buffer to fit the next message, to avoid repeatedly // growing the buffer as we receive all message' data chunks. - next_message_size += Channel::kReadBufferSize - 1; - if (next_message_size > input_overflow_buf_.capacity()) { - input_overflow_buf_.reserve(next_message_size); + if (next_message_buffer_size > input_overflow_buf_.capacity()) { + input_overflow_buf_.reserve(next_message_buffer_size); } } + // Trim the buffer if we can + if (next_message_buffer_size < max_input_buffer_size_ && + input_overflow_buf_.size() < max_input_buffer_size_ && + input_overflow_buf_.capacity() > max_input_buffer_size_) { + // std::string doesn't really have a method to shrink capacity to + // a specific value, so we have to swap with another string. + std::string trimmed_buf; + trimmed_buf.reserve(max_input_buffer_size_); + if (trimmed_buf.capacity() > max_input_buffer_size_) { + // Since we don't control how much space reserve() actually reserves, + // we have to go other way around and change the max size to avoid + // getting into the outer if() again. + max_input_buffer_size_ = trimmed_buf.capacity(); + } + trimmed_buf.assign(input_overflow_buf_.data(), + input_overflow_buf_.size()); + input_overflow_buf_.swap(trimmed_buf); + } + if (input_overflow_buf_.empty() && !DidEmptyInputBuffers()) return false; return true;
diff --git a/ipc/ipc_channel_reader.h b/ipc/ipc_channel_reader.h index 8e2fcba..352bfa5 100644 --- a/ipc/ipc_channel_reader.h +++ b/ipc/ipc_channel_reader.h
@@ -129,6 +129,7 @@ FRIEND_TEST_ALL_PREFIXES(ChannelReaderTest, AttachmentNotYetBrokered); FRIEND_TEST_ALL_PREFIXES(ChannelReaderTest, ResizeOverflowBuffer); FRIEND_TEST_ALL_PREFIXES(ChannelReaderTest, InvalidMessageSize); + FRIEND_TEST_ALL_PREFIXES(ChannelReaderTest, TrimBuffer); using AttachmentIdSet = std::set<BrokerableAttachment::AttachmentId>; using AttachmentIdVector = std::vector<BrokerableAttachment::AttachmentId>; @@ -195,6 +196,11 @@ // this buffer. std::string input_overflow_buf_; + // Maximum overflow buffer size, see Channel::kMaximumReadBufferSize. + // This is not a constant because we update it to reflect the reality + // of std::string::reserve() implementation. + size_t max_input_buffer_size_; + // These messages are waiting to be dispatched. If this vector is non-empty, // then the front Message must be blocked on receiving an attachment from the // AttachmentBroker.
diff --git a/ipc/ipc_channel_reader_unittest.cc b/ipc/ipc_channel_reader_unittest.cc index fdf3144..f49c275 100644 --- a/ipc/ipc_channel_reader_unittest.cc +++ b/ipc/ipc_channel_reader_unittest.cc
@@ -13,6 +13,14 @@ #include "ipc/placeholder_brokerable_attachment.h" #include "testing/gtest/include/gtest/gtest.h" +// Whether IPC::Message::FindNext() can determine message size for +// partial messages. The condition is from FindNext() implementation. +#if USE_ATTACHMENT_BROKER && defined(OS_MACOSX) && !defined(OS_IOS) +#define MESSAGE_FINDNEXT_PARTIAL 0 +#else +#define MESSAGE_FINDNEXT_PARTIAL 1 +#endif + namespace IPC { namespace internal { @@ -64,7 +72,14 @@ : ChannelReader(nullptr), last_dispatched_message_(nullptr) {} ReadState ReadData(char* buffer, int buffer_len, int* bytes_read) override { - return READ_FAILED; + if (data_.empty()) + return READ_PENDING; + + size_t read_len = std::min(static_cast<size_t>(buffer_len), data_.size()); + memcpy(buffer, data_.data(), read_len); + *bytes_read = static_cast<int>(read_len); + data_.erase(0, read_len); + return READ_SUCCEEDED; } bool ShouldDispatchInputMessage(Message* msg) override { return true; } @@ -92,9 +107,18 @@ void set_broker(AttachmentBroker* broker) { broker_ = broker; } + void AppendData(const void* data, size_t size) { + data_.append(static_cast<const char*>(data), size); + } + + void AppendMessageData(const Message& message) { + AppendData(message.data(), message.size()); + } + private: Message* last_dispatched_message_; AttachmentBroker* broker_; + std::string data_; }; class ExposedMessage: public Message { @@ -103,6 +127,9 @@ using Message::header; }; +// Payload that makes messages large +const size_t LargePayloadSize = Channel::kMaximumReadBufferSize * 3 / 2; + } // namespace #if USE_ATTACHMENT_BROKER @@ -192,5 +219,155 @@ #endif // !USE_ATTACHMENT_BROKER +TEST(ChannelReaderTest, TrimBuffer) { + // ChannelReader uses std::string as a buffer, and calls reserve() + // to trim it to kMaximumReadBufferSize. However, an implementation + // is free to actually reserve a larger amount. + size_t trimmed_buffer_size; + { + std::string buf; + buf.reserve(Channel::kMaximumReadBufferSize); + trimmed_buffer_size = buf.capacity(); + } + + // Buffer is trimmed after message is processed. + { + MockChannelReader reader; + + Message message; + message.WriteString(std::string(LargePayloadSize, 'X')); + + // Sanity check + EXPECT_TRUE(message.size() > trimmed_buffer_size); + + // Initially buffer is small + EXPECT_LE(reader.input_overflow_buf_.capacity(), trimmed_buffer_size); + + // Write and process large message + reader.AppendMessageData(message); + EXPECT_EQ(ChannelReader::DISPATCH_FINISHED, + reader.ProcessIncomingMessages()); + + // After processing large message buffer is trimmed + EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size); + } + + // Buffer is trimmed only after entire message is processed. + { + MockChannelReader reader; + + ExposedMessage message; + message.WriteString(std::string(LargePayloadSize, 'X')); + + // Write and process message header + reader.AppendData(message.header(), sizeof(ExposedMessage::Header)); + EXPECT_EQ(ChannelReader::DISPATCH_FINISHED, + reader.ProcessIncomingMessages()); + +#if MESSAGE_FINDNEXT_PARTIAL + // We determined message size for the message from its header, so + // we resized the buffer to fit. + EXPECT_GE(reader.input_overflow_buf_.capacity(), message.size()); +#else + // We couldn't determine message size, so we didn't resize the buffer. +#endif + + // Write and process payload + reader.AppendData(message.payload(), message.payload_size()); + EXPECT_EQ(ChannelReader::DISPATCH_FINISHED, + reader.ProcessIncomingMessages()); + + // But once we process the message, we trim the buffer + EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size); + } + + // Buffer is not trimmed if the next message is also large. + { + MockChannelReader reader; + + // Write large message + Message message1; + message1.WriteString(std::string(LargePayloadSize * 2, 'X')); + reader.AppendMessageData(message1); + + // Write header for the next large message + ExposedMessage message2; + message2.WriteString(std::string(LargePayloadSize, 'Y')); + reader.AppendData(message2.header(), sizeof(ExposedMessage::Header)); + + // Process messages + EXPECT_EQ(ChannelReader::DISPATCH_FINISHED, + reader.ProcessIncomingMessages()); + +#if MESSAGE_FINDNEXT_PARTIAL + // We determined message size for the second (partial) message, so + // we resized the buffer to fit. + EXPECT_GE(reader.input_overflow_buf_.capacity(), message1.size()); +#else + // We couldn't determine message size for the second (partial) message, + // so we trimmed the buffer. + EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size); +#endif + } + + // Buffer resized appropriately if next message is larger than the first. + // (Similar to the test above except for the order of messages.) + { + MockChannelReader reader; + + // Write large message + Message message1; + message1.WriteString(std::string(LargePayloadSize, 'Y')); + reader.AppendMessageData(message1); + + // Write header for the next even larger message + ExposedMessage message2; + message2.WriteString(std::string(LargePayloadSize * 2, 'X')); + reader.AppendData(message2.header(), sizeof(ExposedMessage::Header)); + + // Process messages + EXPECT_EQ(ChannelReader::DISPATCH_FINISHED, + reader.ProcessIncomingMessages()); + +#if MESSAGE_FINDNEXT_PARTIAL + // We determined message size for the second (partial) message, and + // resized the buffer to fit it. + EXPECT_GE(reader.input_overflow_buf_.capacity(), message2.size()); +#else + // We couldn't determine message size for the second (partial) message, + // so we trimmed the buffer. + EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size); +#endif + } + + // Buffer is not trimmed if we've just resized it to accommodate large + // incoming message. + { + MockChannelReader reader; + + // Write small message + Message message1; + message1.WriteString(std::string(11, 'X')); + reader.AppendMessageData(message1); + + // Write header for the next large message + ExposedMessage message2; + message2.WriteString(std::string(LargePayloadSize, 'Y')); + reader.AppendData(message2.header(), sizeof(ExposedMessage::Header)); + + EXPECT_EQ(ChannelReader::DISPATCH_FINISHED, + reader.ProcessIncomingMessages()); + +#if MESSAGE_FINDNEXT_PARTIAL + // We determined message size for the second (partial) message, so + // we resized the buffer to fit. + EXPECT_GE(reader.input_overflow_buf_.capacity(), message2.size()); +#else + // We couldn't determine size for the second (partial) message, and + // first message was small, so we did nothing. +#endif + } +} + } // namespace internal } // namespace IPC
diff --git a/ipc/ipc_sync_channel.cc b/ipc/ipc_sync_channel.cc index 89dd7d7..caf504da6 100644 --- a/ipc/ipc_sync_channel.cc +++ b/ipc/ipc_sync_channel.cc
@@ -305,15 +305,13 @@ return false; } - // TODO(bauerb): Remove logging once investigation of http://crbug.com/141055 - // has finished. if (!msg->is_reply_error()) { bool send_result = deserializers_.back().deserializer-> SerializeOutputParameters(*msg); deserializers_.back().send_result = send_result; - VLOG_IF(1, !send_result) << "Couldn't deserialize reply message"; + DVLOG_IF(1, !send_result) << "Couldn't deserialize reply message"; } else { - VLOG(1) << "Received error reply"; + DVLOG(1) << "Received error reply"; } deserializers_.back().done_event->Signal(); @@ -370,7 +368,7 @@ void SyncChannel::SyncContext::OnSendTimeout(int message_id) { base::AutoLock auto_lock(deserializers_lock_); PendingSyncMessageQueue::iterator iter; - VLOG(1) << "Send timeout"; + DVLOG(1) << "Send timeout"; for (iter = deserializers_.begin(); iter != deserializers_.end(); iter++) { if (iter->id == message_id) { iter->done_event->Signal(); @@ -382,8 +380,7 @@ void SyncChannel::SyncContext::CancelPendingSends() { base::AutoLock auto_lock(deserializers_lock_); PendingSyncMessageQueue::iterator iter; - // TODO(bauerb): Remove once http://crbug/141055 is fixed. - VLOG(1) << "Canceling pending sends"; + DVLOG(1) << "Canceling pending sends"; for (iter = deserializers_.begin(); iter != deserializers_.end(); iter++) iter->done_event->Signal(); } @@ -487,7 +484,7 @@ // *this* might get deleted in WaitForReply. scoped_refptr<SyncContext> context(sync_context()); if (context->shutdown_event()->IsSignaled()) { - VLOG(1) << "shutdown event is signaled"; + DVLOG(1) << "shutdown event is signaled"; delete message; return false; }
diff --git a/mandoline/app/desktop/main.cc b/mandoline/app/desktop/main.cc index a1e26aa..d0a7a99 100644 --- a/mandoline/app/desktop/main.cc +++ b/mandoline/app/desktop/main.cc
@@ -4,6 +4,8 @@ #include "base/at_exit.h" #include "base/command_line.h" +#include "base/debug/stack_trace.h" +#include "base/process/launch.h" #include "mandoline/app/desktop/launcher_process.h" #include "mojo/runner/child_process.h" #include "mojo/runner/init.h" @@ -18,6 +20,13 @@ mojo::runner::InitializeLogging(); mojo::runner::WaitForDebuggerIfNecessary(); +#if !defined(OFFICIAL_BUILD) + base::debug::EnableInProcessStackDumping(); +#if defined(OS_WIN) + base::RouteStdioToConsole(false); +#endif +#endif + if (command_line.HasSwitch(switches::kChildProcess)) return mojo::runner::ChildProcessMain();
diff --git a/media/BUILD.gn b/media/BUILD.gn index f15e5903..52af493 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn
@@ -791,6 +791,7 @@ "//testing/gtest", "//testing/perf", "//third_party/widevine/cdm:version_h", + "//third_party/libyuv", "//ui/gfx:test_support", ] if (is_android) {
diff --git a/media/audio/mac/audio_low_latency_input_mac.cc b/media/audio/mac/audio_low_latency_input_mac.cc index a9386d37..9be0a97f 100644 --- a/media/audio/mac/audio_low_latency_input_mac.cc +++ b/media/audio/mac/audio_low_latency_input_mac.cc
@@ -149,7 +149,8 @@ 1, // input element 1 &enableIO, // enable sizeof(enableIO)); - if (result) { + if (result != noErr) { + CloseAudioUnit(); HandleError(result); return false; } @@ -162,7 +163,8 @@ 0, // output element 0 &enableIO, // disable sizeof(enableIO)); - if (result) { + if (result != noErr) { + CloseAudioUnit(); HandleError(result); return false; } @@ -175,7 +177,8 @@ 0, &input_device_id_, sizeof(input_device_id_)); - if (result) { + if (result != noErr) { + CloseAudioUnit(); HandleError(result); return false; } @@ -189,14 +192,17 @@ 1, &format_, sizeof(format_)); - if (result) { + if (result != noErr) { + CloseAudioUnit(); HandleError(result); return false; } - if (!manager_->MaybeChangeBufferSize( - input_device_id_, audio_unit_, 1, number_of_frames_)) + if (!manager_->MaybeChangeBufferSize(input_device_id_, audio_unit_, 1, + number_of_frames_)) { + CloseAudioUnit(); return false; + } // Register the input procedure for the AUHAL. // This procedure will be called when the AUHAL has received new data @@ -210,7 +216,8 @@ 0, &callback, sizeof(callback)); - if (result) { + if (result != noErr) { + CloseAudioUnit(); HandleError(result); return false; } @@ -219,7 +226,8 @@ // Allocates memory according to the maximum number of audio frames // it can produce in response to a single render call. result = AudioUnitInitialize(audio_unit_); - if (result) { + if (result != noErr) { + CloseAudioUnit(); HandleError(result); return false; } @@ -299,19 +307,7 @@ if (started_) { Stop(); } - if (audio_unit_) { - // Deallocate the audio unit’s resources. - OSStatus result = AudioUnitUninitialize(audio_unit_); - OSSTATUS_DLOG_IF(ERROR, result != noErr, result) - << "AudioUnitUninitialize() failed."; - - result = AudioComponentInstanceDispose(audio_unit_); - OSSTATUS_DLOG_IF(ERROR, result != noErr, result) - << "AudioComponentInstanceDispose() failed."; - - audio_unit_ = 0; - } - + CloseAudioUnit(); // Inform the audio manager that we have been closed. This can cause our // destruction. manager_->ReleaseInputStream(this); @@ -775,4 +771,17 @@ } } +void AUAudioInputStream::CloseAudioUnit() { + DCHECK(thread_checker_.CalledOnValidThread()); + if (!audio_unit_) + return; + OSStatus result = AudioUnitUninitialize(audio_unit_); + OSSTATUS_DLOG_IF(ERROR, result != noErr, result) + << "AudioUnitUninitialize() failed."; + result = AudioComponentInstanceDispose(audio_unit_); + OSSTATUS_DLOG_IF(ERROR, result != noErr, result) + << "AudioComponentInstanceDispose() failed."; + audio_unit_ = 0; +} + } // namespace media
diff --git a/media/audio/mac/audio_low_latency_input_mac.h b/media/audio/mac/audio_low_latency_input_mac.h index e1d14b33..fe6907c5 100644 --- a/media/audio/mac/audio_low_latency_input_mac.h +++ b/media/audio/mac/audio_low_latency_input_mac.h
@@ -126,6 +126,9 @@ // expires 5 seconds after calling Start(). void CheckInputStartupSuccess(); + // Uninitializes the audio unit if needed. + void CloseAudioUnit(); + // Verifies that Open(), Start(), Stop() and Close() are all called on the // creating thread which is the main browser thread (CrBrowserMain) on Mac. base::ThreadChecker thread_checker_;
diff --git a/media/base/android/media_drm_bridge.cc b/media/base/android/media_drm_bridge.cc index 47822bf..196672c 100644 --- a/media/base/android/media_drm_bridge.cc +++ b/media/base/android/media_drm_bridge.cc
@@ -410,11 +410,6 @@ promise->reject(NOT_SUPPORTED_ERROR, 0, "RemoveSession() is not supported."); } -CdmContext* MediaDrmBridge::GetCdmContext() { - NOTREACHED(); - return nullptr; -} - void MediaDrmBridge::DeleteOnCorrectThread() const { DVLOG(1) << __FUNCTION__;
diff --git a/media/base/android/media_drm_bridge.h b/media/base/android/media_drm_bridge.h index 90aec56..ac737581 100644 --- a/media/base/android/media_drm_bridge.h +++ b/media/base/android/media_drm_bridge.h
@@ -108,7 +108,6 @@ scoped_ptr<media::SimpleCdmPromise> promise) override; void RemoveSession(const std::string& session_id, scoped_ptr<media::SimpleCdmPromise> promise) override; - CdmContext* GetCdmContext() override; void DeleteOnCorrectThread() const override; // PlayerTracker implementation. Can be called on any thread.
diff --git a/media/base/media_keys.cc b/media/base/media_keys.cc index 03e7acf..103703ec 100644 --- a/media/base/media_keys.cc +++ b/media/base/media_keys.cc
@@ -10,6 +10,10 @@ MediaKeys::~MediaKeys() {} +CdmContext* MediaKeys::GetCdmContext() { + return nullptr; +} + void MediaKeys::DeleteOnCorrectThread() const { delete this; }
diff --git a/media/base/media_keys.h b/media/base/media_keys.h index a84cdf72..71d73e4e 100644 --- a/media/base/media_keys.h +++ b/media/base/media_keys.h
@@ -156,10 +156,13 @@ virtual void RemoveSession(const std::string& session_id, scoped_ptr<SimpleCdmPromise> promise) = 0; - // Returns the CdmContext associated with |this|, which must NOT be null. - // Usually the CdmContext is owned by |this|. Caller needs to make sure it is - // not used after |this| is destructed. - virtual CdmContext* GetCdmContext() = 0; + // Returns the CdmContext associated with |this| if Decryptor or CDM ID is + // supported. The returned CdmContext is owned by |this|. Caller needs to make + // sure it is not used after |this| is destructed. + // Returns null if no Decryptor nor CDM ID is supported. Instead the media + // player may use the CDM via some platform specific method. + // By default this method returns null. + virtual CdmContext* GetCdmContext(); // Deletes |this| on the correct thread. By default |this| is deleted // immediately. Override this method if |this| needs to be deleted on a
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc index a4824f86..f73d5ac 100644 --- a/media/base/video_frame.cc +++ b/media/base/video_frame.cc
@@ -5,6 +5,7 @@ #include "media/base/video_frame.h" #include <algorithm> +#include <climits> #include "base/bind.h" #include "base/callback_helpers.h" @@ -163,13 +164,15 @@ const gfx::Rect& visible_rect, const gfx::Size& natural_size) { // Check maximum limits for all formats. - if (coded_size.GetArea() > limits::kMaxCanvas || + int coded_size_area = coded_size.GetCheckedArea().ValueOrDefault(INT_MAX); + int natural_size_area = natural_size.GetCheckedArea().ValueOrDefault(INT_MAX); + static_assert(limits::kMaxCanvas < INT_MAX, ""); + if (coded_size_area > limits::kMaxCanvas || coded_size.width() > limits::kMaxDimension || - coded_size.height() > limits::kMaxDimension || - visible_rect.x() < 0 || visible_rect.y() < 0 || - visible_rect.right() > coded_size.width() || + coded_size.height() > limits::kMaxDimension || visible_rect.x() < 0 || + visible_rect.y() < 0 || visible_rect.right() > coded_size.width() || visible_rect.bottom() > coded_size.height() || - natural_size.GetArea() > limits::kMaxCanvas || + natural_size_area > limits::kMaxCanvas || natural_size.width() > limits::kMaxDimension || natural_size.height() > limits::kMaxDimension) return false; @@ -802,15 +805,15 @@ done_callbacks_.push_back(callback); } -void VideoFrame::UpdateReleaseSyncPoint(SyncPointClient* client) { +void VideoFrame::UpdateReleaseSyncToken(SyncTokenClient* client) { DCHECK(HasTextures()); - base::AutoLock locker(release_sync_point_lock_); + base::AutoLock locker(release_sync_token_lock_); // Must wait on the previous sync point before inserting a new sync point so // that |mailbox_holders_release_cb_| guarantees the previous sync point - // occurred when it waits on |release_sync_point_|. - if (release_sync_point_) - client->WaitSyncPoint(release_sync_point_); - release_sync_point_ = client->InsertSyncPoint(); + // occurred when it waits on |release_sync_token_|. + if (release_sync_token_.HasData()) + client->WaitSyncToken(release_sync_token_); + release_sync_token_ = gpu::SyncToken(client->InsertSyncPoint()); } // static @@ -871,8 +874,7 @@ natural_size_(natural_size), shared_memory_handle_(base::SharedMemory::NULLHandle()), shared_memory_offset_(0), - timestamp_(timestamp), - release_sync_point_(0) { + timestamp_(timestamp) { DCHECK(IsValidConfig(format_, storage_type, coded_size_, visible_rect_, natural_size_)); memset(&mailbox_holders_, 0, sizeof(mailbox_holders_)); @@ -919,14 +921,14 @@ VideoFrame::~VideoFrame() { if (!mailbox_holders_release_cb_.is_null()) { - uint32 release_sync_point; + gpu::SyncToken release_sync_token; { - // To ensure that changes to |release_sync_point_| are visible on this + // To ensure that changes to |release_sync_token_| are visible on this // thread (imply a memory barrier). - base::AutoLock locker(release_sync_point_lock_); - release_sync_point = release_sync_point_; + base::AutoLock locker(release_sync_token_lock_); + release_sync_token = release_sync_token_; } - base::ResetAndReturn(&mailbox_holders_release_cb_).Run(release_sync_point); + base::ResetAndReturn(&mailbox_holders_release_cb_).Run(release_sync_token); } for (auto& callback : done_callbacks_)
diff --git a/media/base/video_frame.h b/media/base/video_frame.h index e5ca2e3..717649e 100644 --- a/media/base/video_frame.h +++ b/media/base/video_frame.h
@@ -8,6 +8,7 @@ #include <vector> #include "base/callback.h" +#include "base/macros.h" #include "base/md5.h" #include "base/memory/shared_memory.h" #include "base/synchronization/lock.h" @@ -72,20 +73,20 @@ // CB to be called on the mailbox backing this frame when the frame is // destroyed. - typedef base::Callback<void(uint32)> ReleaseMailboxCB; + typedef base::Callback<void(const gpu::SyncToken&)> ReleaseMailboxCB; - // Interface representing client operations on a SyncPoint, i.e. insert one in + // Interface representing client operations on a SyncToken, i.e. insert one in // the GPU Command Buffer and wait for it. - class SyncPointClient { + class SyncTokenClient { public: - SyncPointClient() {} + SyncTokenClient() {} virtual uint32 InsertSyncPoint() = 0; - virtual void WaitSyncPoint(uint32 sync_point) = 0; + virtual void WaitSyncToken(const gpu::SyncToken& sync_token) = 0; protected: - virtual ~SyncPointClient() {} + virtual ~SyncTokenClient() {} - DISALLOW_COPY_AND_ASSIGN(SyncPointClient); + DISALLOW_COPY_AND_ASSIGN(SyncTokenClient); }; // Call prior to CreateFrame to ensure validity of frame configuration. Called @@ -119,7 +120,7 @@ // Wraps a native texture of the given parameters with a VideoFrame. // The backing of the VideoFrame is held in the mailbox held by // |mailbox_holder|, and |mailbox_holder_release_cb| will be called with - // a syncpoint as the argument when the VideoFrame is to be destroyed. + // a sync token as the argument when the VideoFrame is to be destroyed. static scoped_refptr<VideoFrame> WrapNativeTexture( VideoPixelFormat format, const gpu::MailboxHolder& mailbox_holder, @@ -130,7 +131,7 @@ base::TimeDelta timestamp); // Wraps a set of native textures representing YUV data with a VideoFrame. - // |mailbox_holders_release_cb| will be called with a syncpoint as the + // |mailbox_holders_release_cb| will be called with a sync token as the // argument when the VideoFrame is to be destroyed. static scoped_refptr<VideoFrame> WrapYUV420NativeTextures( const gpu::MailboxHolder& y_mailbox_holder, @@ -401,7 +402,7 @@ // older sync point. The final sync point will be used to release this // VideoFrame. // This method is thread safe. Both blink and compositor threads can call it. - void UpdateReleaseSyncPoint(SyncPointClient* client); + void UpdateReleaseSyncToken(SyncTokenClient* client); private: friend class base::RefCountedThreadSafe<VideoFrame>; @@ -511,8 +512,8 @@ base::TimeDelta timestamp_; - base::Lock release_sync_point_lock_; - uint32 release_sync_point_; + base::Lock release_sync_token_lock_; + gpu::SyncToken release_sync_token_; VideoFrameMetadata metadata_;
diff --git a/media/base/video_frame_pool.cc b/media/base/video_frame_pool.cc index dc9cdf3..52af8ece 100644 --- a/media/base/video_frame_pool.cc +++ b/media/base/video_frame_pool.cc
@@ -80,6 +80,7 @@ if (!frame.get()) { frame = VideoFrame::CreateZeroInitializedFrame( format, coded_size, visible_rect, natural_size, timestamp); + LOG_IF(ERROR, !frame.get()) << "Failed to create a video frame"; } scoped_refptr<VideoFrame> wrapped_frame = VideoFrame::WrapVideoFrame(
diff --git a/media/base/video_frame_unittest.cc b/media/base/video_frame_unittest.cc index 879be7d..c9f05ec 100644 --- a/media/base/video_frame_unittest.cc +++ b/media/base/video_frame_unittest.cc
@@ -261,21 +261,21 @@ ExpectFrameExtents(PIXEL_FORMAT_YV16, "cce408a044b212db42a10dfec304b3ef"); } -static void TextureCallback(uint32* called_sync_point, - uint32 release_sync_point) { - *called_sync_point = release_sync_point; +static void TextureCallback(gpu::SyncToken* called_sync_token, + const gpu::SyncToken& release_sync_token) { + *called_sync_token = release_sync_token; } // Verify the gpu::MailboxHolder::ReleaseCallback is called when VideoFrame is // destroyed with the default release sync point. TEST(VideoFrame, TextureNoLongerNeededCallbackIsCalled) { - uint32 called_sync_point = 1; + gpu::SyncToken called_sync_token(1); { scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTexture( PIXEL_FORMAT_ARGB, - gpu::MailboxHolder(gpu::Mailbox::Generate(), 5, 0 /* sync_point */), - base::Bind(&TextureCallback, &called_sync_point), + gpu::MailboxHolder(gpu::Mailbox::Generate(), gpu::SyncToken(), 5), + base::Bind(&TextureCallback, &called_sync_token), gfx::Size(10, 10), // coded_size gfx::Rect(10, 10), // visible_rect gfx::Size(10, 10), // natural_size @@ -284,22 +284,25 @@ EXPECT_EQ(VideoFrame::STORAGE_OPAQUE, frame->storage_type()); EXPECT_TRUE(frame->HasTextures()); } - // Nobody set a sync point to |frame|, so |frame| set |called_sync_point| to 0 - // as default value. - EXPECT_EQ(0u, called_sync_point); + // Nobody set a sync point to |frame|, so |frame| set |called_sync_token| + // cleared to default value. + EXPECT_FALSE(called_sync_token.HasData()); } namespace { -class SyncPointClientImpl : public VideoFrame::SyncPointClient { +class SyncTokenClientImpl : public VideoFrame::SyncTokenClient { public: - explicit SyncPointClientImpl(uint32 sync_point) : sync_point_(sync_point) {} - ~SyncPointClientImpl() override {} - uint32 InsertSyncPoint() override { return sync_point_; } - void WaitSyncPoint(uint32 sync_point) override {} + explicit SyncTokenClientImpl(const gpu::SyncToken& sync_token) + : sync_token_(sync_token) {} + ~SyncTokenClientImpl() override {} + uint32 InsertSyncPoint() override { + return static_cast<uint32>(sync_token_.release_count()); + } + void WaitSyncToken(const gpu::SyncToken& sync_token) override {} private: - uint32 sync_point_; + gpu::SyncToken sync_token_; }; } // namespace @@ -315,20 +318,20 @@ mailbox[i].name[0] = 50 + 1; } - uint32 sync_point = 7; + gpu::SyncToken sync_token(7); uint32 target = 9; - uint32 release_sync_point = 111; - uint32 called_sync_point = 0; + gpu::SyncToken release_sync_token(111); + gpu::SyncToken called_sync_token; { scoped_refptr<VideoFrame> frame = VideoFrame::WrapYUV420NativeTextures( - gpu::MailboxHolder(mailbox[VideoFrame::kYPlane], target, sync_point), - gpu::MailboxHolder(mailbox[VideoFrame::kUPlane], target, sync_point), - gpu::MailboxHolder(mailbox[VideoFrame::kVPlane], target, sync_point), - base::Bind(&TextureCallback, &called_sync_point), - gfx::Size(10, 10), // coded_size - gfx::Rect(10, 10), // visible_rect - gfx::Size(10, 10), // natural_size - base::TimeDelta()); // timestamp + gpu::MailboxHolder(mailbox[VideoFrame::kYPlane], sync_token, target), + gpu::MailboxHolder(mailbox[VideoFrame::kUPlane], sync_token, target), + gpu::MailboxHolder(mailbox[VideoFrame::kVPlane], sync_token, target), + base::Bind(&TextureCallback, &called_sync_token), + gfx::Size(10, 10), // coded_size + gfx::Rect(10, 10), // visible_rect + gfx::Size(10, 10), // natural_size + base::TimeDelta()); // timestamp EXPECT_EQ(VideoFrame::STORAGE_OPAQUE, frame->storage_type()); EXPECT_EQ(PIXEL_FORMAT_I420, frame->format()); @@ -338,15 +341,15 @@ const gpu::MailboxHolder& mailbox_holder = frame->mailbox_holder(i); EXPECT_EQ(mailbox[i].name[0], mailbox_holder.mailbox.name[0]); EXPECT_EQ(target, mailbox_holder.texture_target); - EXPECT_EQ(sync_point, mailbox_holder.sync_point); + EXPECT_EQ(sync_token, mailbox_holder.sync_token); } - SyncPointClientImpl client(release_sync_point); - frame->UpdateReleaseSyncPoint(&client); - EXPECT_EQ(sync_point, - frame->mailbox_holder(VideoFrame::kYPlane).sync_point); + SyncTokenClientImpl client(release_sync_token); + frame->UpdateReleaseSyncToken(&client); + EXPECT_EQ(sync_token, + frame->mailbox_holder(VideoFrame::kYPlane).sync_token); } - EXPECT_EQ(release_sync_point, called_sync_point); + EXPECT_EQ(release_sync_token, called_sync_token); } TEST(VideoFrame, IsValidConfig_OddCodedSize) {
diff --git a/media/base/yuv_convert_perftest.cc b/media/base/yuv_convert_perftest.cc index d676e4e..81d69ee 100644 --- a/media/base/yuv_convert_perftest.cc +++ b/media/base/yuv_convert_perftest.cc
@@ -12,6 +12,7 @@ #include "media/base/yuv_convert.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/perf/perf_test.h" +#include "third_party/libyuv/include/libyuv/row.h" namespace media { #if !defined(ARCH_CPU_ARM_FAMILY) && !defined(ARCH_CPU_MIPS_FAMILY) @@ -87,6 +88,73 @@ kPerfTestIterations / total_time_seconds, "runs/s", true); } +#ifdef HAS_I422TOARGBROW_SSSE3 +TEST_F(YUVConvertPerfTest, I422ToARGBRow_SSSE3) { + ASSERT_TRUE(base::CPU().has_ssse3()); + + base::TimeTicks start = base::TimeTicks::Now(); + for (int i = 0; i < kPerfTestIterations; ++i) { + for (int row = 0; row < kSourceHeight; ++row) { + int chroma_row = row / 2; + libyuv::I422ToARGBRow_SSSE3( + yuv_bytes_.get() + row * kSourceWidth, + yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2), + yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2), + rgb_bytes_converted_.get(), &libyuv::kYuvIConstants, kWidth); + } + } + double total_time_seconds = (base::TimeTicks::Now() - start).InSecondsF(); + perf_test::PrintResult("yuv_convert_perftest", "", "I422ToARGBRow_SSSE3", + kPerfTestIterations / total_time_seconds, "runs/s", + true); +} +#endif + +TEST_F(YUVConvertPerfTest, ConvertYUVAToARGBRow_MMX) { + ASSERT_TRUE(base::CPU().has_sse()); + + base::TimeTicks start = base::TimeTicks::Now(); + for (int i = 0; i < kPerfTestIterations; ++i) { + for (int row = 0; row < kSourceHeight; ++row) { + int chroma_row = row / 2; + ConvertYUVAToARGBRow_MMX( + yuv_bytes_.get() + row * kSourceWidth, + yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2), + yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2), + yuv_bytes_.get() + row * kSourceWidth, // hack: use luma for alpha + rgb_bytes_converted_.get(), kWidth, GetLookupTable(YV12)); + } + } + media::EmptyRegisterState(); + double total_time_seconds = (base::TimeTicks::Now() - start).InSecondsF(); + perf_test::PrintResult("yuv_convert_perftest", "", "ConvertYUVAToARGBRow_MMX", + kPerfTestIterations / total_time_seconds, "runs/s", + true); +} + +#ifdef HAS_I422ALPHATOARGBROW_SSSE3 +TEST_F(YUVConvertPerfTest, I422AlphaToARGBRow_SSSE3) { + ASSERT_TRUE(base::CPU().has_ssse3()); + + base::TimeTicks start = base::TimeTicks::Now(); + for (int i = 0; i < kPerfTestIterations; ++i) { + for (int row = 0; row < kSourceHeight; ++row) { + int chroma_row = row / 2; + libyuv::I422AlphaToARGBRow_SSSE3( + yuv_bytes_.get() + row * kSourceWidth, + yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2), + yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2), + yuv_bytes_.get() + row * kSourceWidth, // hack: use luma for alpha + rgb_bytes_converted_.get(), &libyuv::kYuvIConstants, kWidth); + } + } + double total_time_seconds = (base::TimeTicks::Now() - start).InSecondsF(); + perf_test::PrintResult("yuv_convert_perftest", "", "I422AlphaToARGBRow_SSSE3", + kPerfTestIterations / total_time_seconds, "runs/s", + true); +} +#endif + // 64-bit release + component builds on Windows are too smart and optimizes // away the function being tested. #if defined(OS_WIN) && (defined(ARCH_CPU_X86) || !defined(COMPONENT_BUILD)) @@ -135,11 +203,11 @@ GetLookupTable(YV12)); } } + media::EmptyRegisterState(); double total_time_seconds = (base::TimeTicks::Now() - start).InSecondsF(); perf_test::PrintResult( "yuv_convert_perftest", "", "LinearScaleYUVToRGB32Row_SSE", kPerfTestIterations / total_time_seconds, "runs/s", true); - media::EmptyRegisterState(); } #endif // defined(OS_WIN) && (ARCH_CPU_X86 || COMPONENT_BUILD)
diff --git a/media/blink/run_all_unittests.cc b/media/blink/run_all_unittests.cc index d84a1af..bdd34a74 100644 --- a/media/blink/run_all_unittests.cc +++ b/media/blink/run_all_unittests.cc
@@ -7,7 +7,7 @@ #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" #include "build/build_config.h" -#include "components/scheduler/child/scheduler_task_runner_delegate_impl.h" +#include "components/scheduler/child/scheduler_tqm_delegate_impl.h" #include "components/scheduler/child/web_task_runner_impl.h" #include "components/scheduler/renderer/renderer_scheduler_impl.h" #include "components/scheduler/renderer/renderer_web_scheduler_impl.h" @@ -57,7 +57,7 @@ } private: - scoped_refptr<scheduler::SchedulerTaskRunnerDelegate> task_runner_delegate_; + scoped_refptr<scheduler::SchedulerTqmDelegate> task_runner_delegate_; scoped_ptr<scheduler::RendererScheduler> scheduler_; scoped_ptr<blink::WebScheduler> web_scheduler_; scoped_ptr<blink::WebTaskRunner> web_task_runner_;
diff --git a/media/cast/BUILD.gn b/media/cast/BUILD.gn index 6b87e13..c9c8fc5 100644 --- a/media/cast/BUILD.gn +++ b/media/cast/BUILD.gn
@@ -27,14 +27,12 @@ "logging/encoding_event_subscriber.h", "logging/log_deserializer.cc", "logging/log_deserializer.h", + "logging/log_event_dispatcher.cc", + "logging/log_event_dispatcher.h", "logging/log_serializer.cc", "logging/log_serializer.h", "logging/logging_defines.cc", "logging/logging_defines.h", - "logging/logging_impl.cc", - "logging/logging_impl.h", - "logging/logging_raw.cc", - "logging/logging_raw.h", "logging/raw_event_subscriber.h", "logging/raw_event_subscriber_bundle.cc", "logging/raw_event_subscriber_bundle.h", @@ -282,8 +280,6 @@ test("cast_unittests") { sources = [ "logging/encoding_event_subscriber_unittest.cc", - "logging/logging_impl_unittest.cc", - "logging/logging_raw_unittest.cc", "logging/receiver_time_offset_estimator_impl_unittest.cc", "logging/serialize_deserialize_test.cc", "logging/simple_event_subscriber_unittest.cc",
diff --git a/media/cast/cast.gyp b/media/cast/cast.gyp index 3e8310d6..1ef6cda5 100644 --- a/media/cast/cast.gyp +++ b/media/cast/cast.gyp
@@ -43,14 +43,12 @@ 'logging/encoding_event_subscriber.h', 'logging/log_deserializer.cc', 'logging/log_deserializer.h', + 'logging/log_event_dispatcher.cc', + 'logging/log_event_dispatcher.h', 'logging/log_serializer.cc', 'logging/log_serializer.h', 'logging/logging_defines.cc', 'logging/logging_defines.h', - 'logging/logging_impl.cc', - 'logging/logging_impl.h', - 'logging/logging_raw.cc', - 'logging/logging_raw.h', 'logging/raw_event_subscriber.h', 'logging/raw_event_subscriber_bundle.cc', 'logging/raw_event_subscriber_bundle.h',
diff --git a/media/cast/cast_environment.cc b/media/cast/cast_environment.cc index f22f0a4..e3def4ff 100644 --- a/media/cast/cast_environment.cc +++ b/media/cast/cast_environment.cc
@@ -10,14 +10,6 @@ using base::SingleThreadTaskRunner; -namespace { - -void DeleteLoggingOnMainThread(scoped_ptr<media::cast::LoggingImpl> logging) { - logging.reset(); -} - -} // namespace - namespace media { namespace cast { @@ -30,17 +22,9 @@ audio_thread_proxy_(audio_thread_proxy), video_thread_proxy_(video_thread_proxy), clock_(clock.Pass()), - logging_(new LoggingImpl) {} + logger_(this) {} -CastEnvironment::~CastEnvironment() { - // Logging must be deleted on the main thread. - if (main_thread_proxy_.get() && - !main_thread_proxy_->RunsTasksOnCurrentThread()) { - main_thread_proxy_->PostTask( - FROM_HERE, - base::Bind(&DeleteLoggingOnMainThread, base::Passed(&logging_))); - } -} +CastEnvironment::~CastEnvironment() {} bool CastEnvironment::PostTask(ThreadId identifier, const tracked_objects::Location& from_here,
diff --git a/media/cast/cast_environment.h b/media/cast/cast_environment.h index 83b5ce3..9b29d4ab 100644 --- a/media/cast/cast_environment.h +++ b/media/cast/cast_environment.h
@@ -11,8 +11,7 @@ #include "base/single_thread_task_runner.h" #include "base/time/tick_clock.h" #include "base/time/time.h" -#include "media/cast/logging/logging_defines.h" -#include "media/cast/logging/logging_impl.h" +#include "media/cast/logging/log_event_dispatcher.h" namespace media { namespace cast { @@ -56,10 +55,8 @@ // All of the media::cast implementation must use this TickClock. base::TickClock* Clock() const { return clock_.get(); } - // Logging is not thread safe. Its methods should always be called from the - // main thread. - // TODO(hubbe): Logging should be a thread-safe interface. - LoggingImpl* Logging() const { return logging_.get(); } + // Thread-safe log event dispatcher. + LogEventDispatcher* logger() { return &logger_; } scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner( ThreadId identifier) const; @@ -76,7 +73,7 @@ scoped_refptr<base::SingleThreadTaskRunner> audio_thread_proxy_; scoped_refptr<base::SingleThreadTaskRunner> video_thread_proxy_; scoped_ptr<base::TickClock> clock_; - scoped_ptr<LoggingImpl> logging_; + LogEventDispatcher logger_; private: friend class base::RefCountedThreadSafe<CastEnvironment>;
diff --git a/media/cast/cast_testing.gypi b/media/cast/cast_testing.gypi index 116727e5..461bedd 100644 --- a/media/cast/cast_testing.gypi +++ b/media/cast/cast_testing.gypi
@@ -76,8 +76,6 @@ 'sources': [ '<(DEPTH)/media/base/run_all_unittests.cc', 'logging/encoding_event_subscriber_unittest.cc', - 'logging/logging_impl_unittest.cc', - 'logging/logging_raw_unittest.cc', 'logging/receiver_time_offset_estimator_impl_unittest.cc', 'logging/serialize_deserialize_test.cc', 'logging/simple_event_subscriber_unittest.cc',
diff --git a/media/cast/logging/encoding_event_subscriber_unittest.cc b/media/cast/logging/encoding_event_subscriber_unittest.cc index b052bbb8..123a8fe 100644 --- a/media/cast/logging/encoding_event_subscriber_unittest.cc +++ b/media/cast/logging/encoding_event_subscriber_unittest.cc
@@ -43,15 +43,12 @@ void Init(EventMediaType event_media_type) { DCHECK(!event_subscriber_); event_subscriber_.reset(new EncodingEventSubscriber(event_media_type, 10)); - cast_environment_->Logging()->AddRawEventSubscriber( - event_subscriber_.get()); + cast_environment_->logger()->Subscribe(event_subscriber_.get()); } ~EncodingEventSubscriberTest() override { - if (event_subscriber_) { - cast_environment_->Logging()->RemoveRawEventSubscriber( - event_subscriber_.get()); - } + if (event_subscriber_) + cast_environment_->logger()->Unsubscribe(event_subscriber_.get()); } void GetEventsAndReset() { @@ -79,20 +76,30 @@ int width = 320; int height = 180; for (int i = 0; i < 11; i++) { - cast_environment_->Logging()->InsertFrameEvent(now, - FRAME_CAPTURE_BEGIN, - VIDEO_EVENT, - i * 100, - /*frame_id*/ 0); - cast_environment_->Logging()->InsertCapturedVideoFrameEvent(now, - i * 100, - width, - height); - cast_environment_->Logging()->InsertFrameEvent(now, - FRAME_DECODED, - VIDEO_EVENT, - i * 100, - /*frame_id*/ 0); + scoped_ptr<FrameEvent> capture_begin_event(new FrameEvent()); + capture_begin_event->timestamp = now; + capture_begin_event->type = FRAME_CAPTURE_BEGIN; + capture_begin_event->media_type = VIDEO_EVENT; + capture_begin_event->rtp_timestamp = i * 100; + cast_environment_->logger()->DispatchFrameEvent(capture_begin_event.Pass()); + + scoped_ptr<FrameEvent> capture_end_event(new FrameEvent()); + capture_end_event->timestamp = now; + capture_end_event->type = FRAME_CAPTURE_END; + capture_end_event->media_type = VIDEO_EVENT; + capture_end_event->rtp_timestamp = i * 100; + capture_end_event->width = width; + capture_end_event->height = height; + cast_environment_->logger()->DispatchFrameEvent(capture_end_event.Pass()); + + scoped_ptr<FrameEvent> decoded_event(new FrameEvent()); + decoded_event->timestamp = now; + decoded_event->type = FRAME_DECODED; + decoded_event->media_type = VIDEO_EVENT; + decoded_event->rtp_timestamp = i * 100; + decoded_event->frame_id = 0; + cast_environment_->logger()->DispatchFrameEvent(decoded_event.Pass()); + width += 160; height += 90; } @@ -119,14 +126,16 @@ // Entry with RTP timestamp 0 should get dropped. for (int i = 0; i < 11; i++) { - cast_environment_->Logging()->InsertPacketEvent(now, - PACKET_RECEIVED, - AUDIO_EVENT, - /*rtp_timestamp*/ i * 100, - /*frame_id*/ 0, - /*packet_id*/ i, - /*max_packet_id*/ 10, - /*size*/ 123); + scoped_ptr<PacketEvent> receive_event(new PacketEvent()); + receive_event->timestamp = now; + receive_event->type = PACKET_RECEIVED; + receive_event->media_type = AUDIO_EVENT; + receive_event->rtp_timestamp = i * 100; + receive_event->frame_id = 0; + receive_event->packet_id = i; + receive_event->max_packet_id = 10; + receive_event->size = 123; + cast_environment_->logger()->DispatchPacketEvent(receive_event.Pass()); } GetEventsAndReset(); @@ -141,18 +150,22 @@ base::TimeTicks now(testing_clock_->NowTicks()); RtpTimestamp rtp_timestamp = 100; - cast_environment_->Logging()->InsertFrameEvent(now, - FRAME_DECODED, - VIDEO_EVENT, - rtp_timestamp, - /*frame_id*/ 0); + scoped_ptr<FrameEvent> video_event(new FrameEvent()); + video_event->timestamp = now; + video_event->type = FRAME_DECODED; + video_event->media_type = VIDEO_EVENT; + video_event->rtp_timestamp = rtp_timestamp; + video_event->frame_id = 0; + cast_environment_->logger()->DispatchFrameEvent(video_event.Pass()); // This is an AUDIO_EVENT and shouldn't be processed by the subscriber. - cast_environment_->Logging()->InsertFrameEvent(now, - FRAME_DECODED, - AUDIO_EVENT, - rtp_timestamp, - /*frame_id*/ 0); + scoped_ptr<FrameEvent> audio_event(new FrameEvent()); + audio_event->timestamp = now; + audio_event->type = FRAME_DECODED; + audio_event->media_type = AUDIO_EVENT; + audio_event->rtp_timestamp = rtp_timestamp; + audio_event->frame_id = 0; + cast_environment_->logger()->DispatchFrameEvent(audio_event.Pass()); GetEventsAndReset(); @@ -174,10 +187,13 @@ Init(VIDEO_EVENT); base::TimeTicks now(testing_clock_->NowTicks()); RtpTimestamp rtp_timestamp = 100; - cast_environment_->Logging()->InsertFrameEvent(now, FRAME_DECODED, - VIDEO_EVENT, - rtp_timestamp, - /*frame_id*/ 0); + scoped_ptr<FrameEvent> decode_event(new FrameEvent()); + decode_event->timestamp = now; + decode_event->type = FRAME_DECODED; + decode_event->media_type = VIDEO_EVENT; + decode_event->rtp_timestamp = rtp_timestamp; + decode_event->frame_id = 0; + cast_environment_->logger()->DispatchFrameEvent(decode_event.Pass()); GetEventsAndReset(); @@ -207,9 +223,14 @@ base::TimeTicks now(testing_clock_->NowTicks()); RtpTimestamp rtp_timestamp = 100; int delay_ms = 100; - cast_environment_->Logging()->InsertFrameEventWithDelay( - now, FRAME_PLAYOUT, AUDIO_EVENT, rtp_timestamp, - /*frame_id*/ 0, base::TimeDelta::FromMilliseconds(delay_ms)); + scoped_ptr<FrameEvent> playout_event(new FrameEvent()); + playout_event->timestamp = now; + playout_event->type = FRAME_PLAYOUT; + playout_event->media_type = AUDIO_EVENT; + playout_event->rtp_timestamp = rtp_timestamp; + playout_event->frame_id = 0; + playout_event->delay_delta = base::TimeDelta::FromMilliseconds(delay_ms); + cast_environment_->logger()->DispatchFrameEvent(playout_event.Pass()); GetEventsAndReset(); @@ -241,10 +262,18 @@ int target_bitrate = 1024; double encoder_cpu_utilization = 0.90; double idealized_bitrate_utilization = 0.42; - cast_environment_->Logging()->InsertEncodedFrameEvent( - now, FRAME_ENCODED, VIDEO_EVENT, rtp_timestamp, - /*frame_id*/ 0, size, key_frame, target_bitrate, - encoder_cpu_utilization, idealized_bitrate_utilization); + scoped_ptr<FrameEvent> encode_event(new FrameEvent()); + encode_event->timestamp = now; + encode_event->type = FRAME_ENCODED; + encode_event->media_type = VIDEO_EVENT; + encode_event->rtp_timestamp = rtp_timestamp; + encode_event->frame_id = 0; + encode_event->size = size; + encode_event->key_frame = key_frame; + encode_event->target_bitrate = target_bitrate; + encode_event->encoder_cpu_utilization = encoder_cpu_utilization; + encode_event->idealized_bitrate_utilization = idealized_bitrate_utilization; + cast_environment_->logger()->DispatchFrameEvent(encode_event.Pass()); GetEventsAndReset(); @@ -276,22 +305,37 @@ RtpTimestamp rtp_timestamp1 = 100; RtpTimestamp rtp_timestamp2 = 200; base::TimeTicks now1(testing_clock_->NowTicks()); - cast_environment_->Logging()->InsertFrameEventWithDelay( - now1, FRAME_PLAYOUT, AUDIO_EVENT, rtp_timestamp1, - /*frame_id*/ 0, /*delay*/ base::TimeDelta::FromMilliseconds(100)); + scoped_ptr<FrameEvent> playout_event(new FrameEvent()); + playout_event->timestamp = now1; + playout_event->type = FRAME_PLAYOUT; + playout_event->media_type = AUDIO_EVENT; + playout_event->rtp_timestamp = rtp_timestamp1; + playout_event->frame_id = 0; + playout_event->delay_delta = base::TimeDelta::FromMilliseconds(100); + cast_environment_->logger()->DispatchFrameEvent(playout_event.Pass()); - testing_clock_->Advance(base::TimeDelta::FromMilliseconds(20)); + task_runner_->Sleep(base::TimeDelta::FromMilliseconds(20)); base::TimeTicks now2(testing_clock_->NowTicks()); - cast_environment_->Logging()->InsertEncodedFrameEvent( - now2, FRAME_ENCODED, AUDIO_EVENT, rtp_timestamp2, - /*frame_id*/ 0, /*size*/ 123, /* key_frame - unused */ false, - /*target_bitrate - unused*/ 0, - 0.44, 0.55); + scoped_ptr<FrameEvent> encode_event(new FrameEvent()); + encode_event->timestamp = now2; + encode_event->type = FRAME_ENCODED; + encode_event->media_type = AUDIO_EVENT; + encode_event->rtp_timestamp = rtp_timestamp2; + encode_event->frame_id = 0; + encode_event->size = 123; + encode_event->encoder_cpu_utilization = 0.44; + encode_event->idealized_bitrate_utilization = 0.55; + cast_environment_->logger()->DispatchFrameEvent(encode_event.Pass()); - testing_clock_->Advance(base::TimeDelta::FromMilliseconds(20)); + task_runner_->Sleep(base::TimeDelta::FromMilliseconds(20)); base::TimeTicks now3(testing_clock_->NowTicks()); - cast_environment_->Logging()->InsertFrameEvent( - now3, FRAME_DECODED, AUDIO_EVENT, rtp_timestamp1, /*frame_id*/ 0); + scoped_ptr<FrameEvent> decode_event(new FrameEvent()); + decode_event->timestamp = now3; + decode_event->type = FRAME_DECODED; + decode_event->media_type = AUDIO_EVENT; + decode_event->rtp_timestamp = rtp_timestamp1; + decode_event->frame_id = 0; + cast_environment_->logger()->DispatchFrameEvent(decode_event.Pass()); GetEventsAndReset(); @@ -338,10 +382,16 @@ RtpTimestamp rtp_timestamp = 100; int packet_id = 2; int size = 100; - cast_environment_->Logging()->InsertPacketEvent( - now, PACKET_RECEIVED, AUDIO_EVENT, - rtp_timestamp, /*frame_id*/ 0, packet_id, - /*max_packet_id*/ 10, size); + scoped_ptr<PacketEvent> receive_event(new PacketEvent()); + receive_event->timestamp = now; + receive_event->type = PACKET_RECEIVED; + receive_event->media_type = AUDIO_EVENT; + receive_event->rtp_timestamp = rtp_timestamp; + receive_event->frame_id = 0; + receive_event->packet_id = packet_id; + receive_event->max_packet_id = 10; + receive_event->size = size; + cast_environment_->logger()->DispatchPacketEvent(receive_event.Pass()); GetEventsAndReset(); @@ -374,25 +424,29 @@ RtpTimestamp rtp_timestamp = 100; int packet_id = 2; int size = 100; - cast_environment_->Logging()->InsertPacketEvent(now1, - PACKET_SENT_TO_NETWORK, - VIDEO_EVENT, - rtp_timestamp, - /*frame_id*/ 0, - packet_id, - /*max_packet_id*/ 10, - size); + scoped_ptr<PacketEvent> send_event(new PacketEvent()); + send_event->timestamp = now1; + send_event->type = PACKET_SENT_TO_NETWORK; + send_event->media_type = VIDEO_EVENT; + send_event->rtp_timestamp = rtp_timestamp; + send_event->frame_id = 0; + send_event->packet_id = packet_id; + send_event->max_packet_id = 10; + send_event->size = size; + cast_environment_->logger()->DispatchPacketEvent(send_event.Pass()); - testing_clock_->Advance(base::TimeDelta::FromMilliseconds(20)); + task_runner_->Sleep(base::TimeDelta::FromMilliseconds(20)); base::TimeTicks now2(testing_clock_->NowTicks()); - cast_environment_->Logging()->InsertPacketEvent(now2, - PACKET_RETRANSMITTED, - VIDEO_EVENT, - rtp_timestamp, - /*frame_id*/ 0, - packet_id, - /*max_packet_id*/ 10, - size); + scoped_ptr<PacketEvent> retransmit_event(new PacketEvent()); + retransmit_event->timestamp = now2; + retransmit_event->type = PACKET_RETRANSMITTED; + retransmit_event->media_type = VIDEO_EVENT; + retransmit_event->rtp_timestamp = rtp_timestamp; + retransmit_event->frame_id = 0; + retransmit_event->packet_id = packet_id; + retransmit_event->max_packet_id = 10; + retransmit_event->size = size; + cast_environment_->logger()->DispatchPacketEvent(retransmit_event.Pass()); GetEventsAndReset(); @@ -425,25 +479,29 @@ int packet_id_1 = 2; int packet_id_2 = 3; int size = 100; - cast_environment_->Logging()->InsertPacketEvent(now1, - PACKET_SENT_TO_NETWORK, - VIDEO_EVENT, - rtp_timestamp, - /*frame_id*/ 0, - packet_id_1, - /*max_packet_id*/ 10, - size); + scoped_ptr<PacketEvent> send_event(new PacketEvent()); + send_event->timestamp = now1; + send_event->type = PACKET_SENT_TO_NETWORK; + send_event->media_type = VIDEO_EVENT; + send_event->rtp_timestamp = rtp_timestamp; + send_event->frame_id = 0; + send_event->packet_id = packet_id_1; + send_event->max_packet_id = 10; + send_event->size = size; + cast_environment_->logger()->DispatchPacketEvent(send_event.Pass()); - testing_clock_->Advance(base::TimeDelta::FromMilliseconds(20)); + task_runner_->Sleep(base::TimeDelta::FromMilliseconds(20)); base::TimeTicks now2(testing_clock_->NowTicks()); - cast_environment_->Logging()->InsertPacketEvent(now2, - PACKET_RETRANSMITTED, - VIDEO_EVENT, - rtp_timestamp, - /*frame_id*/ 0, - packet_id_2, - /*max_packet_id*/ 10, - size); + scoped_ptr<PacketEvent> retransmit_event(new PacketEvent()); + retransmit_event->timestamp = now2; + retransmit_event->type = PACKET_RETRANSMITTED; + retransmit_event->media_type = VIDEO_EVENT; + retransmit_event->rtp_timestamp = rtp_timestamp; + retransmit_event->frame_id = 0; + retransmit_event->packet_id = packet_id_2; + retransmit_event->max_packet_id = 10; + retransmit_event->size = size; + cast_environment_->logger()->DispatchPacketEvent(retransmit_event.Pass()); GetEventsAndReset(); @@ -482,25 +540,29 @@ int packet_id_1 = 2; int packet_id_2 = 3; int size = 100; - cast_environment_->Logging()->InsertPacketEvent(now1, - PACKET_SENT_TO_NETWORK, - VIDEO_EVENT, - rtp_timestamp_1, - /*frame_id*/ 0, - packet_id_1, - /*max_packet_id*/ 10, - size); + scoped_ptr<PacketEvent> send_event(new PacketEvent()); + send_event->timestamp = now1; + send_event->type = PACKET_SENT_TO_NETWORK; + send_event->media_type = VIDEO_EVENT; + send_event->rtp_timestamp = rtp_timestamp_1; + send_event->frame_id = 0; + send_event->packet_id = packet_id_1; + send_event->max_packet_id = 10; + send_event->size = size; + cast_environment_->logger()->DispatchPacketEvent(send_event.Pass()); - testing_clock_->Advance(base::TimeDelta::FromMilliseconds(20)); + task_runner_->Sleep(base::TimeDelta::FromMilliseconds(20)); base::TimeTicks now2(testing_clock_->NowTicks()); - cast_environment_->Logging()->InsertPacketEvent(now2, - PACKET_RETRANSMITTED, - VIDEO_EVENT, - rtp_timestamp_2, - /*frame_id*/ 0, - packet_id_2, - /*max_packet_id*/ 10, - size); + scoped_ptr<PacketEvent> retransmit_event(new PacketEvent()); + retransmit_event->timestamp = now2; + retransmit_event->type = PACKET_RETRANSMITTED; + retransmit_event->media_type = VIDEO_EVENT; + retransmit_event->rtp_timestamp = rtp_timestamp_2; + retransmit_event->frame_id = 0; + retransmit_event->packet_id = packet_id_2; + retransmit_event->max_packet_id = 10; + retransmit_event->size = size; + cast_environment_->logger()->DispatchPacketEvent(retransmit_event.Pass()); GetEventsAndReset(); @@ -544,16 +606,21 @@ RtpTimestamp rtp_timestamp = 12345; base::TimeTicks now(testing_clock_->NowTicks()); - cast_environment_->Logging()->InsertFrameEvent(now, - FRAME_CAPTURE_BEGIN, - VIDEO_EVENT, - rtp_timestamp, - /*frame_id*/ 0); + scoped_ptr<FrameEvent> capture_begin_event(new FrameEvent()); + capture_begin_event->timestamp = now; + capture_begin_event->type = FRAME_CAPTURE_BEGIN; + capture_begin_event->media_type = VIDEO_EVENT; + capture_begin_event->rtp_timestamp = rtp_timestamp; + cast_environment_->logger()->DispatchFrameEvent(capture_begin_event.Pass()); - cast_environment_->Logging()->InsertCapturedVideoFrameEvent( - now, - rtp_timestamp + 30, - 1280, 720); + scoped_ptr<FrameEvent> capture_end_event(new FrameEvent()); + capture_end_event->timestamp = now; + capture_end_event->type = FRAME_CAPTURE_END; + capture_end_event->media_type = VIDEO_EVENT; + capture_end_event->rtp_timestamp = rtp_timestamp + 30; + capture_end_event->width = 1280; + capture_end_event->height = 720; + cast_environment_->logger()->DispatchFrameEvent(capture_end_event.Pass()); GetEventsAndReset(); @@ -570,11 +637,13 @@ rtp_timestamp = 67890; - cast_environment_->Logging()->InsertFrameEvent(now, - FRAME_CAPTURE_BEGIN, - VIDEO_EVENT, - rtp_timestamp, - /*frame_id*/ 0); + capture_begin_event.reset(new FrameEvent()); + capture_begin_event->timestamp = now; + capture_begin_event->type = FRAME_CAPTURE_BEGIN; + capture_begin_event->media_type = VIDEO_EVENT; + capture_begin_event->rtp_timestamp = rtp_timestamp; + cast_environment_->logger()->DispatchFrameEvent(capture_begin_event.Pass()); + GetEventsAndReset(); EXPECT_EQ(rtp_timestamp, first_rtp_timestamp_); @@ -585,17 +654,22 @@ RtpTimestamp rtp_timestamp = 0xffffffff - 20; base::TimeTicks now(testing_clock_->NowTicks()); - cast_environment_->Logging()->InsertFrameEvent(now, - FRAME_CAPTURE_BEGIN, - VIDEO_EVENT, - rtp_timestamp, - /*frame_id*/ 0); + scoped_ptr<FrameEvent> capture_begin_event(new FrameEvent()); + capture_begin_event->timestamp = now; + capture_begin_event->type = FRAME_CAPTURE_BEGIN; + capture_begin_event->media_type = VIDEO_EVENT; + capture_begin_event->rtp_timestamp = rtp_timestamp; + cast_environment_->logger()->DispatchFrameEvent(capture_begin_event.Pass()); // RtpTimestamp has now wrapped around. - cast_environment_->Logging()->InsertCapturedVideoFrameEvent( - now, - rtp_timestamp + 30, - 1280, 720); + scoped_ptr<FrameEvent> capture_end_event(new FrameEvent()); + capture_end_event->timestamp = now; + capture_end_event->type = FRAME_CAPTURE_END; + capture_end_event->media_type = VIDEO_EVENT; + capture_end_event->rtp_timestamp = rtp_timestamp + 30; + capture_end_event->width = 1280; + capture_end_event->height = 720; + cast_environment_->logger()->DispatchFrameEvent(capture_end_event.Pass()); GetEventsAndReset(); @@ -614,12 +688,15 @@ Init(VIDEO_EVENT); RtpTimestamp rtp_timestamp = 100; for (int i = 0; i < kMaxEventsPerProto + 1; i++) { - cast_environment_->Logging()->InsertFrameEvent(testing_clock_->NowTicks(), - FRAME_ACK_RECEIVED, - VIDEO_EVENT, - rtp_timestamp, - /*frame_id*/ 0); - testing_clock_->Advance(base::TimeDelta::FromMilliseconds(30)); + scoped_ptr<FrameEvent> ack_event(new FrameEvent()); + ack_event->timestamp = testing_clock_->NowTicks(); + ack_event->type = FRAME_ACK_RECEIVED; + ack_event->media_type = VIDEO_EVENT; + ack_event->rtp_timestamp = rtp_timestamp; + ack_event->frame_id = 0; + cast_environment_->logger()->DispatchFrameEvent(ack_event.Pass()); + + task_runner_->Sleep(base::TimeDelta::FromMilliseconds(30)); } GetEventsAndReset(); @@ -633,16 +710,18 @@ EXPECT_EQ(kMaxEventsPerProto, frame_event->event_type_size()); for (int i = 0; i < kMaxPacketsPerFrame + 1; i++) { - cast_environment_->Logging()->InsertPacketEvent( - testing_clock_->NowTicks(), - PACKET_SENT_TO_NETWORK, - VIDEO_EVENT, - rtp_timestamp, - /*frame_id*/ 0, - i, - kMaxPacketsPerFrame, - 123); - testing_clock_->Advance(base::TimeDelta::FromMilliseconds(30)); + scoped_ptr<PacketEvent> send_event(new PacketEvent()); + send_event->timestamp = testing_clock_->NowTicks(); + send_event->type = PACKET_SENT_TO_NETWORK; + send_event->media_type = VIDEO_EVENT; + send_event->rtp_timestamp = rtp_timestamp; + send_event->frame_id = 0; + send_event->packet_id = i; + send_event->max_packet_id = kMaxPacketsPerFrame; + send_event->size = 123; + cast_environment_->logger()->DispatchPacketEvent(send_event.Pass()); + + task_runner_->Sleep(base::TimeDelta::FromMilliseconds(30)); } GetEventsAndReset(); @@ -662,16 +741,18 @@ EXPECT_EQ(1, packet_event->base_packet_event_size()); for (int j = 0; j < kMaxEventsPerProto + 1; j++) { - cast_environment_->Logging()->InsertPacketEvent( - testing_clock_->NowTicks(), - PACKET_SENT_TO_NETWORK, - VIDEO_EVENT, - rtp_timestamp, - /*frame_id*/ 0, - 0, - 0, - 123); - testing_clock_->Advance(base::TimeDelta::FromMilliseconds(30)); + scoped_ptr<PacketEvent> send_event(new PacketEvent()); + send_event->timestamp = testing_clock_->NowTicks(); + send_event->type = PACKET_SENT_TO_NETWORK; + send_event->media_type = VIDEO_EVENT; + send_event->rtp_timestamp = rtp_timestamp; + send_event->frame_id = 0; + send_event->packet_id = 0; + send_event->max_packet_id = 0; + send_event->size = 123; + cast_environment_->logger()->DispatchPacketEvent(send_event.Pass()); + + task_runner_->Sleep(base::TimeDelta::FromMilliseconds(30)); } GetEventsAndReset();
diff --git a/media/cast/logging/log_event_dispatcher.cc b/media/cast/logging/log_event_dispatcher.cc new file mode 100644 index 0000000..ac0e9abc --- /dev/null +++ b/media/cast/logging/log_event_dispatcher.cc
@@ -0,0 +1,137 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/cast/logging/log_event_dispatcher.h" + +#include <algorithm> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/location.h" +#include "base/synchronization/waitable_event.h" +#include "media/cast/cast_environment.h" + +namespace media { +namespace cast { + +LogEventDispatcher::LogEventDispatcher(CastEnvironment* env) + : env_(env), impl_(new Impl()) { + DCHECK(env_); +} + +LogEventDispatcher::~LogEventDispatcher() {} + +void LogEventDispatcher::DispatchFrameEvent( + scoped_ptr<FrameEvent> event) const { + if (env_->CurrentlyOn(CastEnvironment::MAIN)) { + impl_->DispatchFrameEvent(event.Pass()); + } else { + env_->PostTask(CastEnvironment::MAIN, FROM_HERE, + base::Bind(&LogEventDispatcher::Impl::DispatchFrameEvent, + impl_, base::Passed(&event))); + } +} + +void LogEventDispatcher::DispatchPacketEvent( + scoped_ptr<PacketEvent> event) const { + if (env_->CurrentlyOn(CastEnvironment::MAIN)) { + impl_->DispatchPacketEvent(event.Pass()); + } else { + env_->PostTask(CastEnvironment::MAIN, FROM_HERE, + base::Bind(&LogEventDispatcher::Impl::DispatchPacketEvent, + impl_, base::Passed(&event))); + } +} + +void LogEventDispatcher::DispatchBatchOfEvents( + scoped_ptr<std::vector<FrameEvent>> frame_events, + scoped_ptr<std::vector<PacketEvent>> packet_events) const { + if (env_->CurrentlyOn(CastEnvironment::MAIN)) { + impl_->DispatchBatchOfEvents(frame_events.Pass(), packet_events.Pass()); + } else { + env_->PostTask( + CastEnvironment::MAIN, FROM_HERE, + base::Bind(&LogEventDispatcher::Impl::DispatchBatchOfEvents, impl_, + base::Passed(&frame_events), base::Passed(&packet_events))); + } +} + +void LogEventDispatcher::Subscribe(RawEventSubscriber* subscriber) { + if (env_->CurrentlyOn(CastEnvironment::MAIN)) { + impl_->Subscribe(subscriber); + } else { + env_->PostTask( + CastEnvironment::MAIN, FROM_HERE, + base::Bind(&LogEventDispatcher::Impl::Subscribe, impl_, subscriber)); + } +} + +void LogEventDispatcher::Unsubscribe(RawEventSubscriber* subscriber) { + if (env_->CurrentlyOn(CastEnvironment::MAIN)) { + impl_->Unsubscribe(subscriber); + } else { + // This method, once it returns, guarantees |subscriber| will not receive + // any more events. Therefore, when called on a thread other than the + // CastEnvironment's MAIN thread, block until the unsubscribe task + // completes. + struct Helper { + static void UnsubscribeAndSignal(const scoped_refptr<Impl>& impl, + RawEventSubscriber* subscriber, + base::WaitableEvent* done) { + impl->Unsubscribe(subscriber); + done->Signal(); + } + }; + base::WaitableEvent done(true, false); + CHECK(env_->PostTask( + CastEnvironment::MAIN, FROM_HERE, + base::Bind(&Helper::UnsubscribeAndSignal, impl_, subscriber, &done))); + done.Wait(); + } +} + +LogEventDispatcher::Impl::Impl() {} + +LogEventDispatcher::Impl::~Impl() { + DCHECK(subscribers_.empty()); +} + +void LogEventDispatcher::Impl::DispatchFrameEvent( + scoped_ptr<FrameEvent> event) const { + for (RawEventSubscriber* s : subscribers_) + s->OnReceiveFrameEvent(*event); +} + +void LogEventDispatcher::Impl::DispatchPacketEvent( + scoped_ptr<PacketEvent> event) const { + for (RawEventSubscriber* s : subscribers_) + s->OnReceivePacketEvent(*event); +} + +void LogEventDispatcher::Impl::DispatchBatchOfEvents( + scoped_ptr<std::vector<FrameEvent>> frame_events, + scoped_ptr<std::vector<PacketEvent>> packet_events) const { + for (RawEventSubscriber* s : subscribers_) { + for (const FrameEvent& e : *frame_events) + s->OnReceiveFrameEvent(e); + for (const PacketEvent& e : *packet_events) + s->OnReceivePacketEvent(e); + } +} + +void LogEventDispatcher::Impl::Subscribe(RawEventSubscriber* subscriber) { + DCHECK(std::find(subscribers_.begin(), subscribers_.end(), subscriber) == + subscribers_.end()); + subscribers_.push_back(subscriber); +} + +void LogEventDispatcher::Impl::Unsubscribe(RawEventSubscriber* subscriber) { + const auto it = + std::find(subscribers_.begin(), subscribers_.end(), subscriber); + DCHECK(it != subscribers_.end()); + subscribers_.erase(it); +} + +} // namespace cast +} // namespace media
diff --git a/media/cast/logging/log_event_dispatcher.h b/media/cast/logging/log_event_dispatcher.h new file mode 100644 index 0000000..d84e79b --- /dev/null +++ b/media/cast/logging/log_event_dispatcher.h
@@ -0,0 +1,81 @@ +// Copyright 2015 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 MEDIA_CAST_LOGGING_LOG_EVENT_DISPATCHER_H_ +#define MEDIA_CAST_LOGGING_LOG_EVENT_DISPATCHER_H_ + +#include <vector> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "media/cast/logging/logging_defines.h" +#include "media/cast/logging/raw_event_subscriber.h" + +namespace media { +namespace cast { + +class CastEnvironment; + +// A thread-safe receiver of logging events that manages an active list of +// EventSubscribers and dispatches the logging events to them on the MAIN +// thread. All methods, constructor, and destructor can be invoked on any +// thread. +class LogEventDispatcher { + public: + // |env| outlives this instance (and generally owns this instance). + explicit LogEventDispatcher(CastEnvironment* env); + + ~LogEventDispatcher(); + + // Called on any thread to schedule the sending of event(s) to all + // EventSubscribers on the MAIN thread. + void DispatchFrameEvent(scoped_ptr<FrameEvent> event) const; + void DispatchPacketEvent(scoped_ptr<PacketEvent> event) const; + void DispatchBatchOfEvents( + scoped_ptr<std::vector<FrameEvent>> frame_events, + scoped_ptr<std::vector<PacketEvent>> packet_events) const; + + // Adds |subscriber| to the active list to begin receiving events on MAIN + // thread. Unsubscribe() must be called before |subscriber| is destroyed. + void Subscribe(RawEventSubscriber* subscriber); + + // Removes |subscriber| from the active list. Once this method returns, the + // |subscriber| is guaranteed not to receive any more events. + void Unsubscribe(RawEventSubscriber* subscriber); + + private: + // The part of the implementation that runs exclusively on the MAIN thread. + class Impl : public base::RefCountedThreadSafe<Impl> { + public: + Impl(); + + void DispatchFrameEvent(scoped_ptr<FrameEvent> event) const; + void DispatchPacketEvent(scoped_ptr<PacketEvent> event) const; + void DispatchBatchOfEvents( + scoped_ptr<std::vector<FrameEvent>> frame_events, + scoped_ptr<std::vector<PacketEvent>> packet_events) const; + void Subscribe(RawEventSubscriber* subscriber); + void Unsubscribe(RawEventSubscriber* subscriber); + + private: + friend class base::RefCountedThreadSafe<Impl>; + + ~Impl(); + + std::vector<RawEventSubscriber*> subscribers_; + + DISALLOW_COPY_AND_ASSIGN(Impl); + }; + + CastEnvironment* const env_; // Owner of this instance. + const scoped_refptr<Impl> impl_; + + DISALLOW_COPY_AND_ASSIGN(LogEventDispatcher); +}; + +} // namespace cast +} // namespace media + +#endif // MEDIA_CAST_LOGGING_LOG_EVENT_DISPATCHER_H_
diff --git a/media/cast/logging/logging_impl.cc b/media/cast/logging/logging_impl.cc deleted file mode 100644 index b64674f..0000000 --- a/media/cast/logging/logging_impl.cc +++ /dev/null
@@ -1,131 +0,0 @@ -// Copyright 2013 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 "base/big_endian.h" -#include "base/trace_event/trace_event.h" -#include "media/cast/logging/logging_impl.h" - -namespace media { -namespace cast { - -// TODO(imcheng): Collapse LoggingRaw onto LoggingImpl. -LoggingImpl::LoggingImpl() { - // LoggingImpl can be constructed on any thread, but its methods should all be - // called on the same thread. - thread_checker_.DetachFromThread(); -} - -LoggingImpl::~LoggingImpl() {} - -void LoggingImpl::InsertFrameEvent(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, - uint32 rtp_timestamp, - uint32 frame_id) { - DCHECK(thread_checker_.CalledOnValidThread()); - raw_.InsertFrameEvent(time_of_event, event, event_media_type, - rtp_timestamp, frame_id); -} - -void LoggingImpl::InsertCapturedVideoFrameEvent( - const base::TimeTicks& time_of_event, - uint32 rtp_timestamp, - int width, - int height) { - DCHECK(thread_checker_.CalledOnValidThread()); - raw_.InsertCapturedVideoFrameEvent( - time_of_event, rtp_timestamp, width, height); -} - - -void LoggingImpl::InsertEncodedFrameEvent( - const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, - uint32 rtp_timestamp, - uint32 frame_id, - int encoded_size, - bool key_frame, - int target_bitrate, - double encoder_cpu_utilization, - double idealized_bitrate_utilization) { - DCHECK(thread_checker_.CalledOnValidThread()); - raw_.InsertEncodedFrameEvent(time_of_event, event, event_media_type, - rtp_timestamp, frame_id, encoded_size, key_frame, target_bitrate, - encoder_cpu_utilization, idealized_bitrate_utilization); -} - -void LoggingImpl::InsertFrameEventWithDelay( - const base::TimeTicks& time_of_event, CastLoggingEvent event, - EventMediaType event_media_type, uint32 rtp_timestamp, uint32 frame_id, - base::TimeDelta delay) { - DCHECK(thread_checker_.CalledOnValidThread()); - raw_.InsertFrameEventWithDelay(time_of_event, event, event_media_type, - rtp_timestamp, frame_id, delay); -} - -void LoggingImpl::InsertSinglePacketEvent(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, - const Packet& packet) { - DCHECK(thread_checker_.CalledOnValidThread()); - - // Parse basic properties. - uint32 rtp_timestamp; - uint16 packet_id, max_packet_id; - const uint8* packet_data = &packet[0]; - base::BigEndianReader big_endian_reader( - reinterpret_cast<const char*>(packet_data + 4), 4); - big_endian_reader.ReadU32(&rtp_timestamp); - base::BigEndianReader cast_big_endian_reader( - reinterpret_cast<const char*>(packet_data + 12 + 2), 4); - cast_big_endian_reader.ReadU16(&packet_id); - cast_big_endian_reader.ReadU16(&max_packet_id); - - // rtp_timestamp is enough - no need for frame_id as well. - InsertPacketEvent(time_of_event, - event, - event_media_type, - rtp_timestamp, - kFrameIdUnknown, - packet_id, - max_packet_id, - packet.size()); -} - -void LoggingImpl::InsertPacketListEvent(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, - const PacketList& packets) { - DCHECK(thread_checker_.CalledOnValidThread()); - for (PacketList::const_iterator it = packets.begin(); it != packets.end(); - ++it) { - InsertSinglePacketEvent(time_of_event, event, event_media_type, - (*it)->data); - } -} - -void LoggingImpl::InsertPacketEvent(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, - uint32 rtp_timestamp, uint32 frame_id, - uint16 packet_id, uint16 max_packet_id, - size_t size) { - DCHECK(thread_checker_.CalledOnValidThread()); - raw_.InsertPacketEvent(time_of_event, event, event_media_type, - rtp_timestamp, frame_id, packet_id, max_packet_id, size); -} - -void LoggingImpl::AddRawEventSubscriber(RawEventSubscriber* subscriber) { - DCHECK(thread_checker_.CalledOnValidThread()); - raw_.AddSubscriber(subscriber); -} - -void LoggingImpl::RemoveRawEventSubscriber(RawEventSubscriber* subscriber) { - DCHECK(thread_checker_.CalledOnValidThread()); - raw_.RemoveSubscriber(subscriber); -} - -} // namespace cast -} // namespace media
diff --git a/media/cast/logging/logging_impl.h b/media/cast/logging/logging_impl.h deleted file mode 100644 index 1fc3e76..0000000 --- a/media/cast/logging/logging_impl.h +++ /dev/null
@@ -1,86 +0,0 @@ -// Copyright 2013 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 MEDIA_CAST_LOGGING_LOGGING_IMPL_H_ -#define MEDIA_CAST_LOGGING_LOGGING_IMPL_H_ - -// Generic class that handles event logging for the cast library. -// Logging has three possible optional forms: -// 1. Raw data and stats accessible by the application. -// 2. Tracing of raw events. - -#include "base/memory/ref_counted.h" -#include "base/threading/thread_checker.h" -#include "media/cast/cast_config.h" -#include "media/cast/logging/logging_defines.h" -#include "media/cast/logging/logging_raw.h" - -namespace media { -namespace cast { - -class LoggingImpl { - public: - LoggingImpl(); - ~LoggingImpl(); - - // Note: All methods below should be called from the same thread. - - void InsertFrameEvent(const base::TimeTicks& time_of_event, - CastLoggingEvent event, EventMediaType event_media_type, - uint32 rtp_timestamp, uint32 frame_id); - - void InsertCapturedVideoFrameEvent(const base::TimeTicks& time_of_event, - uint32 rtp_timestamp, - int width, - int height); - - void InsertEncodedFrameEvent(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, - uint32 rtp_timestamp, - uint32 frame_id, - int encoded_size, - bool key_frame, - int target_bitrate, - double encoder_cpu_utilization, - double idealized_bitrate_utilization); - - void InsertFrameEventWithDelay(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, - uint32 rtp_timestamp, uint32 frame_id, - base::TimeDelta delay); - - void InsertSinglePacketEvent(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, - const Packet& packet); - - void InsertPacketListEvent(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, - const PacketList& packets); - - void InsertPacketEvent(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, uint32 rtp_timestamp, - uint32 frame_id, uint16 packet_id, - uint16 max_packet_id, size_t size); - - // Delegates to |LoggingRaw::AddRawEventSubscriber()|. - void AddRawEventSubscriber(RawEventSubscriber* subscriber); - - // Delegates to |LoggingRaw::RemoveRawEventSubscriber()|. - void RemoveRawEventSubscriber(RawEventSubscriber* subscriber); - - private: - base::ThreadChecker thread_checker_; - LoggingRaw raw_; - - DISALLOW_COPY_AND_ASSIGN(LoggingImpl); -}; - -} // namespace cast -} // namespace media - -#endif // MEDIA_CAST_LOGGING_LOGGING_IMPL_H_
diff --git a/media/cast/logging/logging_impl_unittest.cc b/media/cast/logging/logging_impl_unittest.cc deleted file mode 100644 index fb2779c0..0000000 --- a/media/cast/logging/logging_impl_unittest.cc +++ /dev/null
@@ -1,235 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stdint.h> - -#include <vector> - -#include "base/rand_util.h" -#include "base/test/simple_test_tick_clock.h" -#include "base/time/tick_clock.h" -#include "base/time/time.h" -#include "media/cast/logging/logging_defines.h" -#include "media/cast/logging/logging_impl.h" -#include "media/cast/logging/simple_event_subscriber.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace media { -namespace cast { - -// Insert frame duration- one second. -const int64 kIntervalTime1S = 1; -// Test frame rate goal - 30fps. -const int kFrameIntervalMs = 33; - -static const int64 kStartMillisecond = INT64_C(12345678900000); - -class LoggingImplTest : public ::testing::Test { - protected: - LoggingImplTest() { - testing_clock_.Advance( - base::TimeDelta::FromMilliseconds(kStartMillisecond)); - logging_.AddRawEventSubscriber(&event_subscriber_); - } - - ~LoggingImplTest() override { - logging_.RemoveRawEventSubscriber(&event_subscriber_); - } - - LoggingImpl logging_; - base::SimpleTestTickClock testing_clock_; - SimpleEventSubscriber event_subscriber_; - - DISALLOW_COPY_AND_ASSIGN(LoggingImplTest); -}; - -TEST_F(LoggingImplTest, BasicFrameLogging) { - base::TimeTicks start_time = testing_clock_.NowTicks(); - base::TimeDelta time_interval = testing_clock_.NowTicks() - start_time; - uint32 rtp_timestamp = 0; - uint32 frame_id = 0; - base::TimeTicks now; - do { - now = testing_clock_.NowTicks(); - logging_.InsertFrameEvent( - now, FRAME_CAPTURE_BEGIN, VIDEO_EVENT, rtp_timestamp, frame_id); - testing_clock_.Advance( - base::TimeDelta::FromMilliseconds(kFrameIntervalMs)); - rtp_timestamp += kFrameIntervalMs * 90; - ++frame_id; - time_interval = now - start_time; - } while (time_interval.InSeconds() < kIntervalTime1S); - - // Get logging data. - std::vector<FrameEvent> frame_events; - event_subscriber_.GetFrameEventsAndReset(&frame_events); - // Size of vector should be equal to the number of events logged, - // which equals to number of frames in this case. - EXPECT_EQ(frame_id, frame_events.size()); -} - -TEST_F(LoggingImplTest, FrameLoggingWithSize) { - // Average packet size. - const int kBaseFrameSizeBytes = 25000; - const int kRandomSizeInterval = 100; - base::TimeTicks start_time = testing_clock_.NowTicks(); - base::TimeDelta time_interval = testing_clock_.NowTicks() - start_time; - uint32 rtp_timestamp = 0; - uint32 frame_id = 0; - size_t sum_size = 0; - int target_bitrate = 1234; - do { - int size = kBaseFrameSizeBytes + - base::RandInt(-kRandomSizeInterval, kRandomSizeInterval); - sum_size += static_cast<size_t>(size); - logging_.InsertEncodedFrameEvent(testing_clock_.NowTicks(), - FRAME_ENCODED, VIDEO_EVENT, rtp_timestamp, - frame_id, size, true, target_bitrate, - 0.1, 2.3); - testing_clock_.Advance(base::TimeDelta::FromMilliseconds(kFrameIntervalMs)); - rtp_timestamp += kFrameIntervalMs * 90; - ++frame_id; - time_interval = testing_clock_.NowTicks() - start_time; - } while (time_interval.InSeconds() < kIntervalTime1S); - // Get logging data. - std::vector<FrameEvent> frame_events; - event_subscriber_.GetFrameEventsAndReset(&frame_events); - // Size of vector should be equal to the number of events logged, which - // equals to number of frames in this case. - EXPECT_EQ(frame_id, frame_events.size()); -} - -TEST_F(LoggingImplTest, FrameLoggingWithDelay) { - // Average packet size. - const int kPlayoutDelayMs = 50; - const int kRandomSizeInterval = 20; - base::TimeTicks start_time = testing_clock_.NowTicks(); - base::TimeDelta time_interval = testing_clock_.NowTicks() - start_time; - uint32 rtp_timestamp = 0; - uint32 frame_id = 0; - do { - int delay = kPlayoutDelayMs + - base::RandInt(-kRandomSizeInterval, kRandomSizeInterval); - logging_.InsertFrameEventWithDelay( - testing_clock_.NowTicks(), - FRAME_CAPTURE_BEGIN, - VIDEO_EVENT, - rtp_timestamp, - frame_id, - base::TimeDelta::FromMilliseconds(delay)); - testing_clock_.Advance(base::TimeDelta::FromMilliseconds(kFrameIntervalMs)); - rtp_timestamp += kFrameIntervalMs * 90; - ++frame_id; - time_interval = testing_clock_.NowTicks() - start_time; - } while (time_interval.InSeconds() < kIntervalTime1S); - // Get logging data. - std::vector<FrameEvent> frame_events; - event_subscriber_.GetFrameEventsAndReset(&frame_events); - // Size of vector should be equal to the number of frames logged. - EXPECT_EQ(frame_id, frame_events.size()); -} - -TEST_F(LoggingImplTest, MultipleEventFrameLogging) { - base::TimeTicks start_time = testing_clock_.NowTicks(); - base::TimeDelta time_interval = testing_clock_.NowTicks() - start_time; - uint32 rtp_timestamp = 0u; - uint32 frame_id = 0u; - uint32 num_events = 0u; - do { - logging_.InsertFrameEvent(testing_clock_.NowTicks(), - FRAME_CAPTURE_END, - VIDEO_EVENT, - rtp_timestamp, - frame_id); - ++num_events; - if (frame_id % 2) { - logging_.InsertEncodedFrameEvent(testing_clock_.NowTicks(), - FRAME_ENCODED, AUDIO_EVENT, - rtp_timestamp, - frame_id, 1500, true, 0, 4.5, 6.7); - } else if (frame_id % 3) { - logging_.InsertFrameEvent(testing_clock_.NowTicks(), FRAME_DECODED, - VIDEO_EVENT, rtp_timestamp, frame_id); - } else { - logging_.InsertFrameEventWithDelay( - testing_clock_.NowTicks(), FRAME_PLAYOUT, VIDEO_EVENT, - rtp_timestamp, frame_id, base::TimeDelta::FromMilliseconds(20)); - } - ++num_events; - - testing_clock_.Advance(base::TimeDelta::FromMilliseconds(kFrameIntervalMs)); - rtp_timestamp += kFrameIntervalMs * 90; - ++frame_id; - time_interval = testing_clock_.NowTicks() - start_time; - } while (time_interval.InSeconds() < kIntervalTime1S); - // Get logging data. - std::vector<FrameEvent> frame_events; - event_subscriber_.GetFrameEventsAndReset(&frame_events); - // Size of vector should be equal to the number of frames logged. - EXPECT_EQ(num_events, frame_events.size()); - // Multiple events captured per frame. -} - -TEST_F(LoggingImplTest, PacketLogging) { - const int kNumPacketsPerFrame = 10; - const int kBaseSize = 2500; - const int kSizeInterval = 100; - base::TimeTicks start_time = testing_clock_.NowTicks(); - base::TimeTicks latest_time; - base::TimeDelta time_interval = testing_clock_.NowTicks() - start_time; - RtpTimestamp rtp_timestamp = 0; - int frame_id = 0; - int num_packets = 0; - int sum_size = 0u; - do { - for (int i = 0; i < kNumPacketsPerFrame; ++i) { - int size = kBaseSize + base::RandInt(-kSizeInterval, kSizeInterval); - sum_size += size; - latest_time = testing_clock_.NowTicks(); - ++num_packets; - logging_.InsertPacketEvent(latest_time, - PACKET_RECEIVED, - VIDEO_EVENT, - rtp_timestamp, - frame_id, - i, - kNumPacketsPerFrame, - size); - } - testing_clock_.Advance(base::TimeDelta::FromMilliseconds(kFrameIntervalMs)); - rtp_timestamp += kFrameIntervalMs * 90; - ++frame_id; - time_interval = testing_clock_.NowTicks() - start_time; - } while (time_interval.InSeconds() < kIntervalTime1S); - // Get logging data. - std::vector<PacketEvent> packet_events; - event_subscriber_.GetPacketEventsAndReset(&packet_events); - // Size of vector should be equal to the number of packets logged. - EXPECT_EQ(num_packets, static_cast<int>(packet_events.size())); -} - -TEST_F(LoggingImplTest, MultipleRawEventSubscribers) { - SimpleEventSubscriber event_subscriber_2; - - // Now logging_ has two subscribers. - logging_.AddRawEventSubscriber(&event_subscriber_2); - - logging_.InsertFrameEvent(testing_clock_.NowTicks(), - FRAME_CAPTURE_BEGIN, - VIDEO_EVENT, - /*rtp_timestamp*/ 0u, - /*frame_id*/ 0u); - - std::vector<FrameEvent> frame_events; - event_subscriber_.GetFrameEventsAndReset(&frame_events); - EXPECT_EQ(1u, frame_events.size()); - frame_events.clear(); - event_subscriber_2.GetFrameEventsAndReset(&frame_events); - EXPECT_EQ(1u, frame_events.size()); - - logging_.RemoveRawEventSubscriber(&event_subscriber_2); -} - -} // namespace cast -} // namespace media
diff --git a/media/cast/logging/logging_raw.cc b/media/cast/logging/logging_raw.cc deleted file mode 100644 index b80c05e7..0000000 --- a/media/cast/logging/logging_raw.cc +++ /dev/null
@@ -1,140 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/cast/logging/logging_raw.h" - -#include <algorithm> - -#include "base/logging.h" -#include "base/time/time.h" - -namespace media { -namespace cast { - -LoggingRaw::LoggingRaw() {} - -LoggingRaw::~LoggingRaw() {} - -void LoggingRaw::InsertFrameEvent(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, - uint32 rtp_timestamp, - uint32 frame_id) { - InsertBaseFrameEvent(time_of_event, event, event_media_type, frame_id, - rtp_timestamp, base::TimeDelta(), 0, 0, 0, false, 0, - -1.0, -1.0); -} - -void LoggingRaw::InsertCapturedVideoFrameEvent( - const base::TimeTicks& time_of_event, - uint32 rtp_timestamp, - int width, - int height) { - InsertBaseFrameEvent(time_of_event, FRAME_CAPTURE_END, VIDEO_EVENT, - kFrameIdUnknown, rtp_timestamp, base::TimeDelta(), width, - height, 0, false, 0, -1.0, -1.0); -} - -void LoggingRaw::InsertEncodedFrameEvent(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, - uint32 rtp_timestamp, - uint32 frame_id, - int encoded_size, - bool key_frame, - int target_bitrate, - double encoder_cpu_utilization, - double idealized_bitrate_utilization) { - InsertBaseFrameEvent(time_of_event, event, event_media_type, - frame_id, rtp_timestamp, base::TimeDelta(), - 0, 0, encoded_size, key_frame, target_bitrate, - encoder_cpu_utilization, idealized_bitrate_utilization); -} - -void LoggingRaw::InsertFrameEventWithDelay(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, - uint32 rtp_timestamp, - uint32 frame_id, - base::TimeDelta delay) { - InsertBaseFrameEvent(time_of_event, event, event_media_type, frame_id, - rtp_timestamp, delay, 0, 0, 0, false, 0, -1.0, -1.0); -} - -void LoggingRaw::InsertBaseFrameEvent(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, - uint32 frame_id, - uint32 rtp_timestamp, - base::TimeDelta delay, - int width, - int height, - int encoded_size, - bool key_frame, - int target_bitrate, - double encoder_cpu_utilization, - double idealized_bitrate_utilization) { - FrameEvent frame_event; - frame_event.rtp_timestamp = rtp_timestamp; - frame_event.frame_id = frame_id; - frame_event.width = width; - frame_event.height = height; - frame_event.size = encoded_size; - frame_event.timestamp = time_of_event; - frame_event.type = event; - frame_event.media_type = event_media_type; - frame_event.delay_delta = delay; - frame_event.key_frame = key_frame; - frame_event.target_bitrate = target_bitrate; - frame_event.encoder_cpu_utilization = encoder_cpu_utilization; - frame_event.idealized_bitrate_utilization = idealized_bitrate_utilization; - for (std::vector<RawEventSubscriber*>::const_iterator it = - subscribers_.begin(); - it != subscribers_.end(); ++it) { - (*it)->OnReceiveFrameEvent(frame_event); - } -} - -void LoggingRaw::InsertPacketEvent(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, - uint32 rtp_timestamp, - uint32 frame_id, uint16 packet_id, - uint16 max_packet_id, size_t size) { - PacketEvent packet_event; - packet_event.rtp_timestamp = rtp_timestamp; - packet_event.frame_id = frame_id; - packet_event.max_packet_id = max_packet_id; - packet_event.packet_id = packet_id; - packet_event.size = size; - packet_event.timestamp = time_of_event; - packet_event.type = event; - packet_event.media_type = event_media_type; - for (std::vector<RawEventSubscriber*>::const_iterator it = - subscribers_.begin(); - it != subscribers_.end(); ++it) { - (*it)->OnReceivePacketEvent(packet_event); - } -} - -void LoggingRaw::AddSubscriber(RawEventSubscriber* subscriber) { - DCHECK(subscriber); - DCHECK(std::find(subscribers_.begin(), subscribers_.end(), subscriber) == - subscribers_.end()); - - subscribers_.push_back(subscriber); -} - -void LoggingRaw::RemoveSubscriber(RawEventSubscriber* subscriber) { - DCHECK(subscriber); - DCHECK(std::find(subscribers_.begin(), subscribers_.end(), subscriber) != - subscribers_.end()); - - subscribers_.erase( - std::remove(subscribers_.begin(), subscribers_.end(), subscriber), - subscribers_.end()); -} - -} // namespace cast -} // namespace media
diff --git a/media/cast/logging/logging_raw.h b/media/cast/logging/logging_raw.h deleted file mode 100644 index 49ec985..0000000 --- a/media/cast/logging/logging_raw.h +++ /dev/null
@@ -1,106 +0,0 @@ -// Copyright 2013 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 MEDIA_CAST_LOGGING_LOGGING_RAW_H_ -#define MEDIA_CAST_LOGGING_LOGGING_RAW_H_ - -#include <vector> - -#include "base/basictypes.h" -#include "base/memory/linked_ptr.h" -#include "base/threading/non_thread_safe.h" -#include "base/time/tick_clock.h" -#include "media/cast/logging/logging_defines.h" -#include "media/cast/logging/raw_event_subscriber.h" - -namespace media { -namespace cast { - -// This class is not thread safe, and should only be called from the main -// thread. -class LoggingRaw : public base::NonThreadSafe { - public: - LoggingRaw(); - ~LoggingRaw(); - - // Inform of new event: two types of events: frame and packet. - // Frame events can be inserted with different parameters. - void InsertFrameEvent(const base::TimeTicks& time_of_event, - CastLoggingEvent event, EventMediaType event_media_type, - uint32 rtp_timestamp, uint32 frame_id); - - // Inserts a FRAME_CAPTURE_END event with the VIDEO_EVENT media type. - void InsertCapturedVideoFrameEvent(const base::TimeTicks& time_of_event, - uint32 rtp_timestamp, - int width, - int height); - - // This function is only applicable for FRAME_ENCODED event. - // |encoded_size| - Size of encoded frame in bytes. - // |key_frame| - Whether the frame is a key frame. This field is only - // applicable for video event. - // |target_bitrate| - The target bitrate of the encoder the time the frame - // was encoded. Only applicable for video event. - void InsertEncodedFrameEvent(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, - uint32 rtp_timestamp, - uint32 frame_id, - int encoded_size, - bool key_frame, - int target_bitrate, - double encoder_cpu_utilization, - double idealized_bitrate_utilization); - - // Render/playout delay - // This function is only applicable for FRAME_PLAYOUT event. - void InsertFrameEventWithDelay(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, - uint32 rtp_timestamp, - uint32 frame_id, base::TimeDelta delay); - - // Insert a packet event. - void InsertPacketEvent(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, uint32 rtp_timestamp, - uint32 frame_id, uint16 packet_id, - uint16 max_packet_id, size_t size); - - // Adds |subscriber| so that it will start receiving events on main thread. - // Note that this class does not own |subscriber|. - // It is a no-op to add a subscriber that already exists. - void AddSubscriber(RawEventSubscriber* subscriber); - - // Removes |subscriber| so that it will stop receiving events. - // Note that this class does NOT own the subscribers. This function MUST be - // called before |subscriber| is destroyed if it was previously added. - // It is a no-op to remove a subscriber that doesn't exist. - void RemoveSubscriber(RawEventSubscriber* subscriber); - - private: - void InsertBaseFrameEvent(const base::TimeTicks& time_of_event, - CastLoggingEvent event, - EventMediaType event_media_type, - uint32 frame_id, - uint32 rtp_timestamp, - base::TimeDelta delay, - int width, - int height, - int encoded_size, - bool key_frame, - int target_bitrate, - double encoder_cpu_utilization, - double idealized_bitrate_utilization); - - // List of subscriber pointers. This class does not own the subscribers. - std::vector<RawEventSubscriber*> subscribers_; - - DISALLOW_COPY_AND_ASSIGN(LoggingRaw); -}; - -} // namespace cast -} // namespace media - -#endif // MEDIA_CAST_LOGGING_LOGGING_RAW_H_
diff --git a/media/cast/logging/logging_raw_unittest.cc b/media/cast/logging/logging_raw_unittest.cc deleted file mode 100644 index 0ecfbbf..0000000 --- a/media/cast/logging/logging_raw_unittest.cc +++ /dev/null
@@ -1,202 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/cast/logging/logging_defines.h" -#include "media/cast/logging/logging_raw.h" -#include "media/cast/logging/simple_event_subscriber.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace media { -namespace cast { - -class LoggingRawTest : public ::testing::Test { - protected: - LoggingRawTest() { - raw_.AddSubscriber(&event_subscriber_); - } - - ~LoggingRawTest() override { raw_.RemoveSubscriber(&event_subscriber_); } - - LoggingRaw raw_; - SimpleEventSubscriber event_subscriber_; - std::vector<FrameEvent> frame_events_; - std::vector<PacketEvent> packet_events_; -}; - -TEST_F(LoggingRawTest, FrameEvent) { - CastLoggingEvent event_type = FRAME_DECODED; - EventMediaType media_type = VIDEO_EVENT; - uint32 frame_id = 456u; - RtpTimestamp rtp_timestamp = 123u; - base::TimeTicks timestamp = base::TimeTicks(); - raw_.InsertFrameEvent(timestamp, event_type, media_type, - rtp_timestamp, frame_id); - - event_subscriber_.GetPacketEventsAndReset(&packet_events_); - EXPECT_TRUE(packet_events_.empty()); - - event_subscriber_.GetFrameEventsAndReset(&frame_events_); - ASSERT_EQ(1u, frame_events_.size()); - EXPECT_EQ(rtp_timestamp, frame_events_[0].rtp_timestamp); - EXPECT_EQ(frame_id, frame_events_[0].frame_id); - EXPECT_EQ(0u, frame_events_[0].size); - EXPECT_EQ(timestamp, frame_events_[0].timestamp); - EXPECT_EQ(event_type, frame_events_[0].type); - EXPECT_EQ(media_type, frame_events_[0].media_type); - EXPECT_EQ(base::TimeDelta(), frame_events_[0].delay_delta); -} - -TEST_F(LoggingRawTest, EncodedFrameEvent) { - CastLoggingEvent event_type = FRAME_ENCODED; - EventMediaType media_type = VIDEO_EVENT; - uint32 frame_id = 456u; - RtpTimestamp rtp_timestamp = 123u; - base::TimeTicks timestamp = base::TimeTicks(); - int size = 1024; - bool key_frame = true; - int target_bitrate = 4096; - double encoder_cpu_utilization = 0.11; - double idealized_bitrate_utilization = 0.98; - raw_.InsertEncodedFrameEvent(timestamp, event_type, media_type, - rtp_timestamp, frame_id, size, key_frame, target_bitrate, - encoder_cpu_utilization, idealized_bitrate_utilization); - - event_subscriber_.GetPacketEventsAndReset(&packet_events_); - EXPECT_TRUE(packet_events_.empty()); - - event_subscriber_.GetFrameEventsAndReset(&frame_events_); - ASSERT_EQ(1u, frame_events_.size()); - EXPECT_EQ(rtp_timestamp, frame_events_[0].rtp_timestamp); - EXPECT_EQ(frame_id, frame_events_[0].frame_id); - EXPECT_EQ(size, static_cast<int>(frame_events_[0].size)); - EXPECT_EQ(timestamp, frame_events_[0].timestamp); - EXPECT_EQ(event_type, frame_events_[0].type); - EXPECT_EQ(media_type, frame_events_[0].media_type); - EXPECT_EQ(base::TimeDelta(), frame_events_[0].delay_delta); - EXPECT_EQ(key_frame, frame_events_[0].key_frame); - EXPECT_EQ(target_bitrate, frame_events_[0].target_bitrate); - EXPECT_EQ(encoder_cpu_utilization, frame_events_[0].encoder_cpu_utilization); - EXPECT_EQ(idealized_bitrate_utilization, - frame_events_[0].idealized_bitrate_utilization); -} - -TEST_F(LoggingRawTest, FrameEventWithDelay) { - CastLoggingEvent event_type = FRAME_PLAYOUT; - EventMediaType media_type = VIDEO_EVENT; - uint32 frame_id = 456u; - RtpTimestamp rtp_timestamp = 123u; - base::TimeTicks timestamp = base::TimeTicks(); - base::TimeDelta delay = base::TimeDelta::FromMilliseconds(20); - raw_.InsertFrameEventWithDelay(timestamp, event_type, media_type, - rtp_timestamp, frame_id, delay); - - event_subscriber_.GetPacketEventsAndReset(&packet_events_); - EXPECT_TRUE(packet_events_.empty()); - - event_subscriber_.GetFrameEventsAndReset(&frame_events_); - ASSERT_EQ(1u, frame_events_.size()); - EXPECT_EQ(rtp_timestamp, frame_events_[0].rtp_timestamp); - EXPECT_EQ(frame_id, frame_events_[0].frame_id); - EXPECT_EQ(0u, frame_events_[0].size); - EXPECT_EQ(timestamp, frame_events_[0].timestamp); - EXPECT_EQ(event_type, frame_events_[0].type); - EXPECT_EQ(media_type, frame_events_[0].media_type); - EXPECT_EQ(delay, frame_events_[0].delay_delta); -} - -TEST_F(LoggingRawTest, PacketEvent) { - CastLoggingEvent event_type = PACKET_RECEIVED; - EventMediaType media_type = VIDEO_EVENT; - uint32 frame_id = 456u; - uint16 packet_id = 1u; - uint16 max_packet_id = 10u; - RtpTimestamp rtp_timestamp = 123u; - base::TimeTicks timestamp = base::TimeTicks(); - size_t size = 1024u; - raw_.InsertPacketEvent(timestamp, event_type, media_type, - rtp_timestamp, frame_id, packet_id, max_packet_id, size); - - event_subscriber_.GetFrameEventsAndReset(&frame_events_); - EXPECT_TRUE(frame_events_.empty()); - - event_subscriber_.GetPacketEventsAndReset(&packet_events_); - ASSERT_EQ(1u, packet_events_.size()); - - EXPECT_EQ(rtp_timestamp, packet_events_[0].rtp_timestamp); - EXPECT_EQ(frame_id, packet_events_[0].frame_id); - EXPECT_EQ(max_packet_id, packet_events_[0].max_packet_id); - EXPECT_EQ(packet_id, packet_events_[0].packet_id); - EXPECT_EQ(size, packet_events_[0].size); - EXPECT_EQ(timestamp, packet_events_[0].timestamp); - EXPECT_EQ(event_type, packet_events_[0].type); - EXPECT_EQ(media_type, packet_events_[0].media_type); -} - -TEST_F(LoggingRawTest, MultipleSubscribers) { - SimpleEventSubscriber event_subscriber_2; - - // Now raw_ has two subscribers. - raw_.AddSubscriber(&event_subscriber_2); - - CastLoggingEvent event_type = FRAME_DECODED; - EventMediaType media_type = VIDEO_EVENT; - uint32 frame_id = 456u; - RtpTimestamp rtp_timestamp = 123u; - base::TimeTicks timestamp = base::TimeTicks(); - raw_.InsertFrameEvent(timestamp, event_type, media_type, - rtp_timestamp, frame_id); - - event_subscriber_.GetPacketEventsAndReset(&packet_events_); - EXPECT_TRUE(packet_events_.empty()); - - event_subscriber_.GetFrameEventsAndReset(&frame_events_); - ASSERT_EQ(1u, frame_events_.size()); - EXPECT_EQ(rtp_timestamp, frame_events_[0].rtp_timestamp); - EXPECT_EQ(frame_id, frame_events_[0].frame_id); - EXPECT_EQ(0u, frame_events_[0].size); - EXPECT_EQ(timestamp, frame_events_[0].timestamp); - EXPECT_EQ(event_type, frame_events_[0].type); - EXPECT_EQ(media_type, frame_events_[0].media_type); - EXPECT_EQ(base::TimeDelta(), frame_events_[0].delay_delta); - - event_subscriber_2.GetPacketEventsAndReset(&packet_events_); - EXPECT_TRUE(packet_events_.empty()); - - event_subscriber_2.GetFrameEventsAndReset(&frame_events_); - ASSERT_EQ(1u, frame_events_.size()); - EXPECT_EQ(rtp_timestamp, frame_events_[0].rtp_timestamp); - EXPECT_EQ(frame_id, frame_events_[0].frame_id); - EXPECT_EQ(0u, frame_events_[0].size); - EXPECT_EQ(timestamp, frame_events_[0].timestamp); - EXPECT_EQ(event_type, frame_events_[0].type); - EXPECT_EQ(media_type, frame_events_[0].media_type); - EXPECT_EQ(base::TimeDelta(), frame_events_[0].delay_delta); - - // Remove event_subscriber_2, so it shouldn't receive events after this. - raw_.RemoveSubscriber(&event_subscriber_2); - - media_type = AUDIO_EVENT; - frame_id = 789; - rtp_timestamp = 456; - timestamp = base::TimeTicks(); - raw_.InsertFrameEvent(timestamp, event_type, media_type, - rtp_timestamp, frame_id); - - // |event_subscriber_| should still receive events. - event_subscriber_.GetFrameEventsAndReset(&frame_events_); - ASSERT_EQ(1u, frame_events_.size()); - EXPECT_EQ(rtp_timestamp, frame_events_[0].rtp_timestamp); - EXPECT_EQ(frame_id, frame_events_[0].frame_id); - EXPECT_EQ(0u, frame_events_[0].size); - EXPECT_EQ(timestamp, frame_events_[0].timestamp); - EXPECT_EQ(event_type, frame_events_[0].type); - EXPECT_EQ(media_type, frame_events_[0].media_type); - EXPECT_EQ(base::TimeDelta(), frame_events_[0].delay_delta); - - event_subscriber_2.GetFrameEventsAndReset(&frame_events_); - EXPECT_TRUE(frame_events_.empty()); -} - -} // namespace cast -} // namespace media
diff --git a/media/cast/logging/raw_event_subscriber_bundle.cc b/media/cast/logging/raw_event_subscriber_bundle.cc index 5dc5f79..ecfe10d6 100644 --- a/media/cast/logging/raw_event_subscriber_bundle.cc +++ b/media/cast/logging/raw_event_subscriber_bundle.cc
@@ -21,13 +21,13 @@ stats_subscriber_( is_audio ? AUDIO_EVENT : VIDEO_EVENT, cast_environment->Clock(), offset_estimator) { - cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber_); - cast_environment_->Logging()->AddRawEventSubscriber(&stats_subscriber_); + cast_environment_->logger()->Subscribe(&event_subscriber_); + cast_environment_->logger()->Subscribe(&stats_subscriber_); } RawEventSubscriberBundleForStream::~RawEventSubscriberBundleForStream() { - cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber_); - cast_environment_->Logging()->RemoveRawEventSubscriber(&stats_subscriber_); + cast_environment_->logger()->Unsubscribe(&event_subscriber_); + cast_environment_->logger()->Unsubscribe(&stats_subscriber_); } EncodingEventSubscriber* @@ -45,17 +45,14 @@ : cast_environment_(cast_environment) {} RawEventSubscriberBundle::~RawEventSubscriberBundle() { - if (receiver_offset_estimator_.get()) { - cast_environment_->Logging()->RemoveRawEventSubscriber( - receiver_offset_estimator_.get()); - } + if (receiver_offset_estimator_.get()) + cast_environment_->logger()->Unsubscribe(receiver_offset_estimator_.get()); } void RawEventSubscriberBundle::AddEventSubscribers(bool is_audio) { if (!receiver_offset_estimator_.get()) { receiver_offset_estimator_.reset(new ReceiverTimeOffsetEstimatorImpl); - cast_environment_->Logging()->AddRawEventSubscriber( - receiver_offset_estimator_.get()); + cast_environment_->logger()->Subscribe(receiver_offset_estimator_.get()); } SubscribersMapByStream::iterator it = subscribers_.find(is_audio); if (it != subscribers_.end()) @@ -74,8 +71,7 @@ subscribers_.erase(it); if (subscribers_.empty()) { - cast_environment_->Logging()->RemoveRawEventSubscriber( - receiver_offset_estimator_.get()); + cast_environment_->logger()->Unsubscribe(receiver_offset_estimator_.get()); receiver_offset_estimator_.reset(); } }
diff --git a/media/cast/logging/receiver_time_offset_estimator_impl_unittest.cc b/media/cast/logging/receiver_time_offset_estimator_impl_unittest.cc index ca791d4..2cbaafd 100644 --- a/media/cast/logging/receiver_time_offset_estimator_impl_unittest.cc +++ b/media/cast/logging/receiver_time_offset_estimator_impl_unittest.cc
@@ -25,15 +25,15 @@ task_runner_, task_runner_, task_runner_)) { - cast_environment_->Logging()->AddRawEventSubscriber(&estimator_); + cast_environment_->logger()->Subscribe(&estimator_); } ~ReceiverTimeOffsetEstimatorImplTest() override { - cast_environment_->Logging()->RemoveRawEventSubscriber(&estimator_); + cast_environment_->logger()->Unsubscribe(&estimator_); } void AdvanceClocks(base::TimeDelta time) { - sender_clock_->Advance(time); + task_runner_->Sleep(time); receiver_clock_.Advance(time); } @@ -63,44 +63,62 @@ AdvanceClocks(base::TimeDelta::FromMilliseconds(20)); - cast_environment_->Logging()->InsertEncodedFrameEvent( - sender_clock_->NowTicks(), - FRAME_ENCODED, VIDEO_EVENT, - rtp_timestamp, - frame_id, - 1234, - true, - 5678, - 9.10, - 11.12); + scoped_ptr<FrameEvent> encode_event(new FrameEvent()); + encode_event->timestamp = sender_clock_->NowTicks(); + encode_event->type = FRAME_ENCODED; + encode_event->media_type = VIDEO_EVENT; + encode_event->rtp_timestamp = rtp_timestamp; + encode_event->frame_id = frame_id; + encode_event->size = 1234; + encode_event->key_frame = true; + encode_event->target_bitrate = 5678; + encode_event->encoder_cpu_utilization = 9.10; + encode_event->idealized_bitrate_utilization = 11.12; + cast_environment_->logger()->DispatchFrameEvent(encode_event.Pass()); - cast_environment_->Logging()->InsertPacketEvent( - sender_clock_->NowTicks(), - PACKET_SENT_TO_NETWORK, VIDEO_EVENT, - rtp_timestamp, - frame_id, - 56, 78, 1500); + scoped_ptr<PacketEvent> send_event(new PacketEvent()); + send_event->timestamp = sender_clock_->NowTicks(); + send_event->type = PACKET_SENT_TO_NETWORK; + send_event->media_type = VIDEO_EVENT; + send_event->rtp_timestamp = rtp_timestamp; + send_event->frame_id = frame_id; + send_event->packet_id = 56; + send_event->max_packet_id = 78; + send_event->size = 1500; + cast_environment_->logger()->DispatchPacketEvent(send_event.Pass()); EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound)); AdvanceClocks(base::TimeDelta::FromMilliseconds(10)); - cast_environment_->Logging()->InsertFrameEvent( - receiver_clock_.NowTicks(), FRAME_ACK_SENT, VIDEO_EVENT, - rtp_timestamp, frame_id); + scoped_ptr<FrameEvent> ack_sent_event(new FrameEvent()); + ack_sent_event->timestamp = receiver_clock_.NowTicks(); + ack_sent_event->type = FRAME_ACK_SENT; + ack_sent_event->media_type = VIDEO_EVENT; + ack_sent_event->rtp_timestamp = rtp_timestamp; + ack_sent_event->frame_id = frame_id; + cast_environment_->logger()->DispatchFrameEvent(ack_sent_event.Pass()); - cast_environment_->Logging()->InsertPacketEvent( - receiver_clock_.NowTicks(), - PACKET_RECEIVED, VIDEO_EVENT, - rtp_timestamp, - frame_id, - 56, 78, 1500); + scoped_ptr<PacketEvent> receive_event(new PacketEvent()); + receive_event->timestamp = receiver_clock_.NowTicks(); + receive_event->type = PACKET_RECEIVED; + receive_event->media_type = VIDEO_EVENT; + receive_event->rtp_timestamp = rtp_timestamp; + receive_event->frame_id = frame_id; + receive_event->packet_id = 56; + receive_event->max_packet_id = 78; + receive_event->size = 1500; + cast_environment_->logger()->DispatchPacketEvent(receive_event.Pass()); EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound)); AdvanceClocks(base::TimeDelta::FromMilliseconds(30)); - cast_environment_->Logging()->InsertFrameEvent( - sender_clock_->NowTicks(), FRAME_ACK_RECEIVED, VIDEO_EVENT, - rtp_timestamp, frame_id); + scoped_ptr<FrameEvent> ack_event(new FrameEvent()); + ack_event->timestamp = sender_clock_->NowTicks(); + ack_event->type = FRAME_ACK_RECEIVED; + ack_event->media_type = VIDEO_EVENT; + ack_event->rtp_timestamp = rtp_timestamp; + ack_event->frame_id = frame_id; + cast_environment_->logger()->DispatchFrameEvent(ack_event.Pass()); EXPECT_TRUE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound)); @@ -112,7 +130,7 @@ EXPECT_LE(true_offset_ms, upper_bound_ms); } -// Same scenario as above, but event C arrives before event B. It doens't mean +// Same scenario as above, but event C arrives before event B. It doesn't mean // event C occurred before event B. TEST_F(ReceiverTimeOffsetEstimatorImplTest, EventCArrivesBeforeEventB) { int64 true_offset_ms = 100; @@ -128,23 +146,29 @@ AdvanceClocks(base::TimeDelta::FromMilliseconds(20)); - cast_environment_->Logging()->InsertEncodedFrameEvent( - sender_clock_->NowTicks(), - FRAME_ENCODED, VIDEO_EVENT, - rtp_timestamp, - frame_id, - 1234, - true, - 5678, - 9.10, - 11.12); + scoped_ptr<FrameEvent> encode_event(new FrameEvent()); + encode_event->timestamp = sender_clock_->NowTicks(); + encode_event->type = FRAME_ENCODED; + encode_event->media_type = VIDEO_EVENT; + encode_event->rtp_timestamp = rtp_timestamp; + encode_event->frame_id = frame_id; + encode_event->size = 1234; + encode_event->key_frame = true; + encode_event->target_bitrate = 5678; + encode_event->encoder_cpu_utilization = 9.10; + encode_event->idealized_bitrate_utilization = 11.12; + cast_environment_->logger()->DispatchFrameEvent(encode_event.Pass()); - cast_environment_->Logging()->InsertPacketEvent( - sender_clock_->NowTicks(), - PACKET_SENT_TO_NETWORK, VIDEO_EVENT, - rtp_timestamp, - frame_id, - 56, 78, 1500); + scoped_ptr<PacketEvent> send_event(new PacketEvent()); + send_event->timestamp = sender_clock_->NowTicks(); + send_event->type = PACKET_SENT_TO_NETWORK; + send_event->media_type = VIDEO_EVENT; + send_event->rtp_timestamp = rtp_timestamp; + send_event->frame_id = frame_id; + send_event->packet_id = 56; + send_event->max_packet_id = 78; + send_event->size = 1500; + cast_environment_->logger()->DispatchPacketEvent(send_event.Pass()); EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound)); @@ -153,20 +177,34 @@ AdvanceClocks(base::TimeDelta::FromMilliseconds(30)); base::TimeTicks event_c_time = sender_clock_->NowTicks(); - cast_environment_->Logging()->InsertFrameEvent( - event_c_time, FRAME_ACK_RECEIVED, VIDEO_EVENT, rtp_timestamp, frame_id); + scoped_ptr<FrameEvent> ack_event(new FrameEvent()); + ack_event->timestamp = event_c_time; + ack_event->type = FRAME_ACK_RECEIVED; + ack_event->media_type = VIDEO_EVENT; + ack_event->rtp_timestamp = rtp_timestamp; + ack_event->frame_id = frame_id; + cast_environment_->logger()->DispatchFrameEvent(ack_event.Pass()); EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound)); - cast_environment_->Logging()->InsertPacketEvent( - event_b_time, - PACKET_RECEIVED, VIDEO_EVENT, - rtp_timestamp, - frame_id, - 56, 78, 1500); + scoped_ptr<PacketEvent> receive_event(new PacketEvent()); + receive_event->timestamp = event_b_time; + receive_event->type = PACKET_RECEIVED; + receive_event->media_type = VIDEO_EVENT; + receive_event->rtp_timestamp = rtp_timestamp; + receive_event->frame_id = frame_id; + receive_event->packet_id = 56; + receive_event->max_packet_id = 78; + receive_event->size = 1500; + cast_environment_->logger()->DispatchPacketEvent(receive_event.Pass()); - cast_environment_->Logging()->InsertFrameEvent( - event_b_time, FRAME_ACK_SENT, VIDEO_EVENT, rtp_timestamp, frame_id); + scoped_ptr<FrameEvent> ack_sent_event(new FrameEvent()); + ack_sent_event->timestamp = event_b_time; + ack_sent_event->type = FRAME_ACK_SENT; + ack_sent_event->media_type = VIDEO_EVENT; + ack_sent_event->rtp_timestamp = rtp_timestamp; + ack_sent_event->frame_id = frame_id; + cast_environment_->logger()->DispatchFrameEvent(ack_sent_event.Pass()); EXPECT_TRUE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound)); @@ -198,111 +236,155 @@ // Bound should end up at [95, 103] // Events times in chronological order: 20, 30 x2, 50, 55, 60, 77, 80, 110 AdvanceClocks(base::TimeDelta::FromMilliseconds(20)); - cast_environment_->Logging()->InsertEncodedFrameEvent( - sender_clock_->NowTicks(), - FRAME_ENCODED, VIDEO_EVENT, - rtp_timestamp_a, - frame_id_a, - 1234, - true, - 5678, - 9.10, - 11.12); + scoped_ptr<FrameEvent> encode_event(new FrameEvent()); + encode_event->timestamp = sender_clock_->NowTicks(); + encode_event->type = FRAME_ENCODED; + encode_event->media_type = VIDEO_EVENT; + encode_event->rtp_timestamp = rtp_timestamp_a; + encode_event->frame_id = frame_id_a; + encode_event->size = 1234; + encode_event->key_frame = true; + encode_event->target_bitrate = 5678; + encode_event->encoder_cpu_utilization = 9.10; + encode_event->idealized_bitrate_utilization = 11.12; + cast_environment_->logger()->DispatchFrameEvent(encode_event.Pass()); - cast_environment_->Logging()->InsertPacketEvent( - sender_clock_->NowTicks(), - PACKET_SENT_TO_NETWORK, VIDEO_EVENT, - rtp_timestamp_a, - frame_id_a, - 56, 78, 1500); + scoped_ptr<PacketEvent> send_event(new PacketEvent()); + send_event->timestamp = sender_clock_->NowTicks(); + send_event->type = PACKET_SENT_TO_NETWORK; + send_event->media_type = VIDEO_EVENT; + send_event->rtp_timestamp = rtp_timestamp_a; + send_event->frame_id = frame_id_a; + send_event->packet_id = 56; + send_event->max_packet_id = 78; + send_event->size = 1500; + cast_environment_->logger()->DispatchPacketEvent(send_event.Pass()); AdvanceClocks(base::TimeDelta::FromMilliseconds(10)); - cast_environment_->Logging()->InsertEncodedFrameEvent( - sender_clock_->NowTicks(), - FRAME_ENCODED, VIDEO_EVENT, - rtp_timestamp_b, - frame_id_b, - 1234, - true, - 5678, - 9.10, - 11.12); + encode_event.reset(new FrameEvent()); + encode_event->timestamp = sender_clock_->NowTicks(); + encode_event->type = FRAME_ENCODED; + encode_event->media_type = VIDEO_EVENT; + encode_event->rtp_timestamp = rtp_timestamp_b; + encode_event->frame_id = frame_id_b; + encode_event->size = 1234; + encode_event->key_frame = true; + encode_event->target_bitrate = 5678; + encode_event->encoder_cpu_utilization = 9.10; + encode_event->idealized_bitrate_utilization = 11.12; + cast_environment_->logger()->DispatchFrameEvent(encode_event.Pass()); - cast_environment_->Logging()->InsertPacketEvent( - sender_clock_->NowTicks(), - PACKET_SENT_TO_NETWORK, VIDEO_EVENT, - rtp_timestamp_b, - frame_id_b, - 56, 78, 1500); + send_event.reset(new PacketEvent()); + send_event->timestamp = sender_clock_->NowTicks(); + send_event->type = PACKET_SENT_TO_NETWORK; + send_event->media_type = VIDEO_EVENT; + send_event->rtp_timestamp = rtp_timestamp_b; + send_event->frame_id = frame_id_b; + send_event->packet_id = 56; + send_event->max_packet_id = 78; + send_event->size = 1500; + cast_environment_->logger()->DispatchPacketEvent(send_event.Pass()); - cast_environment_->Logging()->InsertFrameEvent( - receiver_clock_.NowTicks(), FRAME_ACK_SENT, VIDEO_EVENT, - rtp_timestamp_a, frame_id_a); + scoped_ptr<FrameEvent> ack_sent_event(new FrameEvent()); + ack_sent_event->timestamp = receiver_clock_.NowTicks(); + ack_sent_event->type = FRAME_ACK_SENT; + ack_sent_event->media_type = VIDEO_EVENT; + ack_sent_event->rtp_timestamp = rtp_timestamp_a; + ack_sent_event->frame_id = frame_id_a; + cast_environment_->logger()->DispatchFrameEvent(ack_sent_event.Pass()); AdvanceClocks(base::TimeDelta::FromMilliseconds(20)); - cast_environment_->Logging()->InsertPacketEvent( - receiver_clock_.NowTicks(), - PACKET_RECEIVED, VIDEO_EVENT, - rtp_timestamp_b, - frame_id_b, - 56, 78, 1500); + scoped_ptr<PacketEvent> receive_event(new PacketEvent()); + receive_event->timestamp = receiver_clock_.NowTicks(); + receive_event->type = PACKET_RECEIVED; + receive_event->media_type = VIDEO_EVENT; + receive_event->rtp_timestamp = rtp_timestamp_b; + receive_event->frame_id = frame_id_b; + receive_event->packet_id = 56; + receive_event->max_packet_id = 78; + receive_event->size = 1500; + cast_environment_->logger()->DispatchPacketEvent(receive_event.Pass()); - cast_environment_->Logging()->InsertFrameEvent( - receiver_clock_.NowTicks(), FRAME_ACK_SENT, VIDEO_EVENT, - rtp_timestamp_b, frame_id_b); + ack_sent_event.reset(new FrameEvent()); + ack_sent_event->timestamp = receiver_clock_.NowTicks(); + ack_sent_event->type = FRAME_ACK_SENT; + ack_sent_event->media_type = VIDEO_EVENT; + ack_sent_event->rtp_timestamp = rtp_timestamp_b; + ack_sent_event->frame_id = frame_id_b; + cast_environment_->logger()->DispatchFrameEvent(ack_sent_event.Pass()); AdvanceClocks(base::TimeDelta::FromMilliseconds(5)); - cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(), - FRAME_ACK_RECEIVED, - VIDEO_EVENT, - rtp_timestamp_b, - frame_id_b); + scoped_ptr<FrameEvent> ack_event(new FrameEvent()); + ack_event->timestamp = sender_clock_->NowTicks(); + ack_event->type = FRAME_ACK_RECEIVED; + ack_event->media_type = VIDEO_EVENT; + ack_event->rtp_timestamp = rtp_timestamp_b; + ack_event->frame_id = frame_id_b; + cast_environment_->logger()->DispatchFrameEvent(ack_event.Pass()); AdvanceClocks(base::TimeDelta::FromMilliseconds(5)); - cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(), - FRAME_ACK_RECEIVED, - VIDEO_EVENT, - rtp_timestamp_a, - frame_id_a); + ack_event.reset(new FrameEvent()); + ack_event->timestamp = sender_clock_->NowTicks(); + ack_event->type = FRAME_ACK_RECEIVED; + ack_event->media_type = VIDEO_EVENT; + ack_event->rtp_timestamp = rtp_timestamp_a; + ack_event->frame_id = frame_id_a; + cast_environment_->logger()->DispatchFrameEvent(ack_event.Pass()); AdvanceClocks(base::TimeDelta::FromMilliseconds(17)); - cast_environment_->Logging()->InsertEncodedFrameEvent( - sender_clock_->NowTicks(), - FRAME_ENCODED, VIDEO_EVENT, - rtp_timestamp_c, - frame_id_c, - 1234, - true, - 5678, - 9.10, - 11.12); + encode_event.reset(new FrameEvent()); + encode_event->timestamp = sender_clock_->NowTicks(); + encode_event->type = FRAME_ENCODED; + encode_event->media_type = VIDEO_EVENT; + encode_event->rtp_timestamp = rtp_timestamp_c; + encode_event->frame_id = frame_id_c; + encode_event->size = 1234; + encode_event->key_frame = true; + encode_event->target_bitrate = 5678; + encode_event->encoder_cpu_utilization = 9.10; + encode_event->idealized_bitrate_utilization = 11.12; + cast_environment_->logger()->DispatchFrameEvent(encode_event.Pass()); - cast_environment_->Logging()->InsertPacketEvent( - sender_clock_->NowTicks(), - PACKET_SENT_TO_NETWORK, VIDEO_EVENT, - rtp_timestamp_c, - frame_id_c, - 56, 78, 1500); + send_event.reset(new PacketEvent()); + send_event->timestamp = sender_clock_->NowTicks(); + send_event->type = PACKET_SENT_TO_NETWORK; + send_event->media_type = VIDEO_EVENT; + send_event->rtp_timestamp = rtp_timestamp_c; + send_event->frame_id = frame_id_c; + send_event->packet_id = 56; + send_event->max_packet_id = 78; + send_event->size = 1500; + cast_environment_->logger()->DispatchPacketEvent(send_event.Pass()); AdvanceClocks(base::TimeDelta::FromMilliseconds(3)); - cast_environment_->Logging()->InsertPacketEvent( - receiver_clock_.NowTicks(), - PACKET_RECEIVED, VIDEO_EVENT, - rtp_timestamp_c, - frame_id_c, - 56, 78, 1500); + receive_event.reset(new PacketEvent()); + receive_event->timestamp = receiver_clock_.NowTicks(); + receive_event->type = PACKET_RECEIVED; + receive_event->media_type = VIDEO_EVENT; + receive_event->rtp_timestamp = rtp_timestamp_c; + receive_event->frame_id = frame_id_c; + receive_event->packet_id = 56; + receive_event->max_packet_id = 78; + receive_event->size = 1500; + cast_environment_->logger()->DispatchPacketEvent(receive_event.Pass()); - cast_environment_->Logging()->InsertFrameEvent( - receiver_clock_.NowTicks(), FRAME_ACK_SENT, VIDEO_EVENT, - rtp_timestamp_c, frame_id_c); + ack_sent_event.reset(new FrameEvent()); + ack_sent_event->timestamp = receiver_clock_.NowTicks(); + ack_sent_event->type = FRAME_ACK_SENT; + ack_sent_event->media_type = VIDEO_EVENT; + ack_sent_event->rtp_timestamp = rtp_timestamp_c; + ack_sent_event->frame_id = frame_id_c; + cast_environment_->logger()->DispatchFrameEvent(ack_sent_event.Pass()); AdvanceClocks(base::TimeDelta::FromMilliseconds(30)); - cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(), - FRAME_ACK_RECEIVED, - VIDEO_EVENT, - rtp_timestamp_c, - frame_id_c); + ack_event.reset(new FrameEvent()); + ack_event->timestamp = sender_clock_->NowTicks(); + ack_event->type = FRAME_ACK_RECEIVED; + ack_event->media_type = VIDEO_EVENT; + ack_event->rtp_timestamp = rtp_timestamp_c; + ack_event->frame_id = frame_id_c; + cast_environment_->logger()->DispatchFrameEvent(ack_event.Pass()); EXPECT_TRUE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound)); int64 lower_bound_ms = lower_bound.InMilliseconds();
diff --git a/media/cast/logging/simple_event_subscriber_unittest.cc b/media/cast/logging/simple_event_subscriber_unittest.cc index bf2c210..92b6c6e 100644 --- a/media/cast/logging/simple_event_subscriber_unittest.cc +++ b/media/cast/logging/simple_event_subscriber_unittest.cc
@@ -25,11 +25,11 @@ task_runner_, task_runner_, task_runner_)) { - cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber_); + cast_environment_->logger()->Subscribe(&event_subscriber_); } ~SimpleEventSubscriberTest() override { - cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber_); + cast_environment_->logger()->Unsubscribe(&event_subscriber_); } base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment. @@ -40,32 +40,58 @@ TEST_F(SimpleEventSubscriberTest, GetAndResetEvents) { // Log some frame events. - cast_environment_->Logging()->InsertEncodedFrameEvent( - testing_clock_->NowTicks(), FRAME_ENCODED, AUDIO_EVENT, - /*rtp_timestamp*/ 100u, /*frame_id*/ 0u, /*frame_size*/ 123, - /*key_frame*/ false, 0, 0.01, 0.02); - cast_environment_->Logging()->InsertFrameEventWithDelay( - testing_clock_->NowTicks(), FRAME_PLAYOUT, AUDIO_EVENT, - /*rtp_timestamp*/ 100u, - /*frame_id*/ 0u, /*delay*/ base::TimeDelta::FromMilliseconds(100)); - cast_environment_->Logging()->InsertFrameEvent( - testing_clock_->NowTicks(), FRAME_DECODED, AUDIO_EVENT, - /*rtp_timestamp*/ 200u, - /*frame_id*/ 0u); + scoped_ptr<FrameEvent> encode_event(new FrameEvent()); + encode_event->timestamp = testing_clock_->NowTicks(); + encode_event->type = FRAME_ENCODED; + encode_event->media_type = AUDIO_EVENT; + encode_event->rtp_timestamp = 100u; + encode_event->frame_id = 0u; + encode_event->size = 1234; + encode_event->key_frame = true; + encode_event->target_bitrate = 128u; + encode_event->encoder_cpu_utilization = 0.01; + encode_event->idealized_bitrate_utilization = 0.02; + cast_environment_->logger()->DispatchFrameEvent(encode_event.Pass()); + + scoped_ptr<FrameEvent> playout_event(new FrameEvent()); + playout_event->timestamp = testing_clock_->NowTicks(); + playout_event->type = FRAME_PLAYOUT; + playout_event->media_type = AUDIO_EVENT; + playout_event->rtp_timestamp = 100u; + playout_event->frame_id = 0u; + playout_event->delay_delta = base::TimeDelta::FromMilliseconds(100); + cast_environment_->logger()->DispatchFrameEvent(playout_event.Pass()); + + scoped_ptr<FrameEvent> decode_event(new FrameEvent()); + decode_event->timestamp = testing_clock_->NowTicks(); + decode_event->type = FRAME_DECODED; + decode_event->media_type = AUDIO_EVENT; + decode_event->rtp_timestamp = 200u; + decode_event->frame_id = 0u; + cast_environment_->logger()->DispatchFrameEvent(decode_event.Pass()); // Log some packet events. - cast_environment_->Logging()->InsertPacketEvent( - testing_clock_->NowTicks(), PACKET_RECEIVED, AUDIO_EVENT, - /*rtp_timestamp*/ 200u, - /*frame_id*/ 0u, /*packet_id*/ 1u, /*max_packet_id*/ 5u, /*size*/ 100u); - cast_environment_->Logging()->InsertPacketEvent( - testing_clock_->NowTicks(), FRAME_DECODED, VIDEO_EVENT, - /*rtp_timestamp*/ 200u, /*frame_id*/ 0u, /*packet_id*/ 1u, - /*max_packet_id*/ 5u, /*size*/ 100u); - cast_environment_->Logging()->InsertPacketEvent( - testing_clock_->NowTicks(), FRAME_DECODED, VIDEO_EVENT, - /*rtp_timestamp*/ 300u, /*frame_id*/ 0u, /*packet_id*/ 1u, - /*max_packet_id*/ 5u, /*size*/ 100u); + scoped_ptr<PacketEvent> receive_event(new PacketEvent()); + receive_event->timestamp = testing_clock_->NowTicks(); + receive_event->type = PACKET_RECEIVED; + receive_event->media_type = AUDIO_EVENT; + receive_event->rtp_timestamp = 200u; + receive_event->frame_id = 0u; + receive_event->packet_id = 1u; + receive_event->max_packet_id = 5u; + receive_event->size = 100u; + cast_environment_->logger()->DispatchPacketEvent(receive_event.Pass()); + + receive_event.reset(new PacketEvent()); + receive_event->timestamp = testing_clock_->NowTicks(); + receive_event->type = PACKET_RECEIVED; + receive_event->media_type = VIDEO_EVENT; + receive_event->rtp_timestamp = 200u; + receive_event->frame_id = 0u; + receive_event->packet_id = 1u; + receive_event->max_packet_id = 10u; + receive_event->size = 1024u; + cast_environment_->logger()->DispatchPacketEvent(receive_event.Pass()); std::vector<FrameEvent> frame_events; event_subscriber_.GetFrameEventsAndReset(&frame_events); @@ -73,7 +99,7 @@ std::vector<PacketEvent> packet_events; event_subscriber_.GetPacketEventsAndReset(&packet_events); - EXPECT_EQ(3u, packet_events.size()); + EXPECT_EQ(2u, packet_events.size()); // Calling this function again should result in empty vector because no events // were logged since last call.
diff --git a/media/cast/logging/stats_event_subscriber_unittest.cc b/media/cast/logging/stats_event_subscriber_unittest.cc index 09dc51777..d649c896 100644 --- a/media/cast/logging/stats_event_subscriber_unittest.cc +++ b/media/cast/logging/stats_event_subscriber_unittest.cc
@@ -35,19 +35,17 @@ fake_offset_estimator_( base::TimeDelta::FromSeconds(kReceiverOffsetSecs)) { receiver_clock_.Advance(base::TimeDelta::FromSeconds(kReceiverOffsetSecs)); - cast_environment_->Logging()->AddRawEventSubscriber( - &fake_offset_estimator_); + cast_environment_->logger()->Subscribe(&fake_offset_estimator_); } ~StatsEventSubscriberTest() override { if (subscriber_.get()) - cast_environment_->Logging()->RemoveRawEventSubscriber(subscriber_.get()); - cast_environment_->Logging()->RemoveRawEventSubscriber( - &fake_offset_estimator_); + cast_environment_->logger()->Unsubscribe(subscriber_.get()); + cast_environment_->logger()->Unsubscribe(&fake_offset_estimator_); } void AdvanceClocks(base::TimeDelta delta) { - sender_clock_->Advance(delta); + task_runner_->Sleep(delta); receiver_clock_.Advance(delta); } @@ -55,7 +53,7 @@ DCHECK(!subscriber_.get()); subscriber_.reset(new StatsEventSubscriber( event_media_type, cast_environment_->Clock(), &fake_offset_estimator_)); - cast_environment_->Logging()->AddRawEventSubscriber(subscriber_.get()); + cast_environment_->logger()->Subscribe(subscriber_.get()); } base::SimpleTestTickClock* sender_clock_; // Owned by CastEnvironment. @@ -79,30 +77,35 @@ base::TimeTicks start_time = sender_clock_->NowTicks(); // Drop half the frames during the encode step. for (int i = 0; i < num_frames; i++) { - cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(), - FRAME_CAPTURE_BEGIN, - VIDEO_EVENT, - rtp_timestamp, - frame_id); + scoped_ptr<FrameEvent> capture_begin_event(new FrameEvent()); + capture_begin_event->timestamp = sender_clock_->NowTicks(); + capture_begin_event->type = FRAME_CAPTURE_BEGIN; + capture_begin_event->media_type = VIDEO_EVENT; + capture_begin_event->rtp_timestamp = rtp_timestamp; + cast_environment_->logger()->DispatchFrameEvent(capture_begin_event.Pass()); + AdvanceClocks(base::TimeDelta::FromMicroseconds(10)); - cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(), - FRAME_CAPTURE_END, - VIDEO_EVENT, - rtp_timestamp, - frame_id); + scoped_ptr<FrameEvent> capture_end_event(new FrameEvent()); + capture_end_event->timestamp = sender_clock_->NowTicks(); + capture_end_event->type = FRAME_CAPTURE_END; + capture_end_event->media_type = VIDEO_EVENT; + capture_end_event->rtp_timestamp = rtp_timestamp; + cast_environment_->logger()->DispatchFrameEvent(capture_end_event.Pass()); + if (i % 2 == 0) { AdvanceClocks(base::TimeDelta::FromMicroseconds(10)); - cast_environment_->Logging()->InsertEncodedFrameEvent( - sender_clock_->NowTicks(), - FRAME_ENCODED, - VIDEO_EVENT, - rtp_timestamp, - frame_id, - 1024, - true, - 5678, - 9.10, - 11.12); + scoped_ptr<FrameEvent> encode_event(new FrameEvent()); + encode_event->timestamp = sender_clock_->NowTicks(); + encode_event->type = FRAME_ENCODED; + encode_event->media_type = VIDEO_EVENT; + encode_event->rtp_timestamp = rtp_timestamp; + encode_event->frame_id = frame_id; + encode_event->size = 1024; + encode_event->key_frame = true; + encode_event->target_bitrate = 5678; + encode_event->encoder_cpu_utilization = 9.10; + encode_event->idealized_bitrate_utilization = 11.12; + cast_environment_->logger()->DispatchFrameEvent(encode_event.Pass()); } else if (i < extra_frames) { dropped_frames++; } @@ -155,16 +158,18 @@ for (int i = 0; i < num_frames; i++) { int size = 1000 + base::RandInt(-100, 100); total_size += size; - cast_environment_->Logging()->InsertEncodedFrameEvent( - sender_clock_->NowTicks(), - FRAME_ENCODED, VIDEO_EVENT, - rtp_timestamp, - frame_id, - size, - true, - 5678, - 9.10, - 11.12); + scoped_ptr<FrameEvent> encode_event(new FrameEvent()); + encode_event->timestamp = sender_clock_->NowTicks(); + encode_event->type = FRAME_ENCODED; + encode_event->media_type = VIDEO_EVENT; + encode_event->rtp_timestamp = rtp_timestamp; + encode_event->frame_id = frame_id; + encode_event->size = size; + encode_event->key_frame = true; + encode_event->target_bitrate = 5678; + encode_event->encoder_cpu_utilization = 9.10; + encode_event->idealized_bitrate_utilization = 11.12; + cast_environment_->logger()->DispatchFrameEvent(encode_event.Pass()); last_event_time = sender_clock_->NowTicks(); AdvanceClocks(base::TimeDelta::FromMicroseconds(35678)); @@ -215,10 +220,13 @@ int num_frames = 10; base::TimeTicks start_time = sender_clock_->NowTicks(); for (int i = 0; i < num_frames; i++) { - cast_environment_->Logging()->InsertFrameEvent(receiver_clock_.NowTicks(), - FRAME_DECODED, VIDEO_EVENT, - rtp_timestamp, - frame_id); + scoped_ptr<FrameEvent> decode_event(new FrameEvent()); + decode_event->timestamp = receiver_clock_.NowTicks(); + decode_event->type = FRAME_DECODED; + decode_event->media_type = VIDEO_EVENT; + decode_event->rtp_timestamp = rtp_timestamp; + decode_event->frame_id = frame_id; + cast_environment_->logger()->DispatchFrameEvent(decode_event.Pass()); AdvanceClocks(base::TimeDelta::FromMicroseconds(36789)); rtp_timestamp += 90; @@ -251,13 +259,14 @@ base::TimeDelta delay = base::TimeDelta::FromMilliseconds(delay_ms); if (delay_ms > 0) late_frames++; - cast_environment_->Logging()->InsertFrameEventWithDelay( - receiver_clock_.NowTicks(), - FRAME_PLAYOUT, - VIDEO_EVENT, - rtp_timestamp, - frame_id, - delay); + scoped_ptr<FrameEvent> playout_event(new FrameEvent()); + playout_event->timestamp = receiver_clock_.NowTicks(); + playout_event->type = FRAME_PLAYOUT; + playout_event->media_type = VIDEO_EVENT; + playout_event->rtp_timestamp = rtp_timestamp; + playout_event->frame_id = frame_id; + playout_event->delay_delta = delay; + cast_environment_->logger()->DispatchFrameEvent(playout_event.Pass()); AdvanceClocks(base::TimeDelta::FromMicroseconds(37890)); rtp_timestamp += 90; @@ -282,11 +291,12 @@ int num_frames = 10; base::TimeDelta total_latency; for (int i = 0; i < num_frames; i++) { - cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(), - FRAME_CAPTURE_BEGIN, - VIDEO_EVENT, - rtp_timestamp, - frame_id); + scoped_ptr<FrameEvent> capture_begin_event(new FrameEvent()); + capture_begin_event->timestamp = sender_clock_->NowTicks(); + capture_begin_event->type = FRAME_CAPTURE_BEGIN; + capture_begin_event->media_type = VIDEO_EVENT; + capture_begin_event->rtp_timestamp = rtp_timestamp; + cast_environment_->logger()->DispatchFrameEvent(capture_begin_event.Pass()); int latency_micros = 100000 + base::RandInt(-5000, 50000); base::TimeDelta latency = base::TimeDelta::FromMicroseconds(latency_micros); @@ -296,13 +306,14 @@ base::TimeDelta delay = base::TimeDelta::FromMilliseconds(delay_micros); total_latency += latency; - cast_environment_->Logging()->InsertFrameEventWithDelay( - receiver_clock_.NowTicks(), - FRAME_PLAYOUT, - VIDEO_EVENT, - rtp_timestamp, - frame_id, - delay); + scoped_ptr<FrameEvent> playout_event(new FrameEvent()); + playout_event->timestamp = receiver_clock_.NowTicks(); + playout_event->type = FRAME_PLAYOUT; + playout_event->media_type = VIDEO_EVENT; + playout_event->rtp_timestamp = rtp_timestamp; + playout_event->frame_id = frame_id; + playout_event->delay_delta = delay; + cast_environment_->logger()->DispatchFrameEvent(playout_event.Pass()); rtp_timestamp += 90; frame_id++; @@ -338,11 +349,13 @@ base::TimeTicks sender_encoded_time = sender_clock_->NowTicks(); base::TimeTicks receiver_encoded_time = receiver_clock_.NowTicks(); - cast_environment_->Logging()->InsertFrameEvent(sender_encoded_time, - FRAME_ENCODED, - VIDEO_EVENT, - rtp_timestamp, - 0); + scoped_ptr<FrameEvent> encode_event(new FrameEvent()); + encode_event->timestamp = sender_encoded_time; + encode_event->type = FRAME_ENCODED; + encode_event->media_type = VIDEO_EVENT; + encode_event->rtp_timestamp = rtp_timestamp; + encode_event->frame_id = 0; + cast_environment_->logger()->DispatchFrameEvent(encode_event.Pass()); // Every 2nd packet will be retransmitted once. // Every 4th packet will be retransmitted twice. @@ -351,14 +364,17 @@ int size = 1000 + base::RandInt(-100, 100); total_size += size; - cast_environment_->Logging()->InsertPacketEvent(sender_clock_->NowTicks(), - PACKET_SENT_TO_NETWORK, - VIDEO_EVENT, - rtp_timestamp, - 0, - i, - num_packets - 1, - size); + scoped_ptr<PacketEvent> send_event(new PacketEvent()); + send_event->timestamp = sender_clock_->NowTicks(); + send_event->type = PACKET_SENT_TO_NETWORK; + send_event->media_type = VIDEO_EVENT; + send_event->rtp_timestamp = rtp_timestamp; + send_event->frame_id = 0; + send_event->packet_id = i; + send_event->max_packet_id = num_packets - 1; + send_event->size = size; + cast_environment_->logger()->DispatchPacketEvent(send_event.Pass()); + num_packets_transmitted++; total_queueing_latency += sender_clock_->NowTicks() - sender_encoded_time; @@ -379,15 +395,17 @@ // Retransmission 1. AdvanceClocks(base::TimeDelta::FromMicroseconds(12345)); if (i % 2 == 0) { - cast_environment_->Logging()->InsertPacketEvent( - receiver_clock_.NowTicks(), - PACKET_RETRANSMITTED, - VIDEO_EVENT, - rtp_timestamp, - 0, - i, - num_packets - 1, - size); + scoped_ptr<PacketEvent> retransmit_event(new PacketEvent()); + retransmit_event->timestamp = receiver_clock_.NowTicks(); + retransmit_event->type = PACKET_RETRANSMITTED; + retransmit_event->media_type = VIDEO_EVENT; + retransmit_event->rtp_timestamp = rtp_timestamp; + retransmit_event->frame_id = 0; + retransmit_event->packet_id = i; + retransmit_event->max_packet_id = num_packets - 1; + retransmit_event->size = size; + cast_environment_->logger()->DispatchPacketEvent(retransmit_event.Pass()); + retransmit_total_size += size; num_packets_transmitted++; num_packets_retransmitted++; @@ -396,15 +414,17 @@ // Retransmission 2. AdvanceClocks(base::TimeDelta::FromMicroseconds(13456)); if (i % 4 == 0) { - cast_environment_->Logging()->InsertPacketEvent( - receiver_clock_.NowTicks(), - PACKET_RETRANSMITTED, - VIDEO_EVENT, - rtp_timestamp, - 0, - i, - num_packets - 1, - size); + scoped_ptr<PacketEvent> retransmit_event(new PacketEvent()); + retransmit_event->timestamp = receiver_clock_.NowTicks(); + retransmit_event->type = PACKET_RETRANSMITTED; + retransmit_event->media_type = VIDEO_EVENT; + retransmit_event->rtp_timestamp = rtp_timestamp; + retransmit_event->frame_id = 0; + retransmit_event->packet_id = i; + retransmit_event->max_packet_id = num_packets - 1; + retransmit_event->size = size; + cast_environment_->logger()->DispatchPacketEvent(retransmit_event.Pass()); + retransmit_total_size += size; num_packets_transmitted++; num_packets_retransmitted++; @@ -413,38 +433,45 @@ // Retransmission 3. AdvanceClocks(base::TimeDelta::FromMicroseconds(14567)); if (i % 8 == 0) { - cast_environment_->Logging()->InsertPacketEvent( - receiver_clock_.NowTicks(), - PACKET_RETRANSMITTED, - VIDEO_EVENT, - rtp_timestamp, - 0, - i, - num_packets - 1, - size); - cast_environment_->Logging()->InsertPacketEvent( - receiver_clock_.NowTicks(), - PACKET_RTX_REJECTED, - VIDEO_EVENT, - rtp_timestamp, - 0, - i, - num_packets - 1, - size); + scoped_ptr<PacketEvent> retransmit_event(new PacketEvent()); + retransmit_event->timestamp = receiver_clock_.NowTicks(); + retransmit_event->type = PACKET_RETRANSMITTED; + retransmit_event->media_type = VIDEO_EVENT; + retransmit_event->rtp_timestamp = rtp_timestamp; + retransmit_event->frame_id = 0; + retransmit_event->packet_id = i; + retransmit_event->max_packet_id = num_packets - 1; + retransmit_event->size = size; + cast_environment_->logger()->DispatchPacketEvent(retransmit_event.Pass()); + + scoped_ptr<PacketEvent> reject_event(new PacketEvent()); + reject_event->timestamp = receiver_clock_.NowTicks(); + reject_event->type = PACKET_RTX_REJECTED; + reject_event->media_type = VIDEO_EVENT; + reject_event->rtp_timestamp = rtp_timestamp; + reject_event->frame_id = 0; + reject_event->packet_id = i; + reject_event->max_packet_id = num_packets - 1; + reject_event->size = size; + cast_environment_->logger()->DispatchPacketEvent(reject_event.Pass()); + retransmit_total_size += size; num_packets_transmitted++; num_packets_retransmitted++; num_packets_rtx_rejected++; } - cast_environment_->Logging()->InsertPacketEvent(received_time, - PACKET_RECEIVED, - VIDEO_EVENT, - rtp_timestamp, - 0, - i, - num_packets - 1, - size); + scoped_ptr<PacketEvent> receive_event(new PacketEvent()); + receive_event->timestamp = received_time; + receive_event->type = PACKET_RECEIVED; + receive_event->media_type = VIDEO_EVENT; + receive_event->rtp_timestamp = rtp_timestamp; + receive_event->frame_id = 0; + receive_event->packet_id = i; + receive_event->max_packet_id = num_packets - 1; + receive_event->size = size; + cast_environment_->logger()->DispatchPacketEvent(receive_event.Pass()); + num_packets_received++; } @@ -538,43 +565,51 @@ for (int i = 0; i < 10; ++i) { ++frame_id; ++rtp_timestamp; - cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(), - FRAME_CAPTURE_BEGIN, - VIDEO_EVENT, - rtp_timestamp, - frame_id); + + scoped_ptr<FrameEvent> capture_begin_event(new FrameEvent()); + capture_begin_event->timestamp = sender_clock_->NowTicks(); + capture_begin_event->type = FRAME_CAPTURE_BEGIN; + capture_begin_event->media_type = VIDEO_EVENT; + capture_begin_event->rtp_timestamp = rtp_timestamp; + cast_environment_->logger()->DispatchFrameEvent(capture_begin_event.Pass()); + AdvanceClocks(base::TimeDelta::FromMilliseconds(10)); - cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(), - FRAME_CAPTURE_END, - VIDEO_EVENT, - rtp_timestamp, - frame_id); + scoped_ptr<FrameEvent> capture_end_event(new FrameEvent()); + capture_end_event->timestamp = sender_clock_->NowTicks(); + capture_end_event->type = FRAME_CAPTURE_END; + capture_end_event->media_type = VIDEO_EVENT; + capture_end_event->rtp_timestamp = rtp_timestamp; + cast_environment_->logger()->DispatchFrameEvent(capture_end_event.Pass()); + AdvanceClocks(base::TimeDelta::FromMilliseconds(15)); - cast_environment_->Logging()->InsertEncodedFrameEvent( - sender_clock_->NowTicks(), - FRAME_ENCODED, - VIDEO_EVENT, - rtp_timestamp, - frame_id, - 1024, - true, - 5678, - 9.10, - 11.12); + scoped_ptr<FrameEvent> encode_event(new FrameEvent()); + encode_event->timestamp = sender_clock_->NowTicks(); + encode_event->type = FRAME_ENCODED; + encode_event->media_type = VIDEO_EVENT; + encode_event->rtp_timestamp = rtp_timestamp; + encode_event->frame_id = frame_id; + encode_event->size = 1024; + encode_event->key_frame = true; + encode_event->target_bitrate = 5678; + encode_event->encoder_cpu_utilization = 9.10; + encode_event->idealized_bitrate_utilization = 11.12; + cast_environment_->logger()->DispatchFrameEvent(encode_event.Pass()); } // Send 3 packets for the last frame. // Queueing latencies are 100ms, 200ms and 300ms. for (int i = 0; i < 3; ++i) { AdvanceClocks(base::TimeDelta::FromMilliseconds(100)); - cast_environment_->Logging()->InsertPacketEvent(sender_clock_->NowTicks(), - PACKET_SENT_TO_NETWORK, - VIDEO_EVENT, - rtp_timestamp, - 0, - i, - 2, - 123); + scoped_ptr<PacketEvent> send_event(new PacketEvent()); + send_event->timestamp = sender_clock_->NowTicks(); + send_event->type = PACKET_SENT_TO_NETWORK; + send_event->media_type = VIDEO_EVENT; + send_event->rtp_timestamp = rtp_timestamp; + send_event->frame_id = 0; + send_event->packet_id = i; + send_event->max_packet_id = 2; + send_event->size = 123; + cast_environment_->logger()->DispatchPacketEvent(send_event.Pass()); } // Receive 3 packets for the last frame. @@ -582,23 +617,26 @@ // Packet latencies are 400ms. AdvanceClocks(base::TimeDelta::FromMilliseconds(100)); for (int i = 0; i < 3; ++i) { - cast_environment_->Logging()->InsertPacketEvent(receiver_clock_.NowTicks(), - PACKET_RECEIVED, - VIDEO_EVENT, - rtp_timestamp, - 0, - i, - 2, - 123); + scoped_ptr<PacketEvent> receive_event(new PacketEvent()); + receive_event->timestamp = receiver_clock_.NowTicks(); + receive_event->type = PACKET_RECEIVED; + receive_event->media_type = VIDEO_EVENT; + receive_event->rtp_timestamp = rtp_timestamp; + receive_event->frame_id = 0; + receive_event->packet_id = i; + receive_event->max_packet_id = 2; + receive_event->size = 123; + cast_environment_->logger()->DispatchPacketEvent(receive_event.Pass()); } - cast_environment_->Logging()->InsertFrameEventWithDelay( - receiver_clock_.NowTicks(), - FRAME_PLAYOUT, - VIDEO_EVENT, - rtp_timestamp, - frame_id, - base::TimeDelta::FromMilliseconds(100)); + scoped_ptr<FrameEvent> playout_event(new FrameEvent()); + playout_event->timestamp = receiver_clock_.NowTicks(); + playout_event->type = FRAME_PLAYOUT; + playout_event->media_type = VIDEO_EVENT; + playout_event->rtp_timestamp = rtp_timestamp; + playout_event->frame_id = frame_id; + playout_event->delay_delta = base::TimeDelta::FromMilliseconds(100); + cast_environment_->logger()->DispatchFrameEvent(playout_event.Pass()); StatsEventSubscriber::SimpleHistogram* histogram; scoped_ptr<base::ListValue> values;
diff --git a/media/cast/net/cast_transport_sender.h b/media/cast/net/cast_transport_sender.h index fc88a5c3..b20c9df 100644 --- a/media/cast/net/cast_transport_sender.h +++ b/media/cast/net/cast_transport_sender.h
@@ -20,6 +20,7 @@ #include "base/basictypes.h" #include "base/callback.h" +#include "base/memory/scoped_ptr.h" #include "base/single_thread_task_runner.h" #include "base/threading/non_thread_safe.h" #include "base/time/tick_clock.h" @@ -48,8 +49,8 @@ typedef base::Callback<void(CastTransportStatus status)> CastTransportStatusCallback; -typedef base::Callback<void(const std::vector<PacketEvent>&, - const std::vector<FrameEvent>&)> +typedef base::Callback<void(scoped_ptr<std::vector<FrameEvent>>, + scoped_ptr<std::vector<PacketEvent>>)> BulkRawEventsCallback; // The application should only trigger this class from the transport thread.
diff --git a/media/cast/net/cast_transport_sender_impl.cc b/media/cast/net/cast_transport_sender_impl.cc index 9a763de..936bf81e5 100644 --- a/media/cast/net/cast_transport_sender_impl.cc +++ b/media/cast/net/cast_transport_sender_impl.cc
@@ -95,15 +95,14 @@ : clock_(clock), status_callback_(status_callback), transport_task_runner_(transport_task_runner), - transport_( - external_transport ? - NULL : - new UdpTransport(net_log, - transport_task_runner, - local_end_point, - remote_end_point, - GetTransportSendBufferSize(*options), - status_callback)), + transport_(external_transport + ? nullptr + : new UdpTransport(net_log, + transport_task_runner, + local_end_point, + remote_end_point, + GetTransportSendBufferSize(*options), + status_callback)), pacer_(LookupOptionWithDefault(*options, kOptionPacerTargetBurstSize, kTargetBurstSize), @@ -111,7 +110,7 @@ kOptionPacerMaxBurstSize, kMaxBurstSize), clock, - &logging_, + raw_events_callback.is_null() ? nullptr : &recent_packet_events_, external_transport ? external_transport : transport_.get(), transport_task_runner), raw_events_callback_(raw_events_callback), @@ -122,8 +121,6 @@ DCHECK(clock_); if (!raw_events_callback_.is_null()) { DCHECK(raw_events_callback_interval > base::TimeDelta()); - event_subscriber_.reset(new SimpleEventSubscriber); - logging_.AddRawEventSubscriber(event_subscriber_.get()); transport_task_runner->PostDelayedTask( FROM_HERE, base::Bind(&CastTransportSenderImpl::SendRawEvents, @@ -161,8 +158,6 @@ if (transport_) { transport_->StopReceiving(); } - if (event_subscriber_.get()) - logging_.RemoveRawEventSubscriber(event_subscriber_.get()); } void CastTransportSenderImpl::InitializeAudio( @@ -341,13 +336,17 @@ } void CastTransportSenderImpl::SendRawEvents() { - DCHECK(event_subscriber_.get()); DCHECK(!raw_events_callback_.is_null()); - std::vector<PacketEvent> packet_events; - std::vector<FrameEvent> frame_events; - event_subscriber_->GetPacketEventsAndReset(&packet_events); - event_subscriber_->GetFrameEventsAndReset(&frame_events); - raw_events_callback_.Run(packet_events, frame_events); + + if (!recent_frame_events_.empty() || !recent_packet_events_.empty()) { + scoped_ptr<std::vector<FrameEvent>> frame_events( + new std::vector<FrameEvent>()); + frame_events->swap(recent_frame_events_); + scoped_ptr<std::vector<PacketEvent>> packet_events( + new std::vector<PacketEvent>()); + packet_events->swap(recent_packet_events_); + raw_events_callback_.Run(frame_events.Pass(), packet_events.Pass()); + } transport_task_runner_->PostDelayedTask( FROM_HERE, @@ -390,35 +389,40 @@ void CastTransportSenderImpl::OnReceivedLogMessage( EventMediaType media_type, const RtcpReceiverLogMessage& log) { - // Add received log messages into our log system. - RtcpReceiverLogMessage::const_iterator it = log.begin(); - for (; it != log.end(); ++it) { - uint32 rtp_timestamp = it->rtp_timestamp_; + if (raw_events_callback_.is_null()) + return; - RtcpReceiverEventLogMessages::const_iterator event_it = - it->event_log_messages_.begin(); - for (; event_it != it->event_log_messages_.end(); ++event_it) { - switch (event_it->type) { - case PACKET_RECEIVED: - logging_.InsertPacketEvent( - event_it->event_timestamp, event_it->type, - media_type, rtp_timestamp, - kFrameIdUnknown, event_it->packet_id, 0, 0); + // Add received log messages into our log system. + for (const RtcpReceiverFrameLogMessage& frame_log_message : log) { + for (const RtcpReceiverEventLogMessage& event_log_message : + frame_log_message.event_log_messages_) { + switch (event_log_message.type) { + case PACKET_RECEIVED: { + recent_packet_events_.push_back(PacketEvent()); + PacketEvent& receive_event = recent_packet_events_.back(); + receive_event.timestamp = event_log_message.event_timestamp; + receive_event.type = event_log_message.type; + receive_event.media_type = media_type; + receive_event.rtp_timestamp = frame_log_message.rtp_timestamp_; + receive_event.packet_id = event_log_message.packet_id; break; + } case FRAME_ACK_SENT: case FRAME_DECODED: - logging_.InsertFrameEvent( - event_it->event_timestamp, event_it->type, media_type, - rtp_timestamp, kFrameIdUnknown); + case FRAME_PLAYOUT: { + recent_frame_events_.push_back(FrameEvent()); + FrameEvent& frame_event = recent_frame_events_.back(); + frame_event.timestamp = event_log_message.event_timestamp; + frame_event.type = event_log_message.type; + frame_event.media_type = media_type; + frame_event.rtp_timestamp = frame_log_message.rtp_timestamp_; + if (event_log_message.type == FRAME_PLAYOUT) + frame_event.delay_delta = event_log_message.delay_delta; break; - case FRAME_PLAYOUT: - logging_.InsertFrameEventWithDelay( - event_it->event_timestamp, event_it->type, media_type, - rtp_timestamp, kFrameIdUnknown, event_it->delay_delta); - break; + } default: VLOG(2) << "Received log message via RTCP that we did not expect: " - << static_cast<int>(event_it->type); + << event_log_message.type; break; } }
diff --git a/media/cast/net/cast_transport_sender_impl.h b/media/cast/net/cast_transport_sender_impl.h index a5538e78..7a83afd 100644 --- a/media/cast/net/cast_transport_sender_impl.h +++ b/media/cast/net/cast_transport_sender_impl.h
@@ -25,6 +25,7 @@ #define MEDIA_CAST_NET_CAST_TRANSPORT_SENDER_IMPL_H_ #include <set> +#include <vector> #include "base/callback.h" #include "base/gtest_prod_util.h" @@ -35,7 +36,6 @@ #include "base/time/time.h" #include "media/cast/common/transport_encryption_handler.h" #include "media/cast/logging/logging_defines.h" -#include "media/cast/logging/simple_event_subscriber.h" #include "media/cast/net/cast_transport_config.h" #include "media/cast/net/cast_transport_sender.h" #include "media/cast/net/pacing/paced_sender.h" @@ -136,7 +136,7 @@ const DedupInfo& dedup_info); // If |raw_events_callback_| is non-null, calls it with events collected - // by |event_subscriber_| since last call. + // in |recent_frame_events_| and |recent_packet_events_| since last call. void SendRawEvents(); // Called when a packet is received. @@ -155,7 +155,10 @@ CastTransportStatusCallback status_callback_; scoped_refptr<base::SingleThreadTaskRunner> transport_task_runner_; - LoggingImpl logging_; + // FrameEvents and PacketEvents pending delivery via |raw_events_callback_|. + // Do not add elements to these when |raw_events_callback_.is_null()|. + std::vector<FrameEvent> recent_frame_events_; + std::vector<PacketEvent> recent_packet_events_; // Interface to a UDP socket. scoped_ptr<UdpTransport> transport_; @@ -178,9 +181,6 @@ TransportEncryptionHandler audio_encryptor_; TransportEncryptionHandler video_encryptor_; - // This is non-null iff |raw_events_callback_| is non-null. - scoped_ptr<SimpleEventSubscriber> event_subscriber_; - BulkRawEventsCallback raw_events_callback_; base::TimeDelta raw_events_callback_interval_;
diff --git a/media/cast/net/cast_transport_sender_impl_unittest.cc b/media/cast/net/cast_transport_sender_impl_unittest.cc index 921bddf5..9758f3e1 100644 --- a/media/cast/net/cast_transport_sender_impl_unittest.cc +++ b/media/cast/net/cast_transport_sender_impl_unittest.cc
@@ -66,8 +66,7 @@ class CastTransportSenderImplTest : public ::testing::Test { protected: - CastTransportSenderImplTest() - : num_times_callback_called_(0) { + CastTransportSenderImplTest() : num_times_logging_callback_called_(0) { testing_clock_.Advance( base::TimeDelta::FromMilliseconds(kStartMillisecond)); task_runner_ = new test::FakeSingleThreadTaskRunner(&testing_clock_); @@ -151,9 +150,9 @@ RtcpRttCallback()); } - void LogRawEvents(const std::vector<PacketEvent>& packet_events, - const std::vector<FrameEvent>& frame_events) { - num_times_callback_called_++; + void LogRawEvents(scoped_ptr<std::vector<FrameEvent>> frame_events, + scoped_ptr<std::vector<PacketEvent>> packet_events) { + num_times_logging_callback_called_++; } static void UpdateCastTransportStatus(CastTransportStatus status) { @@ -163,31 +162,26 @@ scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; scoped_ptr<CastTransportSenderImpl> transport_sender_; FakePacketSender transport_; - int num_times_callback_called_; + int num_times_logging_callback_called_; }; TEST_F(CastTransportSenderImplTest, InitWithoutLogging) { InitWithoutLogging(); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50)); - EXPECT_EQ(0, num_times_callback_called_); -} - -TEST_F(CastTransportSenderImplTest, InitWithLogging) { - InitWithLogging(); - task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50)); - EXPECT_EQ(5, num_times_callback_called_); + EXPECT_EQ(0, num_times_logging_callback_called_); } TEST_F(CastTransportSenderImplTest, InitWithOptions) { InitWithOptions(); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50)); - EXPECT_EQ(0, num_times_callback_called_); + EXPECT_EQ(0, num_times_logging_callback_called_); } TEST_F(CastTransportSenderImplTest, NacksCancelRetransmits) { - InitWithoutLogging(); + InitWithLogging(); InitializeVideo(); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50)); + EXPECT_EQ(0, num_times_logging_callback_called_); // A fake frame that will be decomposed into 4 packets. EncodedFrame fake_frame; @@ -199,6 +193,7 @@ transport_sender_->InsertFrame(kVideoSsrc, fake_frame); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); EXPECT_EQ(4, transport_.packets_sent()); + EXPECT_EQ(1, num_times_logging_callback_called_); // Resend packet 0. MissingFramesAndPacketsMap missing_packets; @@ -213,6 +208,7 @@ kVideoSsrc, missing_packets, true, dedup_info); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); + EXPECT_EQ(2, num_times_logging_callback_called_); RtcpCastMessage cast_message; cast_message.media_ssrc = kVideoSsrc; @@ -223,6 +219,7 @@ cast_message); transport_.SetPaused(false); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); + EXPECT_EQ(3, num_times_logging_callback_called_); // Resend one packet in the socket when unpaused. // Resend one more packet from NACK. @@ -230,9 +227,10 @@ } TEST_F(CastTransportSenderImplTest, CancelRetransmits) { - InitWithoutLogging(); + InitWithLogging(); InitializeVideo(); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50)); + EXPECT_EQ(0, num_times_logging_callback_called_); // A fake frame that will be decomposed into 4 packets. EncodedFrame fake_frame; @@ -244,6 +242,7 @@ transport_sender_->InsertFrame(kVideoSsrc, fake_frame); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); EXPECT_EQ(4, transport_.packets_sent()); + EXPECT_EQ(1, num_times_logging_callback_called_); // Resend all packets for frame 1. MissingFramesAndPacketsMap missing_packets; @@ -256,21 +255,25 @@ kVideoSsrc, missing_packets, true, dedup_info); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); + EXPECT_EQ(2, num_times_logging_callback_called_); + std::vector<uint32> cancel_sending_frames; cancel_sending_frames.push_back(1); transport_sender_->CancelSendingFrames(kVideoSsrc, cancel_sending_frames); transport_.SetPaused(false); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); + EXPECT_EQ(2, num_times_logging_callback_called_); // Resend one packet in the socket when unpaused. EXPECT_EQ(5, transport_.packets_sent()); } TEST_F(CastTransportSenderImplTest, Kickstart) { - InitWithoutLogging(); + InitWithLogging(); InitializeVideo(); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50)); + EXPECT_EQ(0, num_times_logging_callback_called_); // A fake frame that will be decomposed into 4 packets. EncodedFrame fake_frame; @@ -285,6 +288,7 @@ transport_.SetPaused(false); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); EXPECT_EQ(4, transport_.packets_sent()); + EXPECT_EQ(1, num_times_logging_callback_called_); // Resend 2 packets for frame 1. MissingFramesAndPacketsMap missing_packets; @@ -299,6 +303,7 @@ transport_sender_->ResendFrameForKickstart(kVideoSsrc, 1); transport_.SetPaused(false); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); + EXPECT_EQ(2, num_times_logging_callback_called_); // Resend one packet in the socket when unpaused. // Two more retransmission packets sent. @@ -306,10 +311,11 @@ } TEST_F(CastTransportSenderImplTest, DedupRetransmissionWithAudio) { - InitWithoutLogging(); + InitWithLogging(); InitializeAudio(); InitializeVideo(); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50)); + EXPECT_EQ(0, num_times_logging_callback_called_); // Send two audio frames. EncodedFrame fake_audio; @@ -334,6 +340,7 @@ cast_message); task_runner_->RunTasks(); EXPECT_EQ(2, transport_.packets_sent()); + EXPECT_EQ(0, num_times_logging_callback_called_); // Only 4 ms since last. // Send a fake video frame that will be decomposed into 4 packets. EncodedFrame fake_video; @@ -343,6 +350,7 @@ transport_sender_->InsertFrame(kVideoSsrc, fake_video); task_runner_->RunTasks(); EXPECT_EQ(6, transport_.packets_sent()); + EXPECT_EQ(0, num_times_logging_callback_called_); // Only 4 ms since last. // Retransmission is reject because audio is not acked yet. cast_message.media_ssrc = kVideoSsrc; @@ -354,6 +362,7 @@ cast_message); task_runner_->RunTasks(); EXPECT_EQ(6, transport_.packets_sent()); + EXPECT_EQ(1, num_times_logging_callback_called_); // Ack the second audio frame. cast_message.media_ssrc = kAudioSsrc; @@ -365,6 +374,7 @@ cast_message); task_runner_->RunTasks(); EXPECT_EQ(6, transport_.packets_sent()); + EXPECT_EQ(1, num_times_logging_callback_called_); // Only 6 ms since last. // Retransmission of video packet now accepted. cast_message.media_ssrc = kVideoSsrc; @@ -376,6 +386,10 @@ cast_message); task_runner_->RunTasks(); EXPECT_EQ(7, transport_.packets_sent()); + EXPECT_EQ(1, num_times_logging_callback_called_); // Only 8 ms since last. + + task_runner_->Sleep(base::TimeDelta::FromMilliseconds(2)); + EXPECT_EQ(2, num_times_logging_callback_called_); } } // namespace cast
diff --git a/media/cast/net/pacing/paced_sender.cc b/media/cast/net/pacing/paced_sender.cc index 6b39f074..b8642b1 100644 --- a/media/cast/net/pacing/paced_sender.cc +++ b/media/cast/net/pacing/paced_sender.cc
@@ -8,7 +8,6 @@ #include "base/bind.h" #include "base/debug/dump_without_crashing.h" #include "base/message_loop/message_loop.h" -#include "media/cast/logging/logging_impl.h" namespace media { namespace cast { @@ -45,11 +44,11 @@ size_t target_burst_size, size_t max_burst_size, base::TickClock* clock, - LoggingImpl* logging, + std::vector<PacketEvent>* recent_packet_events, PacketSender* transport, const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner) : clock_(clock), - logging_(logging), + recent_packet_events_(recent_packet_events), transport_(transport), transport_task_runner_(transport_task_runner), audio_ssrc_(0), @@ -62,8 +61,7 @@ current_burst_size_(0), state_(State_Unblocked), has_reached_upper_bound_once_(false), - weak_factory_(this) { -} + weak_factory_(this) {} PacedSender::~PacedSender() {} @@ -320,27 +318,37 @@ state_ = State_Unblocked; } -void PacedSender::LogPacketEvent(const Packet& packet, CastLoggingEvent event) { - // Get SSRC from packet and compare with the audio_ssrc / video_ssrc to see - // if the packet is audio or video. - DCHECK_GE(packet.size(), 12u); - base::BigEndianReader reader(reinterpret_cast<const char*>(&packet[8]), 4); +void PacedSender::LogPacketEvent(const Packet& packet, CastLoggingEvent type) { + if (!recent_packet_events_) + return; + + recent_packet_events_->push_back(PacketEvent()); + PacketEvent& event = recent_packet_events_->back(); + + // Populate the new PacketEvent by parsing the wire-format |packet|. + // + // TODO(miu): This parsing logic belongs in RtpParser. + event.timestamp = clock_->NowTicks(); + event.type = type; + base::BigEndianReader reader(reinterpret_cast<const char*>(&packet[0]), + packet.size()); + bool success = reader.Skip(4); + success &= reader.ReadU32(&event.rtp_timestamp); uint32 ssrc; - bool success = reader.ReadU32(&ssrc); - DCHECK(success); - bool is_audio; + success &= reader.ReadU32(&ssrc); if (ssrc == audio_ssrc_) { - is_audio = true; + event.media_type = AUDIO_EVENT; } else if (ssrc == video_ssrc_) { - is_audio = false; + event.media_type = VIDEO_EVENT; } else { DVLOG(3) << "Got unknown ssrc " << ssrc << " when logging packet event"; return; } - - EventMediaType media_type = is_audio ? AUDIO_EVENT : VIDEO_EVENT; - logging_->InsertSinglePacketEvent(clock_->NowTicks(), event, media_type, - packet); + success &= reader.Skip(2); + success &= reader.ReadU16(&event.packet_id); + success &= reader.ReadU16(&event.max_packet_id); + event.size = packet.size(); + DCHECK(success); } } // namespace cast
diff --git a/media/cast/net/pacing/paced_sender.h b/media/cast/net/pacing/paced_sender.h index 122cf55..a5fcfd17 100644 --- a/media/cast/net/pacing/paced_sender.h +++ b/media/cast/net/pacing/paced_sender.h
@@ -26,8 +26,6 @@ static const size_t kTargetBurstSize = 10; static const size_t kMaxBurstSize = 20; -class LoggingImpl; - // Use std::pair for free comparison operators. // { capture_time, ssrc, packet_id } // The PacketKey is designed to meet two criteria: @@ -79,13 +77,15 @@ public base::NonThreadSafe, public base::SupportsWeakPtr<PacedSender> { public: - // The |external_transport| should only be used by the Cast receiver and for + // |recent_packet_events| is an externally-owned vector where PacedSender will + // add PacketEvents related to sending, retransmission, and rejection. The + // |external_transport| should only be used by the Cast receiver and for // testing. PacedSender( size_t target_burst_size, // Should normally be kTargetBurstSize. size_t max_burst_size, // Should normally be kMaxBurstSize. base::TickClock* clock, - LoggingImpl* logging, + std::vector<PacketEvent>* recent_packet_events, PacketSender* external_transport, const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner); @@ -120,6 +120,9 @@ private: // Actually sends the packets to the transport. void SendStoredPackets(); + + // Convenience method for building a PacketEvent and storing it in the + // externally-owned container of |recent_packet_events_|. void LogPacketEvent(const Packet& packet, CastLoggingEvent event); // Returns true if retransmission for packet indexed by |packet_key| is @@ -163,9 +166,11 @@ // Returns true if the packet should have a higher priority. bool IsHighPriority(const PacketKey& packet_key) const; - base::TickClock* const clock_; // Not owned by this class. - LoggingImpl* const logging_; // Not owned by this class. - PacketSender* transport_; // Not owned by this class. + // These are externally-owned objects injected via the constructor. + base::TickClock* const clock_; + std::vector<PacketEvent>* const recent_packet_events_; + PacketSender* const transport_; + scoped_refptr<base::SingleThreadTaskRunner> transport_task_runner_; uint32 audio_ssrc_; uint32 video_ssrc_;
diff --git a/media/cast/net/pacing/paced_sender_unittest.cc b/media/cast/net/pacing/paced_sender_unittest.cc index 2387d42..13d5afd 100644 --- a/media/cast/net/pacing/paced_sender_unittest.cc +++ b/media/cast/net/pacing/paced_sender_unittest.cc
@@ -6,8 +6,6 @@ #include "base/big_endian.h" #include "base/test/simple_test_tick_clock.h" -#include "media/cast/logging/logging_impl.h" -#include "media/cast/logging/simple_event_subscriber.h" #include "media/cast/net/pacing/paced_sender.h" #include "media/cast/test/fake_single_thread_task_runner.h" #include "testing/gmock/include/gmock/gmock.h" @@ -27,6 +25,7 @@ static const int64 kStartMillisecond = INT64_C(12345678900000); static const uint32 kVideoSsrc = 0x1234; static const uint32 kAudioSsrc = 0x5678; +static const uint32 kFrameRtpTimestamp = 12345; class TestPacketSender : public PacketSender { public: @@ -59,24 +58,16 @@ class PacedSenderTest : public ::testing::Test { protected: PacedSenderTest() { - logging_.AddRawEventSubscriber(&subscriber_); testing_clock_.Advance( base::TimeDelta::FromMilliseconds(kStartMillisecond)); task_runner_ = new test::FakeSingleThreadTaskRunner(&testing_clock_); - paced_sender_.reset(new PacedSender(kTargetBurstSize, - kMaxBurstSize, - &testing_clock_, - &logging_, - &mock_transport_, - task_runner_)); + paced_sender_.reset(new PacedSender(kTargetBurstSize, kMaxBurstSize, + &testing_clock_, &packet_events_, + &mock_transport_, task_runner_)); paced_sender_->RegisterAudioSsrc(kAudioSsrc); paced_sender_->RegisterVideoSsrc(kVideoSsrc); } - ~PacedSenderTest() override { - logging_.RemoveRawEventSubscriber(&subscriber_); - } - static void UpdateCastTransportStatus(CastTransportStatus status) { NOTREACHED(); } @@ -98,12 +89,17 @@ PacketRef packet(new base::RefCountedData<Packet>); packet->data.resize(packet_size, kValue); - // Write ssrc to packet so that it can be recognized as a - // "video frame" for logging purposes. - base::BigEndianWriter writer( - reinterpret_cast<char*>(&packet->data[8]), 4); - bool success = writer.WriteU32(audio ? kAudioSsrc : kVideoSsrc); - DCHECK(success); + // Fill-in packet header fields to test the header parsing (for populating + // the logging events). + base::BigEndianWriter writer(reinterpret_cast<char*>(&packet->data[0]), + packet_size); + bool success = writer.Skip(4); + success &= writer.WriteU32(kFrameRtpTimestamp); + success &= writer.WriteU32(audio ? kAudioSsrc : kVideoSsrc); + success &= writer.Skip(2); + success &= writer.WriteU16(i); + success &= writer.WriteU16(num_of_packets_in_frame - 1); + CHECK(success); packets.push_back(std::make_pair(key, packet)); } return packets; @@ -123,8 +119,7 @@ return mock_transport_.expected_packet_size_.empty(); } - LoggingImpl logging_; - SimpleEventSubscriber subscriber_; + std::vector<PacketEvent> packet_events_; base::SimpleTestTickClock testing_clock_; TestPacketSender mock_transport_; scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; @@ -154,6 +149,7 @@ SendPacketVector packets = CreateSendPacketVector(kSize1, num_of_packets, false); + const base::TimeTicks earliest_event_timestamp = testing_clock_.NowTicks(); mock_transport_.AddExpectedSize(kSize1, 10); EXPECT_TRUE(paced_sender_->SendPackets(packets)); @@ -177,20 +173,21 @@ // Check that we don't get any more packets. EXPECT_TRUE(RunUntilEmpty(3)); + const base::TimeTicks latest_event_timestamp = testing_clock_.NowTicks(); - std::vector<PacketEvent> packet_events; - subscriber_.GetPacketEventsAndReset(&packet_events); - EXPECT_EQ(num_of_packets, static_cast<int>(packet_events.size())); - int sent_to_network_event_count = 0; - for (std::vector<PacketEvent>::iterator it = packet_events.begin(); - it != packet_events.end(); - ++it) { - if (it->type == PACKET_SENT_TO_NETWORK) - sent_to_network_event_count++; - else - FAIL() << "Got unexpected event type " << CastLoggingToString(it->type); + // Check that packet logging events match expected values. + EXPECT_EQ(num_of_packets, static_cast<int>(packet_events_.size())); + uint16 expected_packet_id = 0; + for (const PacketEvent& e : packet_events_) { + ASSERT_LE(earliest_event_timestamp, e.timestamp); + ASSERT_GE(latest_event_timestamp, e.timestamp); + ASSERT_EQ(PACKET_SENT_TO_NETWORK, e.type); + ASSERT_EQ(VIDEO_EVENT, e.media_type); + ASSERT_EQ(kFrameRtpTimestamp, e.rtp_timestamp); + ASSERT_EQ(num_of_packets - 1, e.max_packet_id); + ASSERT_EQ(expected_packet_id++, e.packet_id); + ASSERT_EQ(kSize1, e.size); } - EXPECT_EQ(num_of_packets, sent_to_network_event_count); } TEST_F(PacedSenderTest, PaceWithNack) { @@ -249,32 +246,28 @@ // No more packets. EXPECT_TRUE(RunUntilEmpty(5)); - std::vector<PacketEvent> packet_events; - subscriber_.GetPacketEventsAndReset(&packet_events); int expected_video_network_event_count = num_of_packets_in_frame; int expected_video_retransmitted_event_count = 2 * num_of_packets_in_nack; expected_video_retransmitted_event_count -= 2; // 2 packets deduped int expected_audio_network_event_count = num_of_packets_in_frame; EXPECT_EQ(expected_video_network_event_count + - expected_video_retransmitted_event_count + - expected_audio_network_event_count, - static_cast<int>(packet_events.size())); + expected_video_retransmitted_event_count + + expected_audio_network_event_count, + static_cast<int>(packet_events_.size())); int audio_network_event_count = 0; int video_network_event_count = 0; int video_retransmitted_event_count = 0; - for (std::vector<PacketEvent>::iterator it = packet_events.begin(); - it != packet_events.end(); - ++it) { - if (it->type == PACKET_SENT_TO_NETWORK) { - if (it->media_type == VIDEO_EVENT) + for (const PacketEvent& e : packet_events_) { + if (e.type == PACKET_SENT_TO_NETWORK) { + if (e.media_type == VIDEO_EVENT) video_network_event_count++; else audio_network_event_count++; - } else if (it->type == PACKET_RETRANSMITTED) { - if (it->media_type == VIDEO_EVENT) + } else if (e.type == PACKET_RETRANSMITTED) { + if (e.media_type == VIDEO_EVENT) video_retransmitted_event_count++; } else { - FAIL() << "Got unexpected event type " << CastLoggingToString(it->type); + FAIL() << "Got unexpected event type " << CastLoggingToString(e.type); } } EXPECT_EQ(expected_audio_network_event_count, audio_network_event_count);
diff --git a/media/cast/net/rtcp/receiver_rtcp_event_subscriber_unittest.cc b/media/cast/net/rtcp/receiver_rtcp_event_subscriber_unittest.cc index bd31d24..4980494 100644 --- a/media/cast/net/rtcp/receiver_rtcp_event_subscriber_unittest.cc +++ b/media/cast/net/rtcp/receiver_rtcp_event_subscriber_unittest.cc
@@ -37,56 +37,92 @@ void TearDown() final { if (event_subscriber_) { - cast_environment_->Logging()->RemoveRawEventSubscriber( - event_subscriber_.get()); + cast_environment_->logger()->Unsubscribe(event_subscriber_.get()); + event_subscriber_.reset(); } } void Init(EventMediaType type) { event_subscriber_.reset( new ReceiverRtcpEventSubscriber(kMaxEventEntries, type)); - cast_environment_->Logging()->AddRawEventSubscriber( - event_subscriber_.get()); + cast_environment_->logger()->Subscribe(event_subscriber_.get()); } void InsertEvents() { // Video events - cast_environment_->Logging()->InsertFrameEventWithDelay( - testing_clock_->NowTicks(), FRAME_PLAYOUT, VIDEO_EVENT, - /*rtp_timestamp*/ 100u, /*frame_id*/ 2u, - base::TimeDelta::FromMilliseconds(kDelayMs)); - cast_environment_->Logging()->InsertFrameEvent( - testing_clock_->NowTicks(), FRAME_DECODED, VIDEO_EVENT, - /*rtp_timestamp*/ 200u, /*frame_id*/ 1u); - cast_environment_->Logging()->InsertPacketEvent( - testing_clock_->NowTicks(), PACKET_RECEIVED, VIDEO_EVENT, - /*rtp_timestamp */ 200u, /*frame_id*/ 2u, /*packet_id*/ 1u, - /*max_packet_id*/ 10u, /*size*/ 1024u); + scoped_ptr<FrameEvent> playout_event(new FrameEvent()); + playout_event->timestamp = testing_clock_->NowTicks(); + playout_event->type = FRAME_PLAYOUT; + playout_event->media_type = VIDEO_EVENT; + playout_event->rtp_timestamp = 100u; + playout_event->frame_id = 2u; + playout_event->delay_delta = base::TimeDelta::FromMilliseconds(kDelayMs); + cast_environment_->logger()->DispatchFrameEvent(playout_event.Pass()); + + scoped_ptr<FrameEvent> decode_event(new FrameEvent()); + decode_event->timestamp = testing_clock_->NowTicks(); + decode_event->type = FRAME_DECODED; + decode_event->media_type = VIDEO_EVENT; + decode_event->rtp_timestamp = 200u; + decode_event->frame_id = 1u; + cast_environment_->logger()->DispatchFrameEvent(decode_event.Pass()); + + scoped_ptr<PacketEvent> receive_event(new PacketEvent()); + receive_event->timestamp = testing_clock_->NowTicks(); + receive_event->type = PACKET_RECEIVED; + receive_event->media_type = VIDEO_EVENT; + receive_event->rtp_timestamp = 200u; + receive_event->frame_id = 2u; + receive_event->packet_id = 1u; + receive_event->max_packet_id = 10u; + receive_event->size = 1024u; + cast_environment_->logger()->DispatchPacketEvent(receive_event.Pass()); // Audio events - cast_environment_->Logging()->InsertFrameEventWithDelay( - testing_clock_->NowTicks(), FRAME_PLAYOUT, AUDIO_EVENT, - /*rtp_timestamp*/ 300u, /*frame_id*/ 4u, - base::TimeDelta::FromMilliseconds(kDelayMs)); - cast_environment_->Logging()->InsertFrameEvent( - testing_clock_->NowTicks(), FRAME_DECODED, AUDIO_EVENT, - /*rtp_timestamp*/ 400u, /*frame_id*/ 3u); - cast_environment_->Logging()->InsertPacketEvent( - testing_clock_->NowTicks(), PACKET_RECEIVED, AUDIO_EVENT, - /*rtp_timestamp */ 400u, /*frame_id*/ 5u, /*packet_id*/ 1u, - /*max_packet_id*/ 10u, /*size*/ 128u); + playout_event.reset(new FrameEvent()); + playout_event->timestamp = testing_clock_->NowTicks(); + playout_event->type = FRAME_PLAYOUT; + playout_event->media_type = AUDIO_EVENT; + playout_event->rtp_timestamp = 300u; + playout_event->frame_id = 4u; + playout_event->delay_delta = base::TimeDelta::FromMilliseconds(kDelayMs); + cast_environment_->logger()->DispatchFrameEvent(playout_event.Pass()); + + decode_event.reset(new FrameEvent()); + decode_event->timestamp = testing_clock_->NowTicks(); + decode_event->type = FRAME_DECODED; + decode_event->media_type = AUDIO_EVENT; + decode_event->rtp_timestamp = 400u; + decode_event->frame_id = 3u; + cast_environment_->logger()->DispatchFrameEvent(decode_event.Pass()); + + receive_event.reset(new PacketEvent()); + receive_event->timestamp = testing_clock_->NowTicks(); + receive_event->type = PACKET_RECEIVED; + receive_event->media_type = AUDIO_EVENT; + receive_event->rtp_timestamp = 400u; + receive_event->frame_id = 5u; + receive_event->packet_id = 1u; + receive_event->max_packet_id = 10u; + receive_event->size = 128u; + cast_environment_->logger()->DispatchPacketEvent(receive_event.Pass()); // Unrelated events - cast_environment_->Logging()->InsertFrameEvent(testing_clock_->NowTicks(), - FRAME_CAPTURE_END, - VIDEO_EVENT, - /*rtp_timestamp*/ 100u, - /*frame_id*/ 1u); - cast_environment_->Logging()->InsertFrameEvent(testing_clock_->NowTicks(), - FRAME_CAPTURE_END, - AUDIO_EVENT, - /*rtp_timestamp*/ 100u, - /*frame_id*/ 1u); + scoped_ptr<FrameEvent> encode_event(new FrameEvent()); + encode_event->timestamp = testing_clock_->NowTicks(); + encode_event->type = FRAME_ENCODED; + encode_event->media_type = VIDEO_EVENT; + encode_event->rtp_timestamp = 100u; + encode_event->frame_id = 1u; + cast_environment_->logger()->DispatchFrameEvent(encode_event.Pass()); + + encode_event.reset(new FrameEvent()); + encode_event->timestamp = testing_clock_->NowTicks(); + encode_event->type = FRAME_ENCODED; + encode_event->media_type = AUDIO_EVENT; + encode_event->rtp_timestamp = 100u; + encode_event->frame_id = 1u; + cast_environment_->logger()->DispatchFrameEvent(encode_event.Pass()); } base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment. @@ -117,9 +153,13 @@ Init(VIDEO_EVENT); for (uint32 i = 1u; i <= 10u; ++i) { - cast_environment_->Logging()->InsertFrameEvent( - testing_clock_->NowTicks(), FRAME_DECODED, VIDEO_EVENT, - /*rtp_timestamp*/ i * 10, /*frame_id*/ i); + scoped_ptr<FrameEvent> decode_event(new FrameEvent()); + decode_event->timestamp = testing_clock_->NowTicks(); + decode_event->type = FRAME_DECODED; + decode_event->media_type = VIDEO_EVENT; + decode_event->rtp_timestamp = i * 10; + decode_event->frame_id = i; + cast_environment_->logger()->DispatchFrameEvent(decode_event.Pass()); } ReceiverRtcpEventSubscriber::RtcpEvents rtcp_events;
diff --git a/media/cast/net/rtp/rtp_packetizer_unittest.cc b/media/cast/net/rtp/rtp_packetizer_unittest.cc index 6669b5e8..12cafd6 100644 --- a/media/cast/net/rtp/rtp_packetizer_unittest.cc +++ b/media/cast/net/rtp/rtp_packetizer_unittest.cc
@@ -8,8 +8,6 @@ #include "base/memory/scoped_ptr.h" #include "base/test/simple_test_tick_clock.h" -#include "media/cast/logging/logging_impl.h" -#include "media/cast/logging/simple_event_subscriber.h" #include "media/cast/net/pacing/paced_sender.h" #include "media/cast/net/rtp/packet_storage.h" #include "media/cast/net/rtp/rtp_parser.h" @@ -114,11 +112,8 @@ config_.payload_type = kPayload; config_.max_payload_length = kMaxPacketLength; transport_.reset(new TestRtpPacketTransport(config_)); - pacer_.reset(new PacedSender(kTargetBurstSize, - kMaxBurstSize, - &testing_clock_, - &logging_, - transport_.get(), + pacer_.reset(new PacedSender(kTargetBurstSize, kMaxBurstSize, + &testing_clock_, nullptr, transport_.get(), task_runner_)); pacer_->RegisterVideoSsrc(config_.ssrc); rtp_packetizer_.reset(new RtpPacketizer( @@ -144,7 +139,6 @@ PacketStorage packet_storage_; RtpPacketizerConfig config_; scoped_ptr<TestRtpPacketTransport> transport_; - LoggingImpl logging_; scoped_ptr<PacedSender> pacer_; scoped_ptr<RtpPacketizer> rtp_packetizer_;
diff --git a/media/cast/receiver/audio_decoder.cc b/media/cast/receiver/audio_decoder.cc index f8a40be841..929deb5 100644 --- a/media/cast/receiver/audio_decoder.cc +++ b/media/cast/receiver/audio_decoder.cc
@@ -59,6 +59,15 @@ scoped_ptr<AudioBus> decoded_audio = Decode( encoded_frame->mutable_bytes(), static_cast<int>(encoded_frame->data.size())); + + scoped_ptr<FrameEvent> event(new FrameEvent()); + event->timestamp = cast_environment_->Clock()->NowTicks(); + event->type = FRAME_DECODED; + event->media_type = AUDIO_EVENT; + event->rtp_timestamp = encoded_frame->rtp_timestamp; + event->frame_id = encoded_frame->frame_id; + cast_environment_->logger()->DispatchFrameEvent(event.Pass()); + cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, base::Bind(callback,
diff --git a/media/cast/receiver/cast_receiver_impl.cc b/media/cast/receiver/cast_receiver_impl.cc index 5a01bb08..83d8bf7 100644 --- a/media/cast/receiver/cast_receiver_impl.cc +++ b/media/cast/receiver/cast_receiver_impl.cc
@@ -178,14 +178,20 @@ scoped_ptr<AudioBus> audio_bus, bool is_continuous) { DCHECK(cast_environment->CurrentlyOn(CastEnvironment::MAIN)); + if (audio_bus.get()) { - const base::TimeTicks now = cast_environment->Clock()->NowTicks(); - cast_environment->Logging()->InsertFrameEvent( - now, FRAME_DECODED, AUDIO_EVENT, rtp_timestamp, frame_id); - cast_environment->Logging()->InsertFrameEventWithDelay( - now, FRAME_PLAYOUT, AUDIO_EVENT, rtp_timestamp, frame_id, - playout_time - now); + // TODO(miu): This is reporting incorrect timestamp and delay. + // http://crbug.com/547251 + scoped_ptr<FrameEvent> playout_event(new FrameEvent()); + playout_event->timestamp = cast_environment->Clock()->NowTicks(); + playout_event->type = FRAME_PLAYOUT; + playout_event->media_type = AUDIO_EVENT; + playout_event->rtp_timestamp = rtp_timestamp; + playout_event->frame_id = frame_id; + playout_event->delay_delta = playout_time - playout_event->timestamp; + cast_environment->logger()->DispatchFrameEvent(playout_event.Pass()); } + callback.Run(audio_bus.Pass(), playout_time, is_continuous); } @@ -199,13 +205,18 @@ const scoped_refptr<VideoFrame>& video_frame, bool is_continuous) { DCHECK(cast_environment->CurrentlyOn(CastEnvironment::MAIN)); + if (video_frame.get()) { - const base::TimeTicks now = cast_environment->Clock()->NowTicks(); - cast_environment->Logging()->InsertFrameEvent( - now, FRAME_DECODED, VIDEO_EVENT, rtp_timestamp, frame_id); - cast_environment->Logging()->InsertFrameEventWithDelay( - now, FRAME_PLAYOUT, VIDEO_EVENT, rtp_timestamp, frame_id, - playout_time - now); + // TODO(miu): This is reporting incorrect timestamp and delay. + // http://crbug.com/547251 + scoped_ptr<FrameEvent> playout_event(new FrameEvent()); + playout_event->timestamp = cast_environment->Clock()->NowTicks(); + playout_event->type = FRAME_PLAYOUT; + playout_event->media_type = VIDEO_EVENT; + playout_event->rtp_timestamp = rtp_timestamp; + playout_event->frame_id = frame_id; + playout_event->delay_delta = playout_time - playout_event->timestamp; + cast_environment->logger()->DispatchFrameEvent(playout_event.Pass()); // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc TRACE_EVENT_INSTANT1( @@ -213,6 +224,7 @@ TRACE_EVENT_SCOPE_THREAD, "rtp_timestamp", rtp_timestamp); } + callback.Run(video_frame, playout_time, is_continuous); }
diff --git a/media/cast/receiver/frame_receiver.cc b/media/cast/receiver/frame_receiver.cc index c0b15df..3d89594 100644 --- a/media/cast/receiver/frame_receiver.cc +++ b/media/cast/receiver/frame_receiver.cc
@@ -55,13 +55,13 @@ DCHECK_GT(config.rtp_max_delay_ms, 0); DCHECK_GT(config.target_frame_rate, 0); decryptor_.Initialize(config.aes_key, config.aes_iv_mask); - cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber_); + cast_environment_->logger()->Subscribe(&event_subscriber_); memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_)); } FrameReceiver::~FrameReceiver() { DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); - cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber_); + cast_environment_->logger()->Unsubscribe(&event_subscriber_); } void FrameReceiver::RequestEncodedFrame( @@ -110,10 +110,17 @@ frame_id_to_rtp_timestamp_[rtp_header.frame_id & 0xff] = rtp_header.rtp_timestamp; - cast_environment_->Logging()->InsertPacketEvent( - now, PACKET_RECEIVED, event_media_type_, rtp_header.rtp_timestamp, - rtp_header.frame_id, rtp_header.packet_id, rtp_header.max_packet_id, - payload_size); + + scoped_ptr<PacketEvent> receive_event(new PacketEvent()); + receive_event->timestamp = now; + receive_event->type = PACKET_RECEIVED; + receive_event->media_type = event_media_type_; + receive_event->rtp_timestamp = rtp_header.rtp_timestamp; + receive_event->frame_id = rtp_header.frame_id; + receive_event->packet_id = rtp_header.packet_id; + receive_event->max_packet_id = rtp_header.max_packet_id; + receive_event->size = payload_size; + cast_environment_->logger()->DispatchPacketEvent(receive_event.Pass()); bool duplicate = false; const bool complete = @@ -165,9 +172,14 @@ base::TimeTicks now = cast_environment_->Clock()->NowTicks(); RtpTimestamp rtp_timestamp = frame_id_to_rtp_timestamp_[cast_message.ack_frame_id & 0xff]; - cast_environment_->Logging()->InsertFrameEvent( - now, FRAME_ACK_SENT, event_media_type_, - rtp_timestamp, cast_message.ack_frame_id); + + scoped_ptr<FrameEvent> ack_sent_event(new FrameEvent()); + ack_sent_event->timestamp = now; + ack_sent_event->type = FRAME_ACK_SENT; + ack_sent_event->media_type = event_media_type_; + ack_sent_event->rtp_timestamp = rtp_timestamp; + ack_sent_event->frame_id = cast_message.ack_frame_id; + cast_environment_->logger()->DispatchFrameEvent(ack_sent_event.Pass()); ReceiverRtcpEventSubscriber::RtcpEvents rtcp_events; event_subscriber_.GetRtcpEventsWithRedundancy(&rtcp_events);
diff --git a/media/cast/receiver/frame_receiver_unittest.cc b/media/cast/receiver/frame_receiver_unittest.cc index a92b93a7..79a6ef2 100644 --- a/media/cast/receiver/frame_receiver_unittest.cc +++ b/media/cast/receiver/frame_receiver_unittest.cc
@@ -154,7 +154,7 @@ CreateFrameReceiverOfVideo(); SimpleEventSubscriber event_subscriber; - cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber); + cast_environment_->logger()->Subscribe(&event_subscriber); const bool success = receiver_->ProcessPacket( scoped_ptr<Packet>(new Packet(kPacketSize, 0xff)).Pass()); @@ -164,14 +164,14 @@ std::vector<FrameEvent> frame_events; event_subscriber.GetFrameEventsAndReset(&frame_events); EXPECT_TRUE(frame_events.empty()); - cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber); + cast_environment_->logger()->Unsubscribe(&event_subscriber); } TEST_F(FrameReceiverTest, ReceivesOneFrame) { CreateFrameReceiverOfAudio(); SimpleEventSubscriber event_subscriber; - cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber); + cast_environment_->logger()->Subscribe(&event_subscriber); EXPECT_CALL(mock_transport_, SendRtcpFromRtpReceiver(_, _, _, _, _, _, _)) .WillRepeatedly(testing::Return()); @@ -205,14 +205,14 @@ EXPECT_EQ(AUDIO_EVENT, frame_events.begin()->media_type); EXPECT_EQ(rtp_header_.frame_id, frame_events.begin()->frame_id); EXPECT_EQ(rtp_header_.rtp_timestamp, frame_events.begin()->rtp_timestamp); - cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber); + cast_environment_->logger()->Unsubscribe(&event_subscriber); } TEST_F(FrameReceiverTest, ReceivesFramesSkippingWhenAppropriate) { CreateFrameReceiverOfAudio(); SimpleEventSubscriber event_subscriber; - cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber); + cast_environment_->logger()->Subscribe(&event_subscriber); EXPECT_CALL(mock_transport_, SendRtcpFromRtpReceiver(_, _, _, _, _, _, _)) .WillRepeatedly(testing::Return()); @@ -308,14 +308,14 @@ EXPECT_EQ(frame_offset * rtp_advance_per_frame, frame_events[i].rtp_timestamp); } - cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber); + cast_environment_->logger()->Unsubscribe(&event_subscriber); } TEST_F(FrameReceiverTest, ReceivesFramesRefusingToSkipAny) { CreateFrameReceiverOfVideo(); SimpleEventSubscriber event_subscriber; - cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber); + cast_environment_->logger()->Subscribe(&event_subscriber); EXPECT_CALL(mock_transport_, SendRtcpFromRtpReceiver(_, _, _, _, _, _, _)) .WillRepeatedly(testing::Return()); @@ -414,7 +414,7 @@ EXPECT_EQ(frame_offset * rtp_advance_per_frame, frame_events[i].rtp_timestamp); } - cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber); + cast_environment_->logger()->Unsubscribe(&event_subscriber); } } // namespace cast
diff --git a/media/cast/receiver/video_decoder.cc b/media/cast/receiver/video_decoder.cc index f9b24a420..534eac0 100644 --- a/media/cast/receiver/video_decoder.cc +++ b/media/cast/receiver/video_decoder.cc
@@ -61,6 +61,15 @@ const scoped_refptr<VideoFrame> decoded_frame = Decode( encoded_frame->mutable_bytes(), static_cast<int>(encoded_frame->data.size())); + + scoped_ptr<FrameEvent> decode_event(new FrameEvent()); + decode_event->timestamp = cast_environment_->Clock()->NowTicks(); + decode_event->type = FRAME_DECODED; + decode_event->media_type = VIDEO_EVENT; + decode_event->rtp_timestamp = encoded_frame->rtp_timestamp; + decode_event->frame_id = encoded_frame->frame_id; + cast_environment_->logger()->DispatchFrameEvent(decode_event.Pass()); + cast_environment_->PostTask( CastEnvironment::MAIN, FROM_HERE,
diff --git a/media/cast/sender/audio_encoder.cc b/media/cast/sender/audio_encoder.cc index f521b51..80d69fe9 100644 --- a/media/cast/sender/audio_encoder.cc +++ b/media/cast/sender/audio_encoder.cc
@@ -156,6 +156,9 @@ TRACE_EVENT_ASYNC_END1("cast.stream", "Audio Encode", audio_frame.get(), "Deadline utilization", audio_frame->deadline_utilization); + + audio_frame->encode_completion_time = + cast_environment_->Clock()->NowTicks(); cast_environment_->PostTask( CastEnvironment::MAIN, FROM_HERE,
diff --git a/media/cast/sender/audio_encoder.h b/media/cast/sender/audio_encoder.h index 61ac08b..aac20d76 100644 --- a/media/cast/sender/audio_encoder.h +++ b/media/cast/sender/audio_encoder.h
@@ -9,6 +9,7 @@ #include "base/memory/scoped_ptr.h" #include "base/threading/thread_checker.h" #include "media/base/audio_bus.h" +#include "media/cast/cast_defines.h" #include "media/cast/cast_environment.h" #include "media/cast/sender/sender_encoded_frame.h"
diff --git a/media/cast/sender/external_video_encoder.cc b/media/cast/sender/external_video_encoder.cc index 04226cf5..196b16e2 100644 --- a/media/cast/sender/external_video_encoder.cc +++ b/media/cast/sender/external_video_encoder.cc
@@ -30,16 +30,6 @@ enum { MAX_H264_QUANTIZER = 51 }; static const size_t kOutputBufferCount = 3; -void LogFrameEncodedEvent( - const scoped_refptr<media::cast::CastEnvironment>& cast_environment, - base::TimeTicks event_time, - media::cast::RtpTimestamp rtp_timestamp, - uint32 frame_id) { - cast_environment->Logging()->InsertFrameEvent( - event_time, media::cast::FRAME_ENCODED, media::cast::VIDEO_EVENT, - rtp_timestamp, frame_id); -} - } // namespace namespace media { @@ -318,7 +308,8 @@ const char kZeroEncodeDetails[] = "zero-encode-details"; const std::string details = base::StringPrintf( - "%c/%c,id=%" PRIu32 ",rtp=%" PRIu32 ",br=%d,q=%zu,act=%c,ref=%d", + ("%c/%c,id=%" PRIu32 ",rtp=%" PRIu32 ",br=%d,q=%" PRIuS + ",act=%c,ref=%d"), codec_profile_ == media::VP8PROFILE_ANY ? 'V' : 'H', key_frame ? 'K' : 'D', encoded_frame->frame_id, encoded_frame->rtp_timestamp, request.target_bit_rate / 1000, @@ -330,15 +321,8 @@ base::debug::ClearCrashKey(kZeroEncodeDetails); } - cast_environment_->PostTask( - CastEnvironment::MAIN, - FROM_HERE, - base::Bind(&LogFrameEncodedEvent, - cast_environment_, - cast_environment_->Clock()->NowTicks(), - encoded_frame->rtp_timestamp, - encoded_frame->frame_id)); - + encoded_frame->encode_completion_time = + cast_environment_->Clock()->NowTicks(); cast_environment_->PostTask( CastEnvironment::MAIN, FROM_HERE,
diff --git a/media/cast/sender/frame_sender.cc b/media/cast/sender/frame_sender.cc index ec37a6d..772cf01 100644 --- a/media/cast/sender/frame_sender.cc +++ b/media/cast/sender/frame_sender.cc
@@ -215,15 +215,19 @@ VLOG_IF(1, !is_audio_ && encoded_frame->dependency == EncodedFrame::KEY) << SENDER_SSRC << "Sending encoded key frame, id=" << frame_id; - cast_environment_->Logging()->InsertEncodedFrameEvent( - last_send_time_, FRAME_ENCODED, - is_audio_ ? AUDIO_EVENT : VIDEO_EVENT, - encoded_frame->rtp_timestamp, - frame_id, static_cast<int>(encoded_frame->data.size()), - encoded_frame->dependency == EncodedFrame::KEY, - requested_bitrate_before_encode, - encoded_frame->deadline_utilization, - encoded_frame->lossy_utilization); + scoped_ptr<FrameEvent> encode_event(new FrameEvent()); + encode_event->timestamp = encoded_frame->encode_completion_time; + encode_event->type = FRAME_ENCODED; + encode_event->media_type = is_audio_ ? AUDIO_EVENT : VIDEO_EVENT; + encode_event->rtp_timestamp = encoded_frame->rtp_timestamp; + encode_event->frame_id = frame_id; + encode_event->size = encoded_frame->data.size(); + encode_event->key_frame = encoded_frame->dependency == EncodedFrame::KEY; + encode_event->target_bitrate = requested_bitrate_before_encode; + encode_event->encoder_cpu_utilization = encoded_frame->deadline_utilization; + encode_event->idealized_bitrate_utilization = + encoded_frame->lossy_utilization; + cast_environment_->logger()->DispatchFrameEvent(encode_event.Pass()); RecordLatestFrameTimestamps(frame_id, encoded_frame->reference_time, @@ -321,12 +325,14 @@ base::TimeTicks now = cast_environment_->Clock()->NowTicks(); congestion_control_->AckFrame(cast_feedback.ack_frame_id, now); - cast_environment_->Logging()->InsertFrameEvent( - now, - FRAME_ACK_RECEIVED, - is_audio_ ? AUDIO_EVENT : VIDEO_EVENT, - GetRecordedRtpTimestamp(cast_feedback.ack_frame_id), - cast_feedback.ack_frame_id); + scoped_ptr<FrameEvent> ack_event(new FrameEvent()); + ack_event->timestamp = now; + ack_event->type = FRAME_ACK_RECEIVED; + ack_event->media_type = is_audio_ ? AUDIO_EVENT : VIDEO_EVENT; + ack_event->rtp_timestamp = + GetRecordedRtpTimestamp(cast_feedback.ack_frame_id); + ack_event->frame_id = cast_feedback.ack_frame_id; + cast_environment_->logger()->DispatchFrameEvent(ack_event.Pass()); const bool is_acked_out_of_order = static_cast<int32>(cast_feedback.ack_frame_id -
diff --git a/media/cast/sender/h264_vt_encoder.cc b/media/cast/sender/h264_vt_encoder.cc index 53aaf65..d02b738 100644 --- a/media/cast/sender/h264_vt_encoder.cc +++ b/media/cast/sender/h264_vt_encoder.cc
@@ -756,6 +756,8 @@ // TODO(miu): Compute and populate the |deadline_utilization| and // |lossy_utilization| performance metrics in |encoded_frame|. + encoded_frame->encode_completion_time = + encoder->cast_environment_->Clock()->NowTicks(); encoder->cast_environment_->PostTask( CastEnvironment::MAIN, FROM_HERE, base::Bind(request->frame_encoded_callback,
diff --git a/media/cast/sender/sender_encoded_frame.h b/media/cast/sender/sender_encoded_frame.h index 8a3b2fa..fa7787d 100644 --- a/media/cast/sender/sender_encoded_frame.h +++ b/media/cast/sender/sender_encoded_frame.h
@@ -5,6 +5,7 @@ #ifndef MEDIA_CAST_SENDER_SENDER_ENCODED_FRAME_H_ #define MEDIA_CAST_SENDER_SENDER_ENCODED_FRAME_H_ +#include "base/time/time.h" #include "media/cast/net/cast_transport_config.h" namespace media { @@ -42,6 +43,9 @@ // // TODO(miu): Rename to idealized_bitrate_utilization. double lossy_utilization; + + // The time at which the encode of the frame completed. + base::TimeTicks encode_completion_time; }; } // namespace cast
diff --git a/media/cast/sender/video_encoder_impl.cc b/media/cast/sender/video_encoder_impl.cc index d6b8e45..fcfac17 100644 --- a/media/cast/sender/video_encoder_impl.cc +++ b/media/cast/sender/video_encoder_impl.cc
@@ -45,6 +45,7 @@ scoped_ptr<SenderEncodedFrame> encoded_frame(new SenderEncodedFrame()); encoder->Encode(video_frame, reference_time, encoded_frame.get()); + encoded_frame->encode_completion_time = environment->Clock()->NowTicks(); environment->PostTask( CastEnvironment::MAIN, FROM_HERE,
diff --git a/media/cast/sender/video_sender.cc b/media/cast/sender/video_sender.cc index a96f2fd..f8890bb 100644 --- a/media/cast/sender/video_sender.cc +++ b/media/cast/sender/video_sender.cc
@@ -41,26 +41,35 @@ // Extract capture begin/end timestamps from |video_frame|'s metadata and log // it. -void LogVideoCaptureTimestamps(const CastEnvironment& cast_environment, +void LogVideoCaptureTimestamps(CastEnvironment* cast_environment, const media::VideoFrame& video_frame, RtpTimestamp rtp_timestamp) { - base::TimeTicks capture_begin_time; - base::TimeTicks capture_end_time; + scoped_ptr<FrameEvent> capture_begin_event(new FrameEvent()); + capture_begin_event->type = FRAME_CAPTURE_BEGIN; + capture_begin_event->media_type = VIDEO_EVENT; + capture_begin_event->rtp_timestamp = rtp_timestamp; + + scoped_ptr<FrameEvent> capture_end_event(new FrameEvent()); + capture_end_event->type = FRAME_CAPTURE_END; + capture_end_event->media_type = VIDEO_EVENT; + capture_end_event->rtp_timestamp = rtp_timestamp; + capture_end_event->width = video_frame.visible_rect().width(); + capture_end_event->height = video_frame.visible_rect().height(); + if (!video_frame.metadata()->GetTimeTicks( - media::VideoFrameMetadata::CAPTURE_BEGIN_TIME, &capture_begin_time) || + media::VideoFrameMetadata::CAPTURE_BEGIN_TIME, + &capture_begin_event->timestamp) || !video_frame.metadata()->GetTimeTicks( - media::VideoFrameMetadata::CAPTURE_END_TIME, &capture_end_time)) { + media::VideoFrameMetadata::CAPTURE_END_TIME, + &capture_end_event->timestamp)) { // The frame capture timestamps were not provided by the video capture // source. Simply log the events as happening right now. - capture_begin_time = capture_end_time = - cast_environment.Clock()->NowTicks(); + capture_begin_event->timestamp = capture_end_event->timestamp = + cast_environment->Clock()->NowTicks(); } - cast_environment.Logging()->InsertFrameEvent( - capture_begin_time, FRAME_CAPTURE_BEGIN, VIDEO_EVENT, rtp_timestamp, - kFrameIdUnknown); - cast_environment.Logging()->InsertCapturedVideoFrameEvent( - capture_end_time, rtp_timestamp, video_frame.visible_rect().width(), - video_frame.visible_rect().height()); + + cast_environment->logger()->DispatchFrameEvent(capture_begin_event.Pass()); + cast_environment->logger()->DispatchFrameEvent(capture_end_event.Pass()); } } // namespace @@ -142,7 +151,8 @@ const RtpTimestamp rtp_timestamp = TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency); - LogVideoCaptureTimestamps(*cast_environment_, *video_frame, rtp_timestamp); + LogVideoCaptureTimestamps(cast_environment_.get(), *video_frame, + rtp_timestamp); // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc TRACE_EVENT_INSTANT2(
diff --git a/media/cast/sender/video_sender_unittest.cc b/media/cast/sender/video_sender_unittest.cc index 4e4996b2..4b4c930 100644 --- a/media/cast/sender/video_sender_unittest.cc +++ b/media/cast/sender/video_sender_unittest.cc
@@ -386,7 +386,7 @@ ASSERT_EQ(STATUS_INITIALIZED, operational_status_); SimpleEventSubscriber event_subscriber; - cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber); + cast_environment_->logger()->Subscribe(&event_subscriber); int num_frames = 10; for (int i = 0; i < num_frames; i++) { @@ -412,7 +412,7 @@ EXPECT_EQ(VIDEO_EVENT, frame_events.rbegin()->media_type); EXPECT_EQ(num_frames - 1u, frame_events.rbegin()->frame_id); - cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber); + cast_environment_->logger()->Unsubscribe(&event_subscriber); } TEST_F(VideoSenderTest, StopSendingInTheAbsenceOfAck) {
diff --git a/media/cast/test/cast_benchmarks.cc b/media/cast/test/cast_benchmarks.cc index bea587e2..19d5edf 100644 --- a/media/cast/test/cast_benchmarks.cc +++ b/media/cast/test/cast_benchmarks.cc
@@ -84,9 +84,8 @@ EXPECT_EQ(STATUS_INITIALIZED, status); } -void IgnoreRawEvents(const std::vector<PacketEvent>& packet_events, - const std::vector<FrameEvent>& frame_events) { -} +void IgnoreRawEvents(scoped_ptr<std::vector<FrameEvent>> frame_events, + scoped_ptr<std::vector<PacketEvent>> packet_events) {} } // namespace
diff --git a/media/cast/test/end2end_unittest.cc b/media/cast/test/end2end_unittest.cc index e8137c0..b7880c4 100644 --- a/media/cast/test/end2end_unittest.cc +++ b/media/cast/test/end2end_unittest.cc
@@ -448,8 +448,7 @@ test_receiver_video_callback_(new TestReceiverVideoCallback()) { testing_clock_.Advance( base::TimeDelta::FromMilliseconds(kStartMillisecond)); - cast_environment_sender_->Logging()->AddRawEventSubscriber( - &event_subscriber_sender_); + cast_environment_sender_->logger()->Subscribe(&event_subscriber_sender_); } void Configure(Codec video_codec, @@ -575,28 +574,21 @@ void Create() { net::IPEndPoint dummy_endpoint; transport_sender_.reset(new CastTransportSenderImpl( - NULL, - testing_clock_sender_, - dummy_endpoint, - dummy_endpoint, + nullptr, testing_clock_sender_, dummy_endpoint, dummy_endpoint, make_scoped_ptr(new base::DictionaryValue), base::Bind(&UpdateCastTransportStatus), - base::Bind(&End2EndTest::LogRawEvents, base::Unretained(this)), - base::TimeDelta::FromMilliseconds(1), - task_runner_sender_, - PacketReceiverCallback(), - &sender_to_receiver_)); + base::Bind(&LogEventDispatcher::DispatchBatchOfEvents, + base::Unretained(cast_environment_sender_->logger())), + base::TimeDelta::FromMilliseconds(1), task_runner_sender_, + PacketReceiverCallback(), &sender_to_receiver_)); transport_receiver_.reset(new CastTransportSenderImpl( - NULL, - testing_clock_sender_, - dummy_endpoint, - dummy_endpoint, + nullptr, testing_clock_sender_, dummy_endpoint, dummy_endpoint, make_scoped_ptr(new base::DictionaryValue), base::Bind(&UpdateCastTransportStatus), - base::Bind(&End2EndTest::LogRawEvents, base::Unretained(this)), - base::TimeDelta::FromMilliseconds(1), - task_runner_sender_, + base::Bind(&LogEventDispatcher::DispatchBatchOfEvents, + base::Unretained(cast_environment_receiver_->logger())), + base::TimeDelta::FromMilliseconds(1), task_runner_sender_, base::Bind(&End2EndTest::ReceivePacket, base::Unretained(this)), &receiver_to_sender_)); @@ -639,8 +631,7 @@ } ~End2EndTest() override { - cast_environment_sender_->Logging()->RemoveRawEventSubscriber( - &event_subscriber_sender_); + cast_environment_sender_->logger()->Unsubscribe(&event_subscriber_sender_); } void TearDown() final { @@ -742,33 +733,6 @@ base::Unretained(this))); } - void LogRawEvents(const std::vector<PacketEvent>& packet_events, - const std::vector<FrameEvent>& frame_events) { - for (std::vector<media::cast::PacketEvent>::const_iterator it = - packet_events.begin(); - it != packet_events.end(); - ++it) { - cast_environment_sender_->Logging()->InsertPacketEvent(it->timestamp, - it->type, - it->media_type, - it->rtp_timestamp, - it->frame_id, - it->packet_id, - it->max_packet_id, - it->size); - } - for (std::vector<media::cast::FrameEvent>::const_iterator it = - frame_events.begin(); - it != frame_events.end(); - ++it) { - cast_environment_sender_->Logging()->InsertFrameEvent(it->timestamp, - it->type, - it->media_type, - it->rtp_timestamp, - it->frame_id); - } - } - FrameReceiverConfig audio_receiver_config_; FrameReceiverConfig video_receiver_config_; AudioSenderConfig audio_sender_config_; @@ -1251,6 +1215,8 @@ EXPECT_EQ(num_audio_frames_requested, test_receiver_audio_callback_->number_times_called()); + RunTasks(750); // Make sure that we send a RTCP message with the log. + // Logging tests. // Verify that all frames and all required events were logged. event_subscriber_sender_.GetFrameEventsAndReset(&frame_events_);
diff --git a/media/cast/test/sender.cc b/media/cast/test/sender.cc index 514bc74..5791ffe 100644 --- a/media/cast/test/sender.cc +++ b/media/cast/test/sender.cc
@@ -70,37 +70,6 @@ VLOG(1) << "Transport status: " << status; } -void LogRawEvents( - const scoped_refptr<media::cast::CastEnvironment>& cast_environment, - const std::vector<media::cast::PacketEvent>& packet_events, - const std::vector<media::cast::FrameEvent>& frame_events) { - VLOG(1) << "Got packet events from transport, size: " << packet_events.size(); - for (std::vector<media::cast::PacketEvent>::const_iterator it = - packet_events.begin(); - it != packet_events.end(); - ++it) { - cast_environment->Logging()->InsertPacketEvent(it->timestamp, - it->type, - it->media_type, - it->rtp_timestamp, - it->frame_id, - it->packet_id, - it->max_packet_id, - it->size); - } - VLOG(1) << "Got frame events from transport, size: " << frame_events.size(); - for (std::vector<media::cast::FrameEvent>::const_iterator it = - frame_events.begin(); - it != frame_events.end(); - ++it) { - cast_environment->Logging()->InsertFrameEvent(it->timestamp, - it->type, - it->media_type, - it->rtp_timestamp, - it->frame_id); - } -} - void QuitLoopOnInitializationResult(media::cast::OperationalStatus result) { CHECK(result == media::cast::STATUS_INITIALIZED) << "Cast sender uninitialized"; @@ -146,10 +115,8 @@ scoped_ptr<media::cast::EncodingEventSubscriber> audio_event_subscriber, base::ScopedFILE video_log_file, base::ScopedFILE audio_log_file) { - cast_environment->Logging()->RemoveRawEventSubscriber( - video_event_subscriber.get()); - cast_environment->Logging()->RemoveRawEventSubscriber( - audio_event_subscriber.get()); + cast_environment->logger()->Unsubscribe(video_event_subscriber.get()); + cast_environment->logger()->Unsubscribe(audio_event_subscriber.get()); VLOG(0) << "Dumping logging data for video stream."; media::cast::proto::LogMetadata log_metadata; @@ -175,22 +142,20 @@ void WriteStatsAndDestroySubscribers( const scoped_refptr<media::cast::CastEnvironment>& cast_environment, - scoped_ptr<media::cast::StatsEventSubscriber> video_event_subscriber, - scoped_ptr<media::cast::StatsEventSubscriber> audio_event_subscriber, + scoped_ptr<media::cast::StatsEventSubscriber> video_stats_subscriber, + scoped_ptr<media::cast::StatsEventSubscriber> audio_stats_subscriber, scoped_ptr<media::cast::ReceiverTimeOffsetEstimatorImpl> estimator) { - cast_environment->Logging()->RemoveRawEventSubscriber( - video_event_subscriber.get()); - cast_environment->Logging()->RemoveRawEventSubscriber( - audio_event_subscriber.get()); - cast_environment->Logging()->RemoveRawEventSubscriber(estimator.get()); + cast_environment->logger()->Unsubscribe(video_stats_subscriber.get()); + cast_environment->logger()->Unsubscribe(audio_stats_subscriber.get()); + cast_environment->logger()->Unsubscribe(estimator.get()); - scoped_ptr<base::DictionaryValue> stats = video_event_subscriber->GetStats(); + scoped_ptr<base::DictionaryValue> stats = video_stats_subscriber->GetStats(); std::string json; base::JSONWriter::WriteWithOptions( *stats, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json); VLOG(0) << "Video stats: " << json; - stats = audio_event_subscriber->GetStats(); + stats = audio_stats_subscriber->GetStats(); json.clear(); base::JSONWriter::WriteWithOptions( *stats, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json); @@ -272,16 +237,14 @@ // CastTransportSender initialization. scoped_ptr<media::cast::CastTransportSender> transport_sender = media::cast::CastTransportSender::Create( - NULL, // net log. - cast_environment->Clock(), - net::IPEndPoint(), - remote_endpoint, + nullptr, // net log. + cast_environment->Clock(), net::IPEndPoint(), remote_endpoint, make_scoped_ptr(new base::DictionaryValue), // options base::Bind(&UpdateCastTransportStatus), - base::Bind(&LogRawEvents, cast_environment), + base::Bind(&media::cast::LogEventDispatcher::DispatchBatchOfEvents, + base::Unretained(cast_environment->logger())), base::TimeDelta::FromSeconds(1), - media::cast::PacketReceiverCallback(), - io_message_loop.task_runner()); + media::cast::PacketReceiverCallback(), io_message_loop.task_runner()); // Set up event subscribers. scoped_ptr<media::cast::EncodingEventSubscriber> video_event_subscriber; @@ -294,15 +257,13 @@ media::cast::VIDEO_EVENT, 10000)); audio_event_subscriber.reset(new media::cast::EncodingEventSubscriber( media::cast::AUDIO_EVENT, 10000)); - cast_environment->Logging()->AddRawEventSubscriber( - video_event_subscriber.get()); - cast_environment->Logging()->AddRawEventSubscriber( - audio_event_subscriber.get()); + cast_environment->logger()->Subscribe(video_event_subscriber.get()); + cast_environment->logger()->Subscribe(audio_event_subscriber.get()); // Subscribers for stats. scoped_ptr<media::cast::ReceiverTimeOffsetEstimatorImpl> offset_estimator( new media::cast::ReceiverTimeOffsetEstimatorImpl()); - cast_environment->Logging()->AddRawEventSubscriber(offset_estimator.get()); + cast_environment->logger()->Subscribe(offset_estimator.get()); scoped_ptr<media::cast::StatsEventSubscriber> video_stats_subscriber( new media::cast::StatsEventSubscriber(media::cast::VIDEO_EVENT, cast_environment->Clock(), @@ -311,10 +272,8 @@ new media::cast::StatsEventSubscriber(media::cast::AUDIO_EVENT, cast_environment->Clock(), offset_estimator.get())); - cast_environment->Logging()->AddRawEventSubscriber( - video_stats_subscriber.get()); - cast_environment->Logging()->AddRawEventSubscriber( - audio_stats_subscriber.get()); + cast_environment->logger()->Subscribe(video_stats_subscriber.get()); + cast_environment->logger()->Subscribe(audio_stats_subscriber.get()); base::ScopedFILE video_log_file(fopen(video_log_file_name.c_str(), "w")); if (!video_log_file) {
diff --git a/media/cast/test/simulator.cc b/media/cast/test/simulator.cc index 540f377..f63a797 100644 --- a/media/cast/test/simulator.cc +++ b/media/cast/test/simulator.cc
@@ -121,45 +121,6 @@ LOG(INFO) << "Video status: " << status; } -void LogTransportEvents(const scoped_refptr<CastEnvironment>& env, - const std::vector<PacketEvent>& packet_events, - const std::vector<FrameEvent>& frame_events) { - for (std::vector<media::cast::PacketEvent>::const_iterator it = - packet_events.begin(); - it != packet_events.end(); - ++it) { - env->Logging()->InsertPacketEvent(it->timestamp, - it->type, - it->media_type, - it->rtp_timestamp, - it->frame_id, - it->packet_id, - it->max_packet_id, - it->size); - } - for (std::vector<media::cast::FrameEvent>::const_iterator it = - frame_events.begin(); - it != frame_events.end(); - ++it) { - if (it->type == FRAME_PLAYOUT) { - env->Logging()->InsertFrameEventWithDelay( - it->timestamp, - it->type, - it->media_type, - it->rtp_timestamp, - it->frame_id, - it->delay_delta); - } else { - env->Logging()->InsertFrameEvent( - it->timestamp, - it->type, - it->media_type, - it->rtp_timestamp, - it->frame_id); - } - } -} - // Maintains a queue of encoded video frames. // This works by tracking FRAME_CAPTURE_END and FRAME_ENCODED events. // If a video frame is detected to be encoded it transfers a frame @@ -356,8 +317,8 @@ 100 * 60 * 60); EncodingEventSubscriber video_event_subscriber(VIDEO_EVENT, 30 * 60 * 60); - sender_env->Logging()->AddRawEventSubscriber(&audio_event_subscriber); - sender_env->Logging()->AddRawEventSubscriber(&video_event_subscriber); + sender_env->logger()->Subscribe(&audio_event_subscriber); + sender_env->logger()->Subscribe(&video_event_subscriber); // Audio sender config. AudioSenderConfig audio_sender_config = GetDefaultAudioSenderConfig(); @@ -405,15 +366,12 @@ // Cast receiver. scoped_ptr<CastTransportSender> transport_receiver( new CastTransportSenderImpl( - NULL, - &testing_clock, - net::IPEndPoint(), - net::IPEndPoint(), + nullptr, &testing_clock, net::IPEndPoint(), net::IPEndPoint(), make_scoped_ptr(new base::DictionaryValue), base::Bind(&UpdateCastTransportStatus), - base::Bind(&LogTransportEvents, receiver_env), - base::TimeDelta::FromSeconds(1), - task_runner, + base::Bind(&LogEventDispatcher::DispatchBatchOfEvents, + base::Unretained(receiver_env->logger())), + base::TimeDelta::FromSeconds(1), task_runner, base::Bind(&PacketProxy::ReceivePacket, base::Unretained(&packet_proxy)), &receiver_to_sender)); @@ -426,19 +384,14 @@ packet_proxy.receiver = cast_receiver.get(); // Cast sender and transport sender. - scoped_ptr<CastTransportSender> transport_sender( - new CastTransportSenderImpl( - NULL, - &testing_clock, - net::IPEndPoint(), - net::IPEndPoint(), - make_scoped_ptr(new base::DictionaryValue), - base::Bind(&UpdateCastTransportStatus), - base::Bind(&LogTransportEvents, sender_env), - base::TimeDelta::FromSeconds(1), - task_runner, - PacketReceiverCallback(), - &sender_to_receiver)); + scoped_ptr<CastTransportSender> transport_sender(new CastTransportSenderImpl( + nullptr, &testing_clock, net::IPEndPoint(), net::IPEndPoint(), + make_scoped_ptr(new base::DictionaryValue), + base::Bind(&UpdateCastTransportStatus), + base::Bind(&LogEventDispatcher::DispatchBatchOfEvents, + base::Unretained(sender_env->logger())), + base::TimeDelta::FromSeconds(1), task_runner, PacketReceiverCallback(), + &sender_to_receiver)); scoped_ptr<CastSender> cast_sender( CastSender::Create(sender_env, transport_sender.get())); @@ -486,7 +439,7 @@ scoped_ptr<EncodedVideoFrameTracker> video_frame_tracker; if (quality_test) { video_frame_tracker.reset(new EncodedVideoFrameTracker(&media_source)); - sender_env->Logging()->AddRawEventSubscriber(video_frame_tracker.get()); + sender_env->logger()->Subscribe(video_frame_tracker.get()); } // Quality metrics computed for each frame decoded. @@ -544,6 +497,12 @@ elapsed_time += step; } + // Unsubscribe from logging events. + sender_env->logger()->Unsubscribe(&audio_event_subscriber); + sender_env->logger()->Unsubscribe(&video_event_subscriber); + if (quality_test) + sender_env->logger()->Unsubscribe(video_frame_tracker.get()); + // Get event logs for audio and video. media::cast::proto::LogMetadata audio_metadata, video_metadata; media::cast::FrameEventList audio_frame_events, video_frame_events;
diff --git a/media/cdm/ppapi/ppapi_cdm_adapter.gni b/media/cdm/ppapi/ppapi_cdm_adapter.gni index cf9327c..e7cf90ff 100644 --- a/media/cdm/ppapi/ppapi_cdm_adapter.gni +++ b/media/cdm/ppapi/ppapi_cdm_adapter.gni
@@ -30,6 +30,7 @@ "//media/cdm/ppapi/linked_ptr.h", "//media/cdm/ppapi/ppapi_cdm_adapter.cc", "//media/cdm/ppapi/ppapi_cdm_adapter.h", + "//media/cdm/supported_cdm_versions.cc", "//media/cdm/supported_cdm_versions.h", ] if (is_mac) {
diff --git a/media/cdm/supported_cdm_versions.cc b/media/cdm/supported_cdm_versions.cc new file mode 100644 index 0000000..6a8f896 --- /dev/null +++ b/media/cdm/supported_cdm_versions.cc
@@ -0,0 +1,50 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/cdm/supported_cdm_versions.h" + +#include "base/basictypes.h" +#include "media/cdm/api/content_decryption_module.h" + +namespace media { + +bool IsSupportedCdmModuleVersion(int version) { + switch (version) { + // Latest. + case CDM_MODULE_VERSION: + return true; + default: + return false; + } +} + +bool IsSupportedCdmInterfaceVersion(int version) { + static_assert(cdm::ContentDecryptionModule::kVersion == + cdm::ContentDecryptionModule_8::kVersion, + "update the code below"); + switch (version) { + // Supported versions in decreasing order. + case cdm::ContentDecryptionModule_8::kVersion: + case cdm::ContentDecryptionModule_7::kVersion: + return true; + default: + return false; + } +} + +bool IsSupportedCdmHostVersion(int version) { + static_assert(cdm::ContentDecryptionModule::Host::kVersion == + cdm::ContentDecryptionModule_8::Host::kVersion, + "update the code below"); + switch (version) { + // Supported versions in decreasing order. + case cdm::Host_8::kVersion: + case cdm::Host_7::kVersion: + return true; + default: + return false; + } +} + +} // namespace media
diff --git a/media/cdm/supported_cdm_versions.h b/media/cdm/supported_cdm_versions.h index 6609196..ffd91a59 100644 --- a/media/cdm/supported_cdm_versions.h +++ b/media/cdm/supported_cdm_versions.h
@@ -5,48 +5,24 @@ #ifndef MEDIA_CDM_SUPPORTED_CDM_VERSIONS_H_ #define MEDIA_CDM_SUPPORTED_CDM_VERSIONS_H_ -#include "media/cdm/api/content_decryption_module.h" +#ifdef USE_PPAPI_CDM_ADAPTER +// When building the adapter these functions need to be local. +#define FUNCTION_EXPORT +#else +#include "media/base/media_export.h" +#define FUNCTION_EXPORT MEDIA_EXPORT +#endif namespace media { -bool IsSupportedCdmModuleVersion(int version) { - switch (version) { - // Latest. - case CDM_MODULE_VERSION: - return true; - default: - return false; - } -} +FUNCTION_EXPORT bool IsSupportedCdmModuleVersion(int version); -bool IsSupportedCdmInterfaceVersion(int version) { - static_assert(cdm::ContentDecryptionModule::kVersion == - cdm::ContentDecryptionModule_8::kVersion, - "update the code below"); - switch (version) { - // Supported versions in decreasing order. - case cdm::ContentDecryptionModule_8::kVersion: - case cdm::ContentDecryptionModule_7::kVersion: - return true; - default: - return false; - } -} +FUNCTION_EXPORT bool IsSupportedCdmInterfaceVersion(int version); -bool IsSupportedCdmHostVersion(int version) { - static_assert(cdm::ContentDecryptionModule::Host::kVersion == - cdm::ContentDecryptionModule_8::Host::kVersion, - "update the code below"); - switch (version) { - // Supported versions in decreasing order. - case cdm::Host_8::kVersion: - case cdm::Host_7::kVersion: - return true; - default: - return false; - } -} +FUNCTION_EXPORT bool IsSupportedCdmHostVersion(int version); } // namespace media +#undef FUNCTION_EXPORT + #endif // MEDIA_CDM_SUPPORTED_CDM_VERSIONS_H_
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc index e831f53a..90decc76 100644 --- a/media/filters/gpu_video_decoder.cc +++ b/media/filters/gpu_video_decoder.cc
@@ -416,8 +416,8 @@ scoped_refptr<VideoFrame> frame(VideoFrame::WrapNativeTexture( PIXEL_FORMAT_ARGB, - gpu::MailboxHolder(pb.texture_mailbox(), decoder_texture_target_, - 0 /* sync_point */), + gpu::MailboxHolder(pb.texture_mailbox(), gpu::SyncToken(), + decoder_texture_target_), BindToCurrentLoop(base::Bind( &GpuVideoDecoder::ReleaseMailbox, weak_factory_.GetWeakPtr(), factories_, picture.picture_buffer_id(), pb.texture_id())), @@ -458,9 +458,9 @@ media::GpuVideoAcceleratorFactories* factories, int64 picture_buffer_id, uint32 texture_id, - uint32 release_sync_point) { + const gpu::SyncToken& release_sync_token) { DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread()); - factories->WaitSyncPoint(release_sync_point); + factories->WaitSyncToken(release_sync_token); if (decoder) { decoder->ReusePictureBuffer(picture_buffer_id);
diff --git a/media/filters/gpu_video_decoder.h b/media/filters/gpu_video_decoder.h index 432c2787..ac4d0e0c 100644 --- a/media/filters/gpu_video_decoder.h +++ b/media/filters/gpu_video_decoder.h
@@ -23,6 +23,10 @@ class SingleThreadTaskRunner; } +namespace gpu { +struct SyncToken; +} + namespace media { class DecoderBuffer; @@ -104,7 +108,7 @@ media::GpuVideoAcceleratorFactories* factories, int64 picture_buffer_id, uint32 texture_id, - uint32 release_sync_point); + const gpu::SyncToken& release_sync_token); // Indicate the picture buffer can be reused by the decoder. void ReusePictureBuffer(int64 picture_buffer_id);
diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc index 6b98b4f..4c74c2a 100644 --- a/media/filters/source_buffer_stream.cc +++ b/media/filters/source_buffer_stream.cc
@@ -893,29 +893,6 @@ const BufferQueue& new_buffers, BufferQueue* deleted_buffers) { DCHECK(deleted_buffers); - bool temporarily_select_range = false; - if (!track_buffer_.empty()) { - DecodeTimestamp tb_timestamp = track_buffer_.back()->GetDecodeTimestamp(); - DecodeTimestamp seek_timestamp = FindKeyframeAfterTimestamp(tb_timestamp); - if (seek_timestamp != kNoDecodeTimestamp() && - seek_timestamp < new_buffers.front()->GetDecodeTimestamp() && - range_for_next_append_ != ranges_.end() && - (*range_for_next_append_)->BelongsToRange(seek_timestamp)) { - DCHECK(tb_timestamp < seek_timestamp); - DCHECK(!selected_range_); - DCHECK(!(*range_for_next_append_)->HasNextBufferPosition()); - - // If there are GOPs between the end of the track buffer and the - // beginning of the new buffers, then temporarily seek the range - // so that the buffers between these two times will be deposited in - // |deleted_buffers| as if they were part of the current playback - // position. - // TODO(acolwell): Figure out a more elegant way to do this. - SeekAndSetSelectedRange(*range_for_next_append_, seek_timestamp); - temporarily_select_range = true; - } - } - // Handle splices between the existing buffers and the new buffers. If a // splice is generated the timestamp and duration of the first buffer in // |new_buffers| will be modified. @@ -966,10 +943,6 @@ } RemoveInternal(start, end, exclude_start, deleted_buffers); - - // Restore the range seek state if necessary. - if (temporarily_select_range) - SetSelectedRange(NULL); } bool SourceBufferStream::AreAdjacentInSequence(
diff --git a/media/media.gyp b/media/media.gyp index 9acf41ef..8a2d35d 100644 --- a/media/media.gyp +++ b/media/media.gyp
@@ -498,6 +498,8 @@ 'cdm/player_tracker_impl.h', 'cdm/proxy_decryptor.cc', 'cdm/proxy_decryptor.h', + 'cdm/supported_cdm_versions.cc', + 'cdm/supported_cdm_versions.h', 'ffmpeg/ffmpeg_common.cc', 'ffmpeg/ffmpeg_common.h', 'ffmpeg/ffmpeg_deleters.h', @@ -1447,9 +1449,10 @@ '../testing/gmock.gyp:gmock', '../testing/gtest.gyp:gtest', '../testing/perf/perf_test.gyp:perf_test', + '../third_party/libyuv/libyuv.gyp:libyuv', '../ui/gfx/gfx.gyp:gfx', - '../ui/gfx/gfx.gyp:gfx_test_support', '../ui/gfx/gfx.gyp:gfx_geometry', + '../ui/gfx/gfx.gyp:gfx_test_support', 'media', 'media_test_support', 'shared_memory_support',
diff --git a/media/media_cdm.gypi b/media/media_cdm.gypi index 0dd6a35..a6857f559 100644 --- a/media/media_cdm.gypi +++ b/media/media_cdm.gypi
@@ -61,10 +61,10 @@ 'cdm/ppapi/external_clear_key/libvpx_cdm_video_decoder.h', ], }], - ['os_posix == 1 and OS != "mac" and enable_pepper_cdms==1', { + ['os_posix == 1 and OS != "mac"', { 'type': 'loadable_module', # Must be in PRODUCT_DIR for ASAN bot. }], - ['(OS == "mac" or OS == "win") and enable_pepper_cdms==1', { + ['OS == "mac" or OS == "win"', { 'type': 'shared_library', }], ['OS == "mac"', { @@ -128,7 +128,7 @@ '<(SHARED_INTERMEDIATE_DIR)/clearkeycdmadapter_version.rc', ], 'conditions': [ - ['os_posix == 1 and OS != "mac" and enable_pepper_cdms==1', { + ['os_posix == 1 and OS != "mac"', { # Because clearkeycdm has type 'loadable_module' (see comments), # we must explicitly specify this dependency. 'libraries': [
diff --git a/media/media_cdm_adapter.gyp b/media/media_cdm_adapter.gyp index 8c81df1..876f884 100644 --- a/media/media_cdm_adapter.gyp +++ b/media/media_cdm_adapter.gyp
@@ -36,6 +36,7 @@ 'cdm/ppapi/cdm_logging.cc', 'cdm/ppapi/cdm_logging.h', 'cdm/ppapi/linked_ptr.h', + 'cdm/supported_cdm_versions.cc', 'cdm/supported_cdm_versions.h', ], 'conditions': [
diff --git a/media/renderers/gpu_video_accelerator_factories.h b/media/renderers/gpu_video_accelerator_factories.h index ae766edc..329f4b4 100644 --- a/media/renderers/gpu_video_accelerator_factories.h +++ b/media/renderers/gpu_video_accelerator_factories.h
@@ -28,6 +28,10 @@ class Size; } +namespace gpu { +struct SyncToken; +}; + namespace media { class VideoDecodeAccelerator; @@ -72,7 +76,7 @@ uint32 texture_target) = 0; virtual void DeleteTexture(uint32 texture_id) = 0; - virtual void WaitSyncPoint(uint32 sync_point) = 0; + virtual void WaitSyncToken(const gpu::SyncToken& sync_token) = 0; virtual scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer( const gfx::Size& size,
diff --git a/media/renderers/mock_gpu_video_accelerator_factories.h b/media/renderers/mock_gpu_video_accelerator_factories.h index 9710233f..f6c9dd7 100644 --- a/media/renderers/mock_gpu_video_accelerator_factories.h +++ b/media/renderers/mock_gpu_video_accelerator_factories.h
@@ -39,7 +39,7 @@ std::vector<gpu::Mailbox>* texture_mailboxes, uint32 texture_target)); MOCK_METHOD1(DeleteTexture, void(uint32 texture_id)); - MOCK_METHOD1(WaitSyncPoint, void(uint32 sync_point)); + MOCK_METHOD1(WaitSyncToken, void(const gpu::SyncToken& sync_token)); MOCK_METHOD0(GetTaskRunner, scoped_refptr<base::SingleThreadTaskRunner>()); MOCK_METHOD0(GetVideoDecodeAcceleratorSupportedProfiles, VideoDecodeAccelerator::SupportedProfiles());
diff --git a/media/renderers/skcanvas_video_renderer.cc b/media/renderers/skcanvas_video_renderer.cc index 4c0f1bf..675839b 100644 --- a/media/renderers/skcanvas_video_renderer.cc +++ b/media/renderers/skcanvas_video_renderer.cc
@@ -59,19 +59,19 @@ result == color_space; } -class SyncPointClientImpl : public VideoFrame::SyncPointClient { +class SyncTokenClientImpl : public VideoFrame::SyncTokenClient { public: - explicit SyncPointClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {} - ~SyncPointClientImpl() override {} + explicit SyncTokenClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {} + ~SyncTokenClientImpl() override {} uint32 InsertSyncPoint() override { return gl_->InsertSyncPointCHROMIUM(); } - void WaitSyncPoint(uint32 sync_point) override { - gl_->WaitSyncPointCHROMIUM(sync_point); + void WaitSyncToken(const gpu::SyncToken& sync_token) override { + gl_->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); } private: gpu::gles2::GLES2Interface* gl_; - DISALLOW_IMPLICIT_CONSTRUCTORS(SyncPointClientImpl); + DISALLOW_IMPLICIT_CONSTRUCTORS(SyncTokenClientImpl); }; skia::RefPtr<SkImage> NewSkImageFromVideoFrameYUVTextures( @@ -96,7 +96,7 @@ DCHECK(mailbox_holder.texture_target == GL_TEXTURE_2D || mailbox_holder.texture_target == GL_TEXTURE_EXTERNAL_OES || mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB); - gl->WaitSyncPointCHROMIUM(mailbox_holder.sync_point); + gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); source_textures[i] = gl->CreateAndConsumeTextureCHROMIUM( mailbox_holder.texture_target, mailbox_holder.mailbox.name); @@ -165,7 +165,7 @@ gl, video_frame, source_texture, GL_RGBA, GL_UNSIGNED_BYTE, true, false); } else { - gl->WaitSyncPointCHROMIUM(mailbox_holder.sync_point); + gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); source_texture = gl->CreateAndConsumeTextureCHROMIUM( mailbox_holder.texture_target, mailbox_holder.mailbox.name); } @@ -419,8 +419,8 @@ if (video_frame->HasTextures()) { DCHECK(gl); - SyncPointClientImpl client(gl); - video_frame->UpdateReleaseSyncPoint(&client); + SyncTokenClientImpl client(gl); + video_frame->UpdateReleaseSyncToken(&client); } } @@ -555,7 +555,7 @@ mailbox_holder.texture_target == GL_TEXTURE_EXTERNAL_OES) << mailbox_holder.texture_target; - gl->WaitSyncPointCHROMIUM(mailbox_holder.sync_point); + gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); uint32 source_texture = gl->CreateAndConsumeTextureCHROMIUM( mailbox_holder.texture_target, mailbox_holder.mailbox.name); @@ -572,8 +572,8 @@ gl->DeleteTextures(1, &source_texture); gl->Flush(); - SyncPointClientImpl client(gl); - video_frame->UpdateReleaseSyncPoint(&client); + SyncTokenClientImpl client(gl); + video_frame->UpdateReleaseSyncToken(&client); } void SkCanvasVideoRenderer::ResetCache() {
diff --git a/media/renderers/skcanvas_video_renderer_unittest.cc b/media/renderers/skcanvas_video_renderer_unittest.cc index 29e91683..d787bf0 100644 --- a/media/renderers/skcanvas_video_renderer_unittest.cc +++ b/media/renderers/skcanvas_video_renderer_unittest.cc
@@ -467,7 +467,7 @@ *textures = 1; } }; -void MailboxHoldersReleased(uint32 sync_point) {} +void MailboxHoldersReleased(const gpu::SyncToken& sync_token) {} } // namespace // Test that SkCanvasVideoRendererTest::Paint doesn't crash when GrContext is @@ -485,8 +485,8 @@ TestGLES2Interface gles2; Context3D context_3d(&gles2, gr_context.get()); gfx::Size size(kWidth, kHeight); - gpu::MailboxHolder mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_RECTANGLE_ARB, - 0); + gpu::MailboxHolder mailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), + GL_TEXTURE_RECTANGLE_ARB); auto video_frame = VideoFrame::WrapNativeTexture( PIXEL_FORMAT_UYVY, mailbox, base::Bind(MailboxHoldersReleased), size, gfx::Rect(size), size, kNoTimestamp());
diff --git a/media/video/gpu_memory_buffer_video_frame_pool.cc b/media/video/gpu_memory_buffer_video_frame_pool.cc index 13c73c7f..cad8463 100644 --- a/media/video/gpu_memory_buffer_video_frame_pool.cc +++ b/media/video/gpu_memory_buffer_video_frame_pool.cc
@@ -124,7 +124,7 @@ // longer referenced. // This could be called by any thread. void MailboxHoldersReleased(FrameResources* frame_resources, - uint32 sync_point); + const gpu::SyncToken& sync_token); // Return frame resources to the pool. This has to be called on the thread // where |media_task_runner_| is current. @@ -554,16 +554,16 @@ } if (plane_resource.image_id) gles2->BindTexImage2DCHROMIUM(texture_target_, plane_resource.image_id); - mailbox_holders[i] = - gpu::MailboxHolder(plane_resource.mailbox, texture_target_, 0); + mailbox_holders[i] = gpu::MailboxHolder(plane_resource.mailbox, + gpu::SyncToken(), texture_target_); } - // Insert a sync_point, this is needed to make sure that the textures the + // Insert a sync_token, this is needed to make sure that the textures the // mailboxes refer to will be used only after all the previous commands posted // in the command buffer have been processed. - unsigned sync_point = gles2->InsertSyncPointCHROMIUM(); + gpu::SyncToken sync_token(gles2->InsertSyncPointCHROMIUM()); for (size_t i = 0; i < num_planes; i += planes_per_copy) - mailbox_holders[i].sync_point = sync_point; + mailbox_holders[i].sync_token = sync_token; scoped_refptr<VideoFrame> frame; @@ -700,7 +700,7 @@ // Called when a VideoFrame is no longer references. void GpuMemoryBufferVideoFramePool::PoolImpl::MailboxHoldersReleased( FrameResources* frame_resources, - uint32 sync_point) { + const gpu::SyncToken& sync_token) { // Return the resource on the media thread. media_task_runner_->PostTask( FROM_HERE,
diff --git a/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc b/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc index 943c964..3a8318c 100644 --- a/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc +++ b/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc
@@ -130,7 +130,7 @@ EXPECT_NE(software_frame.get(), frame.get()); gpu::Mailbox mailbox = frame->mailbox_holder(0).mailbox; - unsigned sync_point = frame->mailbox_holder(0).sync_point; + const gpu::SyncToken sync_token = frame->mailbox_holder(0).sync_token; EXPECT_EQ(3u, gles2_->gen_textures); scoped_refptr<VideoFrame> frame2; @@ -153,7 +153,7 @@ EXPECT_NE(software_frame.get(), frame.get()); EXPECT_EQ(6u, gles2_->gen_textures); EXPECT_EQ(frame->mailbox_holder(0).mailbox, mailbox); - EXPECT_NE(frame->mailbox_holder(0).sync_point, sync_point); + EXPECT_NE(frame->mailbox_holder(0).sync_token, sync_token); } TEST_F(GpuMemoryBufferVideoFramePoolTest, DropResourceWhenSizeIsDifferent) {
diff --git a/mojo/converters/surfaces/DEPS b/mojo/converters/surfaces/DEPS index 3d09d22..9c166796 100644 --- a/mojo/converters/surfaces/DEPS +++ b/mojo/converters/surfaces/DEPS
@@ -6,6 +6,7 @@ "+components/mus/public", "+gpu/command_buffer/common/mailbox.h", "+gpu/command_buffer/common/mailbox_holder.h", + "+gpu/command_buffer/common/sync_token.h", "+third_party/skia/include", "+ui/gfx/geometry", "+ui/gfx/transform.h",
diff --git a/mojo/converters/surfaces/surfaces_type_converters.cc b/mojo/converters/surfaces/surfaces_type_converters.cc index 5f2f25d..8908fc8 100644 --- a/mojo/converters/surfaces/surfaces_type_converters.cc +++ b/mojo/converters/surfaces/surfaces_type_converters.cc
@@ -25,6 +25,7 @@ using mus::mojom::Color; using mus::mojom::ColorPtr; +using mus::mojom::CommandBufferNamespace; using mus::mojom::CompositorFrame; using mus::mojom::CompositorFramePtr; using mus::mojom::CompositorFrameMetadata; @@ -54,6 +55,8 @@ using mus::mojom::SurfaceIdPtr; using mus::mojom::SurfaceQuadState; using mus::mojom::SurfaceQuadStatePtr; +using mus::mojom::SyncToken; +using mus::mojom::SyncTokenPtr; using mus::mojom::TextureQuadState; using mus::mojom::TextureQuadStatePtr; using mus::mojom::TileQuadState; @@ -527,12 +530,38 @@ } // static +SyncTokenPtr TypeConverter<SyncTokenPtr, gpu::SyncToken>::Convert( + const gpu::SyncToken& input) { + DCHECK(!input.HasData() || input.verified_flush()); + SyncTokenPtr sync_token(SyncToken::New()); + sync_token->verified_flush = input.verified_flush(); + sync_token->namespace_id = + static_cast<CommandBufferNamespace>(input.namespace_id()); + sync_token->command_buffer_id = input.command_buffer_id(); + sync_token->release_count = input.release_count(); + return sync_token.Pass(); +} + +// static +gpu::SyncToken TypeConverter<gpu::SyncToken, SyncTokenPtr>::Convert( + const SyncTokenPtr& input) { + const gpu::CommandBufferNamespace namespace_id = + static_cast<gpu::CommandBufferNamespace>(input->namespace_id); + gpu::SyncToken sync_token(namespace_id, input->command_buffer_id, + input->release_count); + if (input->verified_flush) + sync_token.SetVerifyFlush(); + + return sync_token; +} + +// static MailboxHolderPtr TypeConverter<MailboxHolderPtr, gpu::MailboxHolder>::Convert( const gpu::MailboxHolder& input) { MailboxHolderPtr holder(MailboxHolder::New()); holder->mailbox = Mailbox::From<gpu::Mailbox>(input.mailbox); + holder->sync_token = SyncToken::From<gpu::SyncToken>(input.sync_token); holder->texture_target = input.texture_target; - holder->sync_point = input.sync_point; return holder.Pass(); } @@ -541,8 +570,8 @@ const MailboxHolderPtr& input) { gpu::MailboxHolder holder; holder.mailbox = input->mailbox.To<gpu::Mailbox>(); + holder.sync_token = input->sync_token.To<gpu::SyncToken>(); holder.texture_target = input->texture_target; - holder.sync_point = input->sync_point; return holder; } @@ -603,7 +632,7 @@ const cc::ReturnedResource& input) { ReturnedResourcePtr returned = ReturnedResource::New(); returned->id = input.id; - returned->sync_point = input.sync_point; + returned->sync_token = SyncToken::From<gpu::SyncToken>(input.sync_token); returned->count = input.count; returned->lost = input.lost; return returned.Pass(); @@ -615,7 +644,7 @@ const ReturnedResourcePtr& input) { cc::ReturnedResource returned; returned.id = input->id; - returned.sync_point = input->sync_point; + returned.sync_token = input->sync_token.To<gpu::SyncToken>(); returned.count = input->count; returned.lost = input->lost; return returned;
diff --git a/mojo/converters/surfaces/surfaces_type_converters.h b/mojo/converters/surfaces/surfaces_type_converters.h index 4bcb0db..a172a8d 100644 --- a/mojo/converters/surfaces/surfaces_type_converters.h +++ b/mojo/converters/surfaces/surfaces_type_converters.h
@@ -14,6 +14,7 @@ #include "components/mus/public/interfaces/surface_id.mojom.h" #include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/common/mailbox_holder.h" +#include "gpu/command_buffer/common/sync_token.h" #include "mojo/converters/surfaces/mojo_surfaces_export.h" #include "third_party/skia/include/core/SkColor.h" @@ -106,6 +107,17 @@ template <> struct MOJO_SURFACES_EXPORT + TypeConverter<mus::mojom::SyncTokenPtr, gpu::SyncToken> { + static mus::mojom::SyncTokenPtr Convert(const gpu::SyncToken& input); +}; +template <> +struct MOJO_SURFACES_EXPORT + TypeConverter<gpu::SyncToken, mus::mojom::SyncTokenPtr> { + static gpu::SyncToken Convert(const mus::mojom::SyncTokenPtr& input); +}; + +template <> +struct MOJO_SURFACES_EXPORT TypeConverter<mus::mojom::MailboxHolderPtr, gpu::MailboxHolder> { static mus::mojom::MailboxHolderPtr Convert(const gpu::MailboxHolder& input); };
diff --git a/mojo/converters/surfaces/tests/surface_unittest.cc b/mojo/converters/surfaces/tests/surface_unittest.cc index fceaa32..3d0694b 100644 --- a/mojo/converters/surfaces/tests/surface_unittest.cc +++ b/mojo/converters/surfaces/tests/surface_unittest.cc
@@ -402,17 +402,17 @@ gpu::Mailbox mailbox; mailbox.Generate(); uint32_t texture_target = GL_TEXTURE_2D; - uint32_t sync_point = 7u; - gpu::MailboxHolder holder(mailbox, texture_target, sync_point); + gpu::SyncToken sync_token(7u); + gpu::MailboxHolder holder(mailbox, sync_token, texture_target); MailboxHolderPtr mus_holder = MailboxHolder::From(holder); EXPECT_EQ(texture_target, mus_holder->texture_target); - EXPECT_EQ(sync_point, mus_holder->sync_point); + EXPECT_EQ(sync_token, mus_holder->sync_token.To<gpu::SyncToken>()); gpu::MailboxHolder round_trip_holder = mus_holder.To<gpu::MailboxHolder>(); EXPECT_EQ(mailbox, round_trip_holder.mailbox); EXPECT_EQ(texture_target, round_trip_holder.texture_target); - EXPECT_EQ(sync_point, round_trip_holder.sync_point); + EXPECT_EQ(sync_token, round_trip_holder.sync_token); } TEST(SurfaceLibTest, TransferableResource) { @@ -446,32 +446,32 @@ EXPECT_EQ(mailbox_holder.mailbox, round_trip_resource.mailbox_holder.mailbox); EXPECT_EQ(mailbox_holder.texture_target, round_trip_resource.mailbox_holder.texture_target); - EXPECT_EQ(mailbox_holder.sync_point, - round_trip_resource.mailbox_holder.sync_point); + EXPECT_EQ(mailbox_holder.sync_token, + round_trip_resource.mailbox_holder.sync_token); EXPECT_EQ(is_software, round_trip_resource.is_software); } TEST(SurfaceLibTest, ReturnedResource) { uint32_t id = 5u; - uint32_t sync_point = 24u; + gpu::SyncToken sync_token(24u); int count = 2; bool lost = false; cc::ReturnedResource resource; resource.id = id; - resource.sync_point = sync_point; + resource.sync_token = sync_token; resource.count = count; resource.lost = lost; ReturnedResourcePtr mus_resource = ReturnedResource::From(resource); EXPECT_EQ(id, mus_resource->id); - EXPECT_EQ(sync_point, mus_resource->sync_point); + EXPECT_EQ(sync_token, mus_resource->sync_token.To<gpu::SyncToken>()); EXPECT_EQ(count, mus_resource->count); EXPECT_EQ(lost, mus_resource->lost); cc::ReturnedResource round_trip_resource = mus_resource.To<cc::ReturnedResource>(); EXPECT_EQ(id, round_trip_resource.id); - EXPECT_EQ(sync_point, round_trip_resource.sync_point); + EXPECT_EQ(sync_token, round_trip_resource.sync_token); EXPECT_EQ(count, round_trip_resource.count); EXPECT_EQ(lost, round_trip_resource.lost); }
diff --git a/mojo/package_manager/package_manager_impl.cc b/mojo/package_manager/package_manager_impl.cc index c1880c5..37bef8b 100644 --- a/mojo/package_manager/package_manager_impl.cc +++ b/mojo/package_manager/package_manager_impl.cc
@@ -84,7 +84,7 @@ if (resolved_url.SchemeIsFile()) { // LocalFetcher uses the network service to infer MIME types from URLs. // Skip this for mojo URLs to avoid recursively loading the network service. - if (!network_service_ && !url.SchemeIs("mojo")) { + if (!network_service_ && !url.SchemeIs("mojo") && !url.SchemeIs("exe")) { shell::ConnectToService(application_manager_, GURL("mojo:network_service"), &network_service_); }
diff --git a/mojo/platform_handle/BUILD.gn b/mojo/platform_handle/BUILD.gn index e6a1dc0..f224dd9 100644 --- a/mojo/platform_handle/BUILD.gn +++ b/mojo/platform_handle/BUILD.gn
@@ -25,9 +25,10 @@ source_set("defs") { visibility = [ ":platform_handle", + "//components/font_service/public/cpp", "//components/mus/gles2", "//mojo/gles2", - "//mojo/runner:native_application_support", + "//mojo/runner:platform_handle", ] sources = [
diff --git a/mojo/public/mojo_application.gni b/mojo/public/mojo_application.gni index 705ddc6..364a092 100644 --- a/mojo/public/mojo_application.gni +++ b/mojo/public/mojo_application.gni
@@ -96,10 +96,13 @@ deps = rebase_path([ "mojo/public/c/system", + "mojo/public/platform/native:gles2", "mojo/public/platform/native:system", ], ".", mojo_root) + deps += [ "//mojo/platform_handle" ] + deps += mojo_deps if (defined(invoker.public_deps)) { public_deps = invoker.public_deps
diff --git a/mojo/runner/BUILD.gn b/mojo/runner/BUILD.gn index 2ef7910..6dd96424 100644 --- a/mojo/runner/BUILD.gn +++ b/mojo/runner/BUILD.gn
@@ -200,10 +200,8 @@ check_includes = false } -source_set("native_application_support") { +source_set("platform_handle") { sources = [ - "native_application_support.cc", - "native_application_support.h", "platform_handle_impl.cc", ] @@ -212,9 +210,21 @@ ] deps = [ + "//mojo/platform_handle:defs", + "//third_party/mojo/src/mojo/edk/embedder:embedder", + ] +} + +source_set("native_application_support") { + sources = [ + "native_application_support.cc", + "native_application_support.h", + ] + + deps = [ + ":platform_handle", "//base", "//mojo/gles2", - "//mojo/platform_handle:defs", "//mojo/shell", ]
diff --git a/mojo/runner/child/BUILD.gn b/mojo/runner/child/BUILD.gn index 82ea546..fae89c08 100644 --- a/mojo/runner/child/BUILD.gn +++ b/mojo/runner/child/BUILD.gn
@@ -23,7 +23,9 @@ ":interfaces", "//base", "//mojo/application/public/interfaces", + "//mojo/gles2", "//mojo/message_pump", + "//mojo/runner:platform_handle", "//third_party/mojo/src/mojo/edk/system", ] } @@ -91,6 +93,7 @@ "//mojo/application/public/cpp", "//mojo/application/public/interfaces", "//mojo/common:common_base", + "//mojo/gles2", "//mojo/message_pump", "//mojo/runner:init", "//third_party/mojo/src/mojo/edk/embedder:embedder",
diff --git a/mojo/runner/child/native_apptest_target.cc b/mojo/runner/child/native_apptest_target.cc index ebe8750d..a4b2301 100644 --- a/mojo/runner/child/native_apptest_target.cc +++ b/mojo/runner/child/native_apptest_target.cc
@@ -29,34 +29,6 @@ namespace { -class EDKState : public mojo::embedder::ProcessDelegate { - public: - EDKState() : io_thread_("io_thread") { - mojo::embedder::Init(); - - // Create and start our I/O thread. - base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0); - CHECK(io_thread_.StartWithOptions(io_thread_options)); - io_runner_ = io_thread_.task_runner().get(); - CHECK(io_runner_.get()); - - // TODO(vtl): This should be SLAVE, not NONE. - mojo::embedder::InitIPCSupport(mojo::embedder::ProcessType::NONE, - io_runner_, this, io_runner_, - mojo::embedder::ScopedPlatformHandle()); - } - ~EDKState() override { mojo::embedder::ShutdownIPCSupport(); } - - private: - // mojo::embedder::ProcessDelegate: - void OnShutdownComplete() override {} - - base::Thread io_thread_; - scoped_refptr<base::SingleThreadTaskRunner> io_runner_; - - DISALLOW_COPY_AND_ASSIGN(EDKState); -}; - class TargetApplicationDelegate : public mojo::ApplicationDelegate, public mojo::runner::test::TestNativeService, @@ -91,6 +63,17 @@ DISALLOW_COPY_AND_ASSIGN(TargetApplicationDelegate); }; +class ProcessDelegate : public mojo::embedder::ProcessDelegate { + public: + ProcessDelegate() {} + ~ProcessDelegate() override {} + + private: + void OnShutdownComplete() override {} + + DISALLOW_COPY_AND_ASSIGN(ProcessDelegate); +}; + } // namespace int main(int argc, char** argv) { @@ -108,7 +91,17 @@ #endif { - EDKState edk; + mojo::embedder::Init(); + + ProcessDelegate process_delegate; + base::Thread io_thread("io_thread"); + base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0); + CHECK(io_thread.StartWithOptions(io_thread_options)); + + mojo::embedder::InitIPCSupport( + mojo::embedder::ProcessType::NONE, io_thread.task_runner().get(), + &process_delegate, io_thread.task_runner().get(), + mojo::embedder::ScopedPlatformHandle()); mojo::InterfaceRequest<mojo::Application> application_request; scoped_ptr<mojo::runner::RunnerConnection> connection( @@ -122,6 +115,8 @@ } connection.reset(); + + mojo::embedder::ShutdownIPCSupport(); } return 0;
diff --git a/net/BUILD.gn b/net/BUILD.gn index e98add3..a5d6638 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -1213,10 +1213,8 @@ dest = _net_unittests_apk_assets_dir if (v8_use_external_startup_data) { - sources = [ - "$root_out_dir/natives_blob.bin", - "$root_out_dir/snapshot_blob.bin", - ] + renaming_sources = v8_external_startup_data_renaming_sources + renaming_destinations = v8_external_startup_data_renaming_destinations deps = [ "//v8", ]
diff --git a/net/android/traffic_stats_unittest.cc b/net/android/traffic_stats_unittest.cc index 0d53c246..de49ec53 100644 --- a/net/android/traffic_stats_unittest.cc +++ b/net/android/traffic_stats_unittest.cc
@@ -15,10 +15,10 @@ namespace { TEST(TrafficStatsAndroidTest, BasicsTest) { - test_server::EmbeddedTestServer embedded_test_server; + EmbeddedTestServer embedded_test_server; embedded_test_server.ServeFilesFromDirectory( base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); - ASSERT_TRUE(embedded_test_server.InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server.Start()); int64_t tx_bytes_before_request = -1; int64_t rx_bytes_before_request = -1; @@ -48,10 +48,10 @@ } TEST(TrafficStatsAndroidTest, UIDBasicsTest) { - test_server::EmbeddedTestServer embedded_test_server; + EmbeddedTestServer embedded_test_server; embedded_test_server.ServeFilesFromDirectory( base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); - ASSERT_TRUE(embedded_test_server.InitializeAndWaitUntilReady()); + ASSERT_TRUE(embedded_test_server.Start()); int64_t tx_bytes_before_request = -1; int64_t rx_bytes_before_request = -1;
diff --git a/net/base/network_quality_estimator_unittest.cc b/net/base/network_quality_estimator_unittest.cc index 3c54fd5..038ab62 100644 --- a/net/base/network_quality_estimator_unittest.cc +++ b/net/base/network_quality_estimator_unittest.cc
@@ -46,7 +46,7 @@ // Set up embedded test server. embedded_test_server_.ServeFilesFromDirectory( base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); - EXPECT_TRUE(embedded_test_server_.InitializeAndWaitUntilReady()); + EXPECT_TRUE(embedded_test_server_.Start()); embedded_test_server_.RegisterRequestHandler(base::Bind( &TestNetworkQualityEstimator::HandleRequest, base::Unretained(this))); } @@ -99,7 +99,7 @@ std::string current_network_id_; // Embedded server used for testing. - net::test_server::EmbeddedTestServer embedded_test_server_; + net::EmbeddedTestServer embedded_test_server_; DISALLOW_COPY_AND_ASSIGN(TestNetworkQualityEstimator); };
diff --git a/net/cert/nss_cert_database_chromeos.cc b/net/cert/nss_cert_database_chromeos.cc index 63d969c..0cffac5 100644 --- a/net/cert/nss_cert_database_chromeos.cc +++ b/net/cert/nss_cert_database_chromeos.cc
@@ -42,7 +42,7 @@ } void NSSCertDatabaseChromeOS::ListCerts( - const base::Callback<void(scoped_ptr<CertificateList> certs)>& callback) { + const NSSCertDatabase::ListCertsCallback& callback) { scoped_ptr<CertificateList> certs(new CertificateList()); // base::Pased will NULL out |certs|, so cache the underlying pointer here.
diff --git a/net/cert_net/cert_net_fetcher_impl_unittest.cc b/net/cert_net/cert_net_fetcher_impl_unittest.cc index e3337a0..7f5e54a 100644 --- a/net/cert_net/cert_net_fetcher_impl_unittest.cc +++ b/net/cert_net/cert_net_fetcher_impl_unittest.cc
@@ -11,7 +11,7 @@ #include "net/cert/mock_cert_verifier.h" #include "net/dns/mock_host_resolver.h" #include "net/http/http_server_properties_impl.h" -#include "net/test/spawned_test_server/spawned_test_server.h" +#include "net/test/embedded_test_server/embedded_test_server.h" #include "net/url_request/url_request_job_factory_impl.h" #include "net/url_request/url_request_test_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -135,15 +135,13 @@ class CertNetFetcherImplTest : public PlatformTest { public: - CertNetFetcherImplTest() - : test_server_(SpawnedTestServer::TYPE_HTTP, - SpawnedTestServer::kLocalhost, - base::FilePath(kDocRoot)) { + CertNetFetcherImplTest() { + test_server_.AddDefaultHandlers(base::FilePath(kDocRoot)); context_.set_network_delegate(&network_delegate_); } protected: - SpawnedTestServer test_server_; + EmbeddedTestServer test_server_; TestNetworkDelegate network_delegate_; RequestContext context_; }; @@ -168,17 +166,17 @@ TestFetchCallback callback3; // Request a URL with Content-Type "application/pkix-cert" - GURL url1 = test_server_.GetURL("files/cert.crt"); + GURL url1 = test_server_.GetURL("/cert.crt"); scoped_ptr<CertNetFetcher::Request> request1 = StartRequest(&fetcher, url1, callback1); // Request a URL with Content-Type "application/pkix-crl" - GURL url2 = test_server_.GetURL("files/root.crl"); + GURL url2 = test_server_.GetURL("/root.crl"); scoped_ptr<CertNetFetcher::Request> request2 = StartRequest(&fetcher, url2, callback2); // Request a URL with Content-Type "application/pkcs7-mime" - GURL url3 = test_server_.GetURL("files/certs.p7c"); + GURL url3 = test_server_.GetURL("/certs.p7c"); scoped_ptr<CertNetFetcher::Request> request3 = StartRequest(&fetcher, url3, callback3); @@ -205,7 +203,7 @@ CertNetFetcherImpl fetcher(&context_); TestFetchCallback callback; - GURL url = test_server_.GetURL("files/foo.txt"); + GURL url = test_server_.GetURL("/foo.txt"); scoped_ptr<CertNetFetcher::Request> request = StartRequest(&fetcher, url, callback); scoped_ptr<FetchResult> result = callback.WaitForResult(); @@ -222,7 +220,7 @@ // Response was HTTP status 404. { TestFetchCallback callback; - GURL url = test_server_.GetURL("files/404.html"); + GURL url = test_server_.GetURL("/404.html"); scoped_ptr<CertNetFetcher::Request> request = StartRequest(&fetcher, url, callback); scoped_ptr<FetchResult> result = callback.WaitForResult(); @@ -232,7 +230,7 @@ // Response was HTTP status 500. { TestFetchCallback callback; - GURL url = test_server_.GetURL("files/500.html"); + GURL url = test_server_.GetURL("/500.html"); scoped_ptr<CertNetFetcher::Request> request = StartRequest(&fetcher, url, callback); scoped_ptr<FetchResult> result = callback.WaitForResult(); @@ -247,7 +245,7 @@ CertNetFetcherImpl fetcher(&context_); TestFetchCallback callback; - GURL url = test_server_.GetURL("files/downloadable.js"); + GURL url = test_server_.GetURL("/downloadable.js"); scoped_ptr<CertNetFetcher::Request> request = StartRequest(&fetcher, url, callback); scoped_ptr<FetchResult> result = callback.WaitForResult(); @@ -262,7 +260,7 @@ CertNetFetcherImpl fetcher(&context_); // Fetch a URL whose HTTP headers make it cacheable for 1 hour. - GURL url(test_server_.GetURL("files/cacheable_1hr.crt")); + GURL url(test_server_.GetURL("/cacheable_1hr.crt")); { TestFetchCallback callback; @@ -275,7 +273,7 @@ EXPECT_EQ(1, network_delegate_.created_requests()); // Kill the HTTP server. - ASSERT_TRUE(test_server_.Stop()); + ASSERT_TRUE(test_server_.ShutdownAndWaitUntilComplete()); // Fetch again -- will fail unless served from cache. { @@ -298,7 +296,7 @@ // This file has a response body 12 bytes long. So setting the maximum to 11 // bytes will cause it to fail. - GURL url(test_server_.GetURL("files/certs.p7c")); + GURL url(test_server_.GetURL("/certs.p7c")); TestFetchCallback callback; scoped_ptr<CertNetFetcher::Request> request = fetcher.FetchCaIssuers( url, CertNetFetcher::DEFAULT, 11, callback.callback()); @@ -314,7 +312,7 @@ CertNetFetcherImpl fetcher(&context_); - GURL url(test_server_.GetURL("slow/certs.p7c?5")); + GURL url(test_server_.GetURL("/slow/certs.p7c?5")); TestFetchCallback callback; scoped_ptr<CertNetFetcher::Request> request = fetcher.FetchCaIssuers( url, 10, CertNetFetcher::DEFAULT, callback.callback()); @@ -329,7 +327,7 @@ CertNetFetcherImpl fetcher(&context_); - GURL url(test_server_.GetURL("files/gzipped_crl")); + GURL url(test_server_.GetURL("/gzipped_crl")); TestFetchCallback callback; scoped_ptr<CertNetFetcher::Request> request = StartRequest(&fetcher, url, callback); @@ -363,7 +361,7 @@ CertNetFetcherImpl fetcher(&context_); - GURL url(test_server_.GetURL("files/redirect_https")); + GURL url(test_server_.GetURL("/redirect_https")); TestFetchCallback callback; scoped_ptr<CertNetFetcher::Request> request = @@ -409,15 +407,15 @@ TestFetchCallback callback2; TestFetchCallback callback3; - GURL url1 = test_server_.GetURL("files/cert.crt"); + GURL url1 = test_server_.GetURL("/cert.crt"); scoped_ptr<CertNetFetcher::Request> request1 = StartRequest(&fetcher, url1, callback1); - GURL url2 = test_server_.GetURL("files/root.crl"); + GURL url2 = test_server_.GetURL("/root.crl"); scoped_ptr<CertNetFetcher::Request> request2 = StartRequest(&fetcher, url2, callback2); - GURL url3 = test_server_.GetURL("files/certs.p7c"); + GURL url3 = test_server_.GetURL("/certs.p7c"); scoped_ptr<CertNetFetcher::Request> request3 = StartRequest(&fetcher, url3, callback3); @@ -461,12 +459,12 @@ TestFetchCallback callback2; TestFetchCallback callback3; - GURL url1 = test_server_.GetURL("files/cert.crt"); + GURL url1 = test_server_.GetURL("/cert.crt"); scoped_ptr<CertNetFetcher::Request> request1 = StartRequest(&fetcher, url1, callback1); - GURL url2 = test_server_.GetURL("files/certs.p7c"); + GURL url2 = test_server_.GetURL("/certs.p7c"); scoped_ptr<CertNetFetcher::Request> request2 = StartRequest(&fetcher, url2, callback2); @@ -499,7 +497,7 @@ scoped_ptr<CertNetFetcherImpl> fetcher(new CertNetFetcherImpl(&context_)); - GURL url(test_server_.GetURL("slow/certs.p7c?20")); + GURL url(test_server_.GetURL("/slow/certs.p7c?20")); TestFetchCallback callback; scoped_ptr<CertNetFetcher::Request> request = StartRequest(fetcher.get(), url, callback); @@ -515,8 +513,8 @@ CertNetFetcherImpl fetcher(&context_); - GURL url1 = test_server_.GetURL("files/cert.crt"); - GURL url2 = test_server_.GetURL("files/root.crl"); + GURL url1 = test_server_.GetURL("/cert.crt"); + GURL url2 = test_server_.GetURL("/root.crl"); // Issue 3 requests for url1, and 3 requests for url2 TestFetchCallback callback1; @@ -578,7 +576,7 @@ TestFetchCallback callback2; TestFetchCallback callback3; - GURL url = test_server_.GetURL("files/cert.crt"); + GURL url = test_server_.GetURL("/cert.crt"); scoped_ptr<CertNetFetcher::Request> request1 = StartRequest(&fetcher, url, callback1); @@ -611,7 +609,7 @@ TestFetchCallback callback[3]; scoped_ptr<CertNetFetcher::Request> request[3]; - GURL url = test_server_.GetURL("files/cert.crt"); + GURL url = test_server_.GetURL("/cert.crt"); for (size_t i = 0; i < arraysize(callback); ++i) { request[i] = StartRequest(&fetcher, url, callback[i]); @@ -638,7 +636,7 @@ // Deleted by callback2. CertNetFetcher* fetcher = new CertNetFetcherImpl(&context_); - GURL url = test_server_.GetURL("files/cert.crt"); + GURL url = test_server_.GetURL("/cert.crt"); TestFetchCallback callback[4]; scoped_ptr<CertNetFetcher::Request> reqs[4]; @@ -670,7 +668,7 @@ CertNetFetcherImpl fetcher(&context_); - GURL url = test_server_.GetURL("files/cert.crt"); + GURL url = test_server_.GetURL("/cert.crt"); TestFetchCallback callback[5]; scoped_ptr<CertNetFetcher::Request> req[5]; @@ -702,7 +700,7 @@ CertNetFetcherImpl fetcher(&context_); - GURL url = test_server_.GetURL("files/cert.crt"); + GURL url = test_server_.GetURL("/cert.crt"); TestFetchCallback callback[4]; scoped_ptr<CertNetFetcher::Request> request[4]; @@ -734,7 +732,7 @@ CertNetFetcherImpl fetcher(&context_); - GURL url = test_server_.GetURL("files/cert.crt"); + GURL url = test_server_.GetURL("/cert.crt"); TestFetchCallback callback1; scoped_ptr<CertNetFetcher::Request> request1 =
diff --git a/net/data/ssl/certificates/quic_test.example.com.key.sct b/net/data/ssl/certificates/quic_test.example.com.key.sct new file mode 100644 index 0000000..55b0b42 --- /dev/null +++ b/net/data/ssl/certificates/quic_test.example.com.key.sct
@@ -0,0 +1 @@ +fake sct for test.example.com
diff --git a/net/http/transport_security_state_static.h b/net/http/transport_security_state_static.h index ce8c696..45da2ec10 100644 --- a/net/http/transport_security_state_static.h +++ b/net/http/transport_security_state_static.h
@@ -3472,7 +3472,7 @@ 0xed, 0x34, 0x58, 0x57, 0xff, 0xe8, 0xc1, 0x0c, 0x76, 0x37, 0xf6, 0x0b, 0xac, 0xeb, 0xfb, 0xfe, 0x24, 0xee, 0xb3, 0xac, 0xae, 0x22, 0xc9, 0x66, 0x7b, 0x6a, 0x37, 0xf9, 0x5c, 0xe3, 0x5d, 0xda, 0x68, 0xb2, 0xee, 0xe2, - 0x87, 0x5f, 0x2a, 0xa3, 0x0c, 0xc4, 0x1d, 0x47, 0x5e, 0x57, 0xea, 0xce, + 0x87, 0x5f, 0x2a, 0xa3, 0x0c, 0xc4, 0x1d, 0x45, 0x5e, 0x57, 0xea, 0xce, 0xa6, 0x9e, 0xbe, 0x8b, 0xbf, 0x0a, 0xa1, 0x44, 0xf6, 0x9b, 0xae, 0x8e, 0x9d, 0x60, 0x1d, 0x72, 0x93, 0x9d, 0x6e, 0x48, 0xd4, 0x60, 0x85, 0x34, 0xf8, 0xdc, 0xf6, 0xff, 0x9f, 0x71, 0xcd, 0xfd, 0x0a, 0x1d, 0x7f, 0xa7, @@ -3482,7 +3482,7 @@ 0xb9, 0x19, 0xb9, 0x4a, 0x97, 0xf7, 0xfd, 0xfb, 0xef, 0x9e, 0x4d, 0xd9, 0x3a, 0xe8, 0xd1, 0xd4, 0x14, 0xc1, 0x3a, 0x42, 0x29, 0x5a, 0x49, 0xd8, 0x77, 0x7f, 0x23, 0xe8, 0x1a, 0xfc, 0xeb, 0xff, 0x92, 0x4f, 0xa7, 0x1f, - 0xdb, 0x9a, 0x3a, 0xff, 0xfe, 0xea, 0x7b, 0xb9, 0xa1, 0xc5, 0xff, 0xae, + 0xdb, 0x9a, 0x2a, 0xff, 0xfe, 0xea, 0x7b, 0xb9, 0xa1, 0xc5, 0xff, 0xae, 0xbc, 0x8e, 0xbf, 0xd1, 0x2f, 0x3f, 0x5c, 0x27, 0x54, 0x23, 0x37, 0x10, 0xb8, 0xb5, 0x69, 0x1d, 0x69, 0x1d, 0x69, 0x1d, 0x50, 0x6c, 0x14, 0x10, 0x41, 0x0b, 0xff, 0xf7, 0xb4, 0x8d, 0xc1, 0xe4, 0x0e, 0x07, 0x14, 0x3a, @@ -3491,7 +3491,7 @@ 0x0a, 0x7e, 0x53, 0x7f, 0xff, 0xfd, 0xd8, 0xf6, 0x93, 0x5a, 0x8f, 0x75, 0x23, 0x80, 0x5b, 0xca, 0x5e, 0x50, 0xeb, 0x93, 0x73, 0xae, 0x85, 0x9d, 0x7f, 0xfe, 0x81, 0xfe, 0x52, 0x8f, 0x77, 0x17, 0xf6, 0x00, 0x75, 0xff, - 0xf2, 0x0f, 0xf2, 0xcd, 0x72, 0x12, 0x4f, 0xa3, 0xaa, 0x48, 0xa3, 0xf2, + 0xf2, 0x0f, 0xf2, 0xcd, 0x72, 0x12, 0x4f, 0xa2, 0xaa, 0x48, 0xa3, 0xf2, 0xb5, 0xcd, 0x56, 0x17, 0xbd, 0x67, 0x84, 0x28, 0x61, 0xb9, 0x91, 0x95, 0x35, 0x33, 0x90, 0xfa, 0x75, 0xe1, 0x85, 0x3e, 0xa1, 0x01, 0xe3, 0x1d, 0x8f, 0xbb, 0x62, 0xdf, 0x61, 0x71, 0x7f, 0xf9, 0x55, 0xbc, 0x95, 0xce,
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json index fe4267f..5465026 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -4011,16 +4011,16 @@ { "name": "ryanhowell.io", "include_subdomains": true, "mode": "force-https" }, { "name": "ryansmithphotography.com", "include_subdomains": true, "mode": "force-https" }, { "name": "schnell-gold.com", "include_subdomains": true, "mode": "force-https" }, - { "name": "segurosocial.gov", "include_subdomains": true, "mode": "force-https" }, + { "name": "segurosocial.gov", "include_subdomains": false, "mode": "force-https" }, { "name": "selectel.ru", "include_subdomains": true, "mode": "force-https" }, { "name": "sevsopr.ru", "include_subdomains": true, "mode": "force-https" }, { "name": "silver-heart.co.uk", "include_subdomains": true, "mode": "force-https" }, { "name": "slamix.nl", "include_subdomains": true, "mode": "force-https" }, { "name": "smartpolicingplatform.com", "include_subdomains": true, "mode": "force-https" }, - { "name": "socialsecurity.gov", "include_subdomains": true, "mode": "force-https" }, + { "name": "socialsecurity.gov", "include_subdomains": false, "mode": "force-https" }, { "name": "splikity.com", "include_subdomains": true, "mode": "force-https" }, { "name": "square.gs", "include_subdomains": true, "mode": "force-https" }, - { "name": "ssa.gov", "include_subdomains": true, "mode": "force-https" }, + { "name": "ssa.gov", "include_subdomains": false, "mode": "force-https" }, { "name": "ssl.rip", "include_subdomains": true, "mode": "force-https" }, { "name": "stellenticket.de", "include_subdomains": true, "mode": "force-https" }, { "name": "subdimension.org", "include_subdomains": true, "mode": "force-https" },
diff --git a/net/log/net_log_util_unittest.cc b/net/log/net_log_util_unittest.cc index 1f9db74..ee6cf731 100644 --- a/net/log/net_log_util_unittest.cc +++ b/net/log/net_log_util_unittest.cc
@@ -15,7 +15,6 @@ #include "net/http/http_transaction.h" #include "net/log/test_net_log.h" #include "net/log/test_net_log_entry.h" -#include "net/test/spawned_test_server/spawned_test_server.h" #include "net/url_request/url_request_test_util.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/net/net.gyp b/net/net.gyp index 3241d9a..61b2c75 100644 --- a/net/net.gyp +++ b/net/net.gyp
@@ -1528,10 +1528,14 @@ ], 'variables': { 'dest_path': '<(asset_location)', - 'src_files': [ + 'renaming_sources': [ '<(PRODUCT_DIR)/natives_blob.bin', '<(PRODUCT_DIR)/snapshot_blob.bin', ], + 'renaming_destinations': [ + 'natives_blob_<(arch_suffix).bin', + 'snapshot_blob_<(arch_suffix).bin', + ], 'clear': 1, }, 'includes': ['../build/android/copy_ex.gypi'], @@ -1546,13 +1550,16 @@ ['v8_use_external_startup_data==1', { 'asset_location': '<(PRODUCT_DIR)/net_unittests_apk/assets', 'additional_input_paths': [ - '<(PRODUCT_DIR)/net_unittests_apk/assets/natives_blob.bin', - '<(PRODUCT_DIR)/net_unittests_apk/assets/snapshot_blob.bin', + '<(PRODUCT_DIR)/net_unittests_apk/assets/natives_blob_<(arch_suffix).bin', + '<(PRODUCT_DIR)/net_unittests_apk/assets/snapshot_blob_<(arch_suffix).bin', ], }], ], }, - 'includes': [ '../build/apk_test.gypi' ], + 'includes': [ + '../build/apk_test.gypi', + '../build/android/v8_external_startup_data_arch_suffix.gypi', + ], }, { 'target_name': 'net_junit_tests',
diff --git a/net/net.gypi b/net/net.gypi index e24cd6ad4..dd96f5e0 100644 --- a/net/net.gypi +++ b/net/net.gypi
@@ -380,6 +380,8 @@ 'quic/quic_write_blocked_list.h', 'quic/reliable_quic_stream.cc', 'quic/reliable_quic_stream.h', + 'quic/stream_sequencer_buffer.cc', + 'quic/stream_sequencer_buffer.h', ], 'net_non_nacl_sources': [ 'android/android_private_key.cc', @@ -1559,6 +1561,7 @@ 'quic/quic_utils_test.cc', 'quic/quic_write_blocked_list_test.cc', 'quic/reliable_quic_stream_test.cc', + 'quic/stream_sequencer_buffer_test.cc', 'quic/test_tools/crypto_test_utils.cc', 'quic/test_tools/crypto_test_utils.h', 'quic/test_tools/crypto_test_utils_chromium.cc',
diff --git a/net/proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc b/net/proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc index fd227df..5fae7a41 100644 --- a/net/proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc +++ b/net/proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc
@@ -13,7 +13,7 @@ #include "net/base/test_completion_callback.h" #include "net/proxy/mock_proxy_script_fetcher.h" #include "net/proxy/proxy_script_fetcher_impl.h" -#include "net/test/spawned_test_server/spawned_test_server.h" +#include "net/test/embedded_test_server/embedded_test_server.h" #include "net/url_request/url_request_test_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -283,14 +283,12 @@ }; TEST(DhcpProxyScriptAdapterFetcher, MockDhcpRealFetch) { - SpawnedTestServer test_server( - SpawnedTestServer::TYPE_HTTP, - SpawnedTestServer::kLocalhost, - base::FilePath( - FILE_PATH_LITERAL("net/data/proxy_script_fetcher_unittest"))); + EmbeddedTestServer test_server; + test_server.ServeFilesFromSourceDirectory( + "net/data/proxy_script_fetcher_unittest"); ASSERT_TRUE(test_server.Start()); - GURL configured_url = test_server.GetURL("files/downloadable.pac"); + GURL configured_url = test_server.GetURL("/downloadable.pac"); FetcherClient client; TestURLRequestContext url_request_context;
diff --git a/net/proxy/proxy_resolver_factory_mojo_unittest.cc b/net/proxy/proxy_resolver_factory_mojo_unittest.cc index dad931c..15d8a64 100644 --- a/net/proxy/proxy_resolver_factory_mojo_unittest.cc +++ b/net/proxy/proxy_resolver_factory_mojo_unittest.cc
@@ -291,7 +291,6 @@ void Cancel(); int WaitForResult(); - int error() const { return error_; } const ProxyInfo& results() const { return results_; } LoadState load_state() { return resolver_->GetLoadState(handle_); } BoundTestNetLog& net_log() { return net_log_; }
diff --git a/net/proxy/proxy_resolver_perftest.cc b/net/proxy/proxy_resolver_perftest.cc index 9390181..6b9759f4 100644 --- a/net/proxy/proxy_resolver_perftest.cc +++ b/net/proxy/proxy_resolver_perftest.cc
@@ -15,7 +15,7 @@ #include "net/proxy/proxy_resolver.h" #include "net/proxy/proxy_resolver_factory.h" #include "net/proxy/proxy_resolver_v8.h" -#include "net/test/spawned_test_server/spawned_test_server.h" +#include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(OS_WIN) @@ -90,12 +90,10 @@ // |resolver_name| is the label used when logging the results. PacPerfSuiteRunner(ProxyResolverFactory* factory, const std::string& resolver_name) - : factory_(factory), - resolver_name_(resolver_name), - test_server_(SpawnedTestServer::TYPE_HTTP, - SpawnedTestServer::kLocalhost, - base::FilePath(FILE_PATH_LITERAL( - "net/data/proxy_resolver_perftest"))) {} + : factory_(factory), resolver_name_(resolver_name) { + test_server_.ServeFilesFromSourceDirectory( + "net/data/proxy_resolver_perftest"); + } void RunAllTests() { ASSERT_TRUE(test_server_.Start()); @@ -113,8 +111,7 @@ int queries_len) { scoped_ptr<ProxyResolver> resolver; if (!factory_->expects_pac_bytes()) { - GURL pac_url = - test_server_.GetURL(std::string("files/") + script_name); + GURL pac_url = test_server_.GetURL(std::string("/") + script_name); int rv = factory_->CreateProxyResolver( ProxyResolverScriptData::FromURL(pac_url), &resolver, CompletionCallback(), nullptr); @@ -189,7 +186,7 @@ ProxyResolverFactory* factory_; std::string resolver_name_; - SpawnedTestServer test_server_; + EmbeddedTestServer test_server_; }; #if defined(OS_WIN)
diff --git a/net/proxy/proxy_script_fetcher_impl_unittest.cc b/net/proxy/proxy_script_fetcher_impl_unittest.cc index 437d88ab..7d117eb 100644 --- a/net/proxy/proxy_script_fetcher_impl_unittest.cc +++ b/net/proxy/proxy_script_fetcher_impl_unittest.cc
@@ -24,7 +24,7 @@ #include "net/http/http_server_properties_impl.h" #include "net/http/transport_security_state.h" #include "net/ssl/ssl_config_service_defaults.h" -#include "net/test/spawned_test_server/spawned_test_server.h" +#include "net/test/embedded_test_server/embedded_test_server.h" #include "net/url_request/url_request_context_storage.h" #include "net/url_request/url_request_file_job.h" #include "net/url_request/url_request_job_factory_impl.h" @@ -186,15 +186,13 @@ class ProxyScriptFetcherImplTest : public PlatformTest { public: - ProxyScriptFetcherImplTest() - : test_server_(SpawnedTestServer::TYPE_HTTP, - SpawnedTestServer::kLocalhost, - base::FilePath(kDocRoot)) { + ProxyScriptFetcherImplTest() { + test_server_.AddDefaultHandlers(base::FilePath(kDocRoot)); context_.set_network_delegate(&network_delegate_); } protected: - SpawnedTestServer test_server_; + EmbeddedTestServer test_server_; BasicNetworkDelegate network_delegate_; RequestContext context_; }; @@ -232,7 +230,7 @@ ProxyScriptFetcherImpl pac_fetcher(&context_); { // Fetch a PAC with mime type "text/plain" - GURL url(test_server_.GetURL("files/pac.txt")); + GURL url(test_server_.GetURL("/pac.txt")); base::string16 text; TestCompletionCallback callback; int result = pac_fetcher.Fetch(url, &text, callback.callback()); @@ -241,7 +239,7 @@ EXPECT_EQ(ASCIIToUTF16("-pac.txt-\n"), text); } { // Fetch a PAC with mime type "text/html" - GURL url(test_server_.GetURL("files/pac.html")); + GURL url(test_server_.GetURL("/pac.html")); base::string16 text; TestCompletionCallback callback; int result = pac_fetcher.Fetch(url, &text, callback.callback()); @@ -250,7 +248,7 @@ EXPECT_EQ(ASCIIToUTF16("-pac.html-\n"), text); } { // Fetch a PAC with mime type "application/x-ns-proxy-autoconfig" - GURL url(test_server_.GetURL("files/pac.nsproxy")); + GURL url(test_server_.GetURL("/pac.nsproxy")); base::string16 text; TestCompletionCallback callback; int result = pac_fetcher.Fetch(url, &text, callback.callback()); @@ -266,7 +264,7 @@ ProxyScriptFetcherImpl pac_fetcher(&context_); { // Fetch a PAC which gives a 500 -- FAIL - GURL url(test_server_.GetURL("files/500.pac")); + GURL url(test_server_.GetURL("/500.pac")); base::string16 text; TestCompletionCallback callback; int result = pac_fetcher.Fetch(url, &text, callback.callback()); @@ -275,7 +273,7 @@ EXPECT_TRUE(text.empty()); } { // Fetch a PAC which gives a 404 -- FAIL - GURL url(test_server_.GetURL("files/404.pac")); + GURL url(test_server_.GetURL("/404.pac")); base::string16 text; TestCompletionCallback callback; int result = pac_fetcher.Fetch(url, &text, callback.callback()); @@ -292,7 +290,7 @@ // Fetch PAC scripts via HTTP with a Content-Disposition header -- should // have no effect. - GURL url(test_server_.GetURL("files/downloadable.pac")); + GURL url(test_server_.GetURL("/downloadable.pac")); base::string16 text; TestCompletionCallback callback; int result = pac_fetcher.Fetch(url, &text, callback.callback()); @@ -308,7 +306,7 @@ ProxyScriptFetcherImpl pac_fetcher(&context_); // Fetch a PAC script whose HTTP headers make it cacheable for 1 hour. - GURL url(test_server_.GetURL("files/cacheable_1hr.pac")); + GURL url(test_server_.GetURL("/cacheable_1hr.pac")); { base::string16 text; TestCompletionCallback callback; @@ -319,7 +317,7 @@ } // Kill the HTTP server. - ASSERT_TRUE(test_server_.Stop()); + ASSERT_TRUE(test_server_.ShutdownAndWaitUntilComplete()); // Try to fetch the file again. Since the server is not running anymore, the // call should fail, thus indicating that the file was not fetched from the @@ -345,7 +343,7 @@ // These two URLs are the same file, but are http:// vs file:// GURL urls[] = { - test_server_.GetURL("files/large-pac.nsproxy"), + test_server_.GetURL("/large-pac.nsproxy"), #if !defined(DISABLE_FILE_SUPPORT) GetTestFileUrl("large-pac.nsproxy") #endif @@ -367,7 +365,7 @@ pac_fetcher.SetSizeConstraint(prev_size); { // Make sure we can still fetch regular URLs. - GURL url(test_server_.GetURL("files/pac.nsproxy")); + GURL url(test_server_.GetURL("/pac.nsproxy")); base::string16 text; TestCompletionCallback callback; int result = pac_fetcher.Fetch(url, &text, callback.callback()); @@ -389,7 +387,7 @@ // Try fetching a URL which takes 1.2 seconds. We should abort the request // after 500 ms, and fail with a timeout error. { - GURL url(test_server_.GetURL("slow/proxy.pac?1.2")); + GURL url(test_server_.GetURL("/slow/proxy.pac?1.2")); base::string16 text; TestCompletionCallback callback; int result = pac_fetcher.Fetch(url, &text, callback.callback()); @@ -402,7 +400,7 @@ pac_fetcher.SetTimeoutConstraint(prev_timeout); { // Make sure we can still fetch regular URLs. - GURL url(test_server_.GetURL("files/pac.nsproxy")); + GURL url(test_server_.GetURL("/pac.nsproxy")); base::string16 text; TestCompletionCallback callback; int result = pac_fetcher.Fetch(url, &text, callback.callback()); @@ -422,7 +420,7 @@ // Test a response that is gzip-encoded -- should get inflated. { - GURL url(test_server_.GetURL("files/gzipped_pac")); + GURL url(test_server_.GetURL("/gzipped_pac")); base::string16 text; TestCompletionCallback callback; int result = pac_fetcher.Fetch(url, &text, callback.callback()); @@ -434,7 +432,7 @@ // Test a response that was served as UTF-16 (BE). It should // be converted to UTF8. { - GURL url(test_server_.GetURL("files/utf16be_pac")); + GURL url(test_server_.GetURL("/utf16be_pac")); base::string16 text; TestCompletionCallback callback; int result = pac_fetcher.Fetch(url, &text, callback.callback());
diff --git a/net/quic/congestion_control/tcp_cubic_bytes_sender.cc b/net/quic/congestion_control/tcp_cubic_bytes_sender.cc index 06288db..c34d448 100644 --- a/net/quic/congestion_control/tcp_cubic_bytes_sender.cc +++ b/net/quic/congestion_control/tcp_cubic_bytes_sender.cc
@@ -22,8 +22,7 @@ // The minimum cwnd based on RFC 3782 (TCP NewReno) for cwnd reductions on a // fast retransmission. const QuicByteCount kDefaultMinimumCongestionWindow = 2 * kDefaultTCPMSS; -const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS; -const QuicByteCount kMaxBurstBytes = 3 * kMaxSegmentSize; +const QuicByteCount kMaxBurstBytes = 3 * kDefaultTCPMSS; const float kRenoBeta = 0.7f; // Reno backoff factor. const uint32 kDefaultNumConnections = 2; // N-connection emulation. } // namespace @@ -44,13 +43,12 @@ largest_sent_packet_number_(0), largest_acked_packet_number_(0), largest_sent_at_last_cutback_(0), - congestion_window_(initial_tcp_congestion_window * kMaxSegmentSize), + congestion_window_(initial_tcp_congestion_window * kDefaultTCPMSS), min_congestion_window_(kDefaultMinimumCongestionWindow), min4_mode_(false), - max_congestion_window_(max_congestion_window * kMaxSegmentSize), - slowstart_threshold_(max_congestion_window * kMaxSegmentSize), - last_cutback_exited_slowstart_(false), - clock_(clock) {} + max_congestion_window_(max_congestion_window * kDefaultTCPMSS), + slowstart_threshold_(max_congestion_window * kDefaultTCPMSS), + last_cutback_exited_slowstart_(false) {} TcpCubicBytesSender::~TcpCubicBytesSender() { } @@ -61,18 +59,18 @@ if (config.HasReceivedConnectionOptions() && ContainsQuicTag(config.ReceivedConnectionOptions(), kIW10)) { // Initial window experiment. - congestion_window_ = 10 * kMaxSegmentSize; + congestion_window_ = 10 * kDefaultTCPMSS; } if (config.HasReceivedConnectionOptions() && ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN1)) { // Min CWND experiment. - min_congestion_window_ = kMaxSegmentSize; + min_congestion_window_ = kDefaultTCPMSS; } if (config.HasReceivedConnectionOptions() && ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN4)) { // Min CWND of 4 experiment. min4_mode_ = true; - min_congestion_window_ = kMaxSegmentSize; + min_congestion_window_ = kDefaultTCPMSS; } } } @@ -90,8 +88,8 @@ // Make sure CWND is in appropriate range (in case of bad data). QuicByteCount new_congestion_window = bandwidth.ToBytesPerPeriod(rtt_ms); congestion_window_ = - max(min(new_congestion_window, kMaxCongestionWindow * kMaxSegmentSize), - kMinCongestionWindowForBandwidthResumption * kMaxSegmentSize); + max(min(new_congestion_window, kMaxCongestionWindow * kDefaultTCPMSS), + kMinCongestionWindowForBandwidthResumption * kDefaultTCPMSS); } void TcpCubicBytesSender::SetNumEmulatedConnections(int num_connections) { @@ -120,7 +118,7 @@ if (rtt_updated && InSlowStart() && hybrid_slow_start_.ShouldExitSlowStart( rtt_stats_->latest_rtt(), rtt_stats_->min_rtt(), - congestion_window_ / kMaxSegmentSize)) { + congestion_window_ / kDefaultTCPMSS)) { slowstart_threshold_ = congestion_window_; } for (CongestionVector::const_iterator it = lost_packets.begin(); @@ -227,7 +225,7 @@ if (GetCongestionWindow() > bytes_in_flight) { return QuicTime::Delta::Zero(); } - if (min4_mode_ && bytes_in_flight < 4 * kMaxSegmentSize) { + if (min4_mode_ && bytes_in_flight < 4 * kDefaultTCPMSS) { return QuicTime::Delta::Zero(); } return QuicTime::Delta::Infinite(); @@ -310,7 +308,7 @@ } if (InSlowStart()) { // TCP slow start, exponential growth, increase by one for each ACK. - congestion_window_ += kMaxSegmentSize; + congestion_window_ += kDefaultTCPMSS; DVLOG(1) << "Slow start; congestion window: " << congestion_window_ << " slowstart threshold: " << slowstart_threshold_; return; @@ -322,8 +320,8 @@ // Divide by num_connections to smoothly increase the CWND at a faster rate // than conventional Reno. if (num_acked_packets_ * num_connections_ >= - congestion_window_ / kMaxSegmentSize) { - congestion_window_ += kMaxSegmentSize; + congestion_window_ / kDefaultTCPMSS) { + congestion_window_ += kDefaultTCPMSS; num_acked_packets_ = 0; }
diff --git a/net/quic/congestion_control/tcp_cubic_bytes_sender.h b/net/quic/congestion_control/tcp_cubic_bytes_sender.h index 7a345f6..9040fb6 100644 --- a/net/quic/congestion_control/tcp_cubic_bytes_sender.h +++ b/net/quic/congestion_control/tcp_cubic_bytes_sender.h
@@ -129,8 +129,6 @@ // collection of slowstart_packets_lost. bool last_cutback_exited_slowstart_; - const QuicClock* clock_; - DISALLOW_COPY_AND_ASSIGN(TcpCubicBytesSender); };
diff --git a/net/quic/congestion_control/tcp_cubic_sender.cc b/net/quic/congestion_control/tcp_cubic_sender.cc index 457dd2e..81da996 100644 --- a/net/quic/congestion_control/tcp_cubic_sender.cc +++ b/net/quic/congestion_control/tcp_cubic_sender.cc
@@ -23,8 +23,7 @@ // The minimum cwnd based on RFC 3782 (TCP NewReno) for cwnd reductions on a // fast retransmission. The cwnd after a timeout is still 1. const QuicPacketCount kDefaultMinimumCongestionWindow = 2; -const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS; -const QuicByteCount kMaxBurstBytes = 3 * kMaxSegmentSize; +const QuicByteCount kMaxBurstBytes = 3 * kDefaultTCPMSS; const float kRenoBeta = 0.7f; // Reno backoff factor. const uint32 kDefaultNumConnections = 2; // N-connection emulation. } // namespace @@ -49,8 +48,7 @@ min4_mode_(false), slowstart_threshold_(max_tcp_congestion_window), last_cutback_exited_slowstart_(false), - max_tcp_congestion_window_(max_tcp_congestion_window), - clock_(clock) {} + max_tcp_congestion_window_(max_tcp_congestion_window) {} TcpCubicSender::~TcpCubicSender() { UMA_HISTOGRAM_COUNTS("Net.QuicSession.FinalTcpCwnd", congestion_window_); @@ -105,7 +103,7 @@ // Make sure CWND is in appropriate range (in case of bad data). QuicPacketCount new_congestion_window = - bandwidth.ToBytesPerPeriod(rtt_ms) / kMaxPacketSize; + bandwidth.ToBytesPerPeriod(rtt_ms) / kDefaultTCPMSS; congestion_window_ = max(min(new_congestion_window, kMaxCongestionWindow), kMinCongestionWindowForBandwidthResumption); } @@ -117,7 +115,7 @@ void TcpCubicSender::SetMaxCongestionWindow( QuicByteCount max_congestion_window) { - max_tcp_congestion_window_ = max_congestion_window / kMaxPacketSize; + max_tcp_congestion_window_ = max_congestion_window / kDefaultTCPMSS; } float TcpCubicSender::RenoBeta() const { @@ -237,12 +235,12 @@ if (InRecovery()) { // PRR is used when in recovery. return prr_.TimeUntilSend(GetCongestionWindow(), bytes_in_flight, - slowstart_threshold_ * kMaxSegmentSize); + slowstart_threshold_ * kDefaultTCPMSS); } if (GetCongestionWindow() > bytes_in_flight) { return QuicTime::Delta::Zero(); } - if (min4_mode_ && bytes_in_flight < 4 * kMaxSegmentSize) { + if (min4_mode_ && bytes_in_flight < 4 * kDefaultTCPMSS) { return QuicTime::Delta::Zero(); } return QuicTime::Delta::Infinite(); @@ -279,7 +277,7 @@ } QuicByteCount TcpCubicSender::GetCongestionWindow() const { - return congestion_window_ * kMaxSegmentSize; + return congestion_window_ * kDefaultTCPMSS; } bool TcpCubicSender::InSlowStart() const { @@ -287,7 +285,7 @@ } QuicByteCount TcpCubicSender::GetSlowStartThreshold() const { - return slowstart_threshold_ * kMaxSegmentSize; + return slowstart_threshold_ * kDefaultTCPMSS; } bool TcpCubicSender::IsCwndLimited(QuicByteCount bytes_in_flight) const {
diff --git a/net/quic/congestion_control/tcp_cubic_sender.h b/net/quic/congestion_control/tcp_cubic_sender.h index 1e82401..e4eb9081 100644 --- a/net/quic/congestion_control/tcp_cubic_sender.h +++ b/net/quic/congestion_control/tcp_cubic_sender.h
@@ -130,8 +130,6 @@ // Maximum number of outstanding packets for tcp. QuicPacketCount max_tcp_congestion_window_; - const QuicClock* clock_; - DISALLOW_COPY_AND_ASSIGN(TcpCubicSender); };
diff --git a/net/quic/congestion_control/tcp_cubic_sender_test.cc b/net/quic/congestion_control/tcp_cubic_sender_test.cc index ad19af8..3d13996 100644 --- a/net/quic/congestion_control/tcp_cubic_sender_test.cc +++ b/net/quic/congestion_control/tcp_cubic_sender_test.cc
@@ -748,7 +748,7 @@ CachedNetworkParameters cached_network_params; const QuicPacketCount kNumberOfPackets = 123; const int kBandwidthEstimateBytesPerSecond = - kNumberOfPackets * kMaxPacketSize; + kNumberOfPackets * kDefaultTCPMSS; cached_network_params.set_bandwidth_estimate_bytes_per_second( kBandwidthEstimateBytesPerSecond); cached_network_params.set_min_rtt_ms(1000); @@ -761,12 +761,12 @@ // Resumed CWND is limited to be in a sensible range. cached_network_params.set_bandwidth_estimate_bytes_per_second( - (kMaxCongestionWindow + 1) * kMaxPacketSize); + (kMaxCongestionWindow + 1) * kDefaultTCPMSS); sender_->ResumeConnectionState(cached_network_params, false); EXPECT_EQ(kMaxCongestionWindow, sender_->congestion_window()); cached_network_params.set_bandwidth_estimate_bytes_per_second( - (kMinCongestionWindowForBandwidthResumption - 1) * kMaxPacketSize); + (kMinCongestionWindowForBandwidthResumption - 1) * kDefaultTCPMSS); sender_->ResumeConnectionState(cached_network_params, false); EXPECT_EQ(kMinCongestionWindowForBandwidthResumption, sender_->congestion_window());
diff --git a/net/quic/crypto/crypto_handshake.cc b/net/quic/crypto/crypto_handshake.cc index c790814c..7676c8cc 100644 --- a/net/quic/crypto/crypto_handshake.cc +++ b/net/quic/crypto/crypto_handshake.cc
@@ -15,7 +15,8 @@ : key_exchange(0), aead(0), x509_ecdsa_supported(false), - x509_supported(false) {} + x509_supported(false), + sct_supported_by_client(false) {} QuicCryptoNegotiatedParameters::~QuicCryptoNegotiatedParameters() {}
diff --git a/net/quic/crypto/crypto_handshake.h b/net/quic/crypto/crypto_handshake.h index 74671cae..ef4fe22 100644 --- a/net/quic/crypto/crypto_handshake.h +++ b/net/quic/crypto/crypto_handshake.h
@@ -137,6 +137,10 @@ // Used to generate cert chain when sending server config updates. std::string client_common_set_hashes; std::string client_cached_cert_hashes; + + // Default to false; set to true if the client indicates that it supports sct + // by sending CSCT tag with an empty value in client hello. + bool sct_supported_by_client; }; struct NET_EXPORT_PRIVATE QuicCryptoProof { @@ -146,6 +150,7 @@ std::string signature; // QuicCryptoProof does not take ownership of |certs|. const std::vector<std::string>* certs; + std::string cert_sct; }; // QuicCryptoConfig contains common configuration between clients and servers.
diff --git a/net/quic/crypto/crypto_protocol.h b/net/quic/crypto/crypto_protocol.h index 6d56198c..18dbc0c 100644 --- a/net/quic/crypto/crypto_protocol.h +++ b/net/quic/crypto/crypto_protocol.h
@@ -188,6 +188,8 @@ TAG('S', 'T', 'K', 0); // Source-address token const QuicTag kCertificateTag = TAG('C', 'R', 'T', 255); // Certificate chain +const QuicTag kCertificateSCTTag = + TAG('C', 'S', 'C', 'T'); // Signed cert timestamp (RFC6962) of leaf cert. #undef TAG
diff --git a/net/quic/crypto/crypto_server_test.cc b/net/quic/crypto/crypto_server_test.cc index 52b4baaa..427c1cf 100644 --- a/net/quic/crypto/crypto_server_test.cc +++ b/net/quic/crypto/crypto_server_test.cc
@@ -115,6 +115,8 @@ CryptoTestUtils::FakeProofSourceForTesting()) { #endif supported_versions_ = GetParam().supported_versions; + config_.set_enable_serving_sct(true); + client_version_ = supported_versions_.front(); client_version_string_ = QuicUtils::TagToString(QuicVersionToQuicTag(client_version_)); @@ -149,6 +151,7 @@ "KEXS", "C255", "PUBS", pub_hex_.c_str(), "NONC", nonce_hex_.c_str(), + "CSCT", "", "VER\0", client_version_string_.c_str(), "$padding", static_cast<int>(kClientHelloMinimumSize), nullptr); @@ -348,6 +351,7 @@ const vector<string>* certs; IPAddressNumber server_ip; string sig; + string cert_sct; #if defined(USE_OPENSSL) scoped_ptr<ProofSource> proof_source( CryptoTestUtils::ProofSourceForTesting()); @@ -355,7 +359,8 @@ scoped_ptr<ProofSource> proof_source( CryptoTestUtils::FakeProofSourceForTesting()); #endif - if (!proof_source->GetProof(server_ip, "", "", false, &certs, &sig) || + if (!proof_source->GetProof(server_ip, "", "", false, &certs, &sig, + &cert_sct) || certs->empty()) { return "#0100000000000000"; } @@ -440,14 +445,17 @@ // clang-format on ShouldSucceed(msg); - StringPiece cert, proof; + StringPiece cert, proof, cert_sct; EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert)); EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof)); + EXPECT_EQ(client_version_ > QUIC_VERSION_29, + out_.GetStringPiece(kCertificateSCTTag, &cert_sct)); EXPECT_NE(0u, cert.size()); EXPECT_NE(0u, proof.size()); const HandshakeFailureReason kRejectReasons[] = { SERVER_CONFIG_INCHOATE_HELLO_FAILURE}; CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); + EXPECT_EQ(client_version_ > QUIC_VERSION_29, cert_sct.size() > 0); } TEST_P(CryptoServerTest, TooSmall) {
diff --git a/net/quic/crypto/crypto_utils.cc b/net/quic/crypto/crypto_utils.cc index 6021dc6..555a2b9 100644 --- a/net/quic/crypto/crypto_utils.cc +++ b/net/quic/crypto/crypto_utils.cc
@@ -165,4 +165,40 @@ return QuicUtils::FNV1a_64_Hash(cert.data(), cert.size()); } +QuicErrorCode CryptoUtils::ValidateServerHello( + const CryptoHandshakeMessage& server_hello, + const QuicVersionVector& negotiated_versions, + string* error_details) { + DCHECK(error_details != nullptr); + + if (server_hello.tag() != kSHLO) { + *error_details = "Bad tag"; + return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; + } + + const QuicTag* supported_version_tags; + size_t num_supported_versions; + + if (server_hello.GetTaglist(kVER, &supported_version_tags, + &num_supported_versions) != QUIC_NO_ERROR) { + *error_details = "server hello missing version list"; + return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; + } + if (!negotiated_versions.empty()) { + bool mismatch = num_supported_versions != negotiated_versions.size(); + for (size_t i = 0; i < num_supported_versions && !mismatch; ++i) { + mismatch = QuicTagToQuicVersion(supported_version_tags[i]) != + negotiated_versions[i]; + } + // The server sent a list of supported versions, and the connection + // reports that there was a version negotiation during the handshake. + // Ensure that these two lists are identical. + if (mismatch) { + *error_details = "Downgrade attack detected"; + return QUIC_VERSION_NEGOTIATION_MISMATCH; + } + } + return QUIC_NO_ERROR; +} + } // namespace net
diff --git a/net/quic/crypto/crypto_utils.h b/net/quic/crypto/crypto_utils.h index 436f178..ff9c951 100644 --- a/net/quic/crypto/crypto_utils.h +++ b/net/quic/crypto/crypto_utils.h
@@ -12,6 +12,7 @@ #include "base/strings/string_piece.h" #include "net/base/net_export.h" #include "net/quic/crypto/crypto_handshake.h" +#include "net/quic/crypto/crypto_handshake_message.h" #include "net/quic/crypto/crypto_protocol.h" #include "net/quic/quic_protocol.h" #include "net/quic/quic_time.h" @@ -74,6 +75,16 @@ // XLCT tag. static uint64 ComputeLeafCertHash(const std::string& cert); + // Validates that |server_hello| is actually an SHLO message and that it is + // not part of a downgrade attack. + // + // Returns QUIC_NO_ERROR if this is the case or returns the appropriate error + // code and sets |error_details|. + static QuicErrorCode ValidateServerHello( + const CryptoHandshakeMessage& server_hello, + const QuicVersionVector& negotiated_versions, + std::string* error_details); + private: DISALLOW_COPY_AND_ASSIGN(CryptoUtils); };
diff --git a/net/quic/crypto/proof_source.h b/net/quic/crypto/proof_source.h index 744a8edd..235b972b 100644 --- a/net/quic/crypto/proof_source.h +++ b/net/quic/crypto/proof_source.h
@@ -45,13 +45,16 @@ // |hostname| may be empty to signify that a default certificate should be // used. // + // |out_leaf_cert_sct| points to the signed timestamp (RFC6962) of the leaf + // cert. // This function may be called concurrently. virtual bool GetProof(const IPAddressNumber& server_ip, const std::string& hostname, const std::string& server_config, bool ecdsa_ok, const std::vector<std::string>** out_certs, - std::string* out_signature) = 0; + std::string* out_signature, + std::string* out_leaf_cert_sct) = 0; }; } // namespace net
diff --git a/net/quic/crypto/proof_source_chromium.h b/net/quic/crypto/proof_source_chromium.h index ef5e676..fae666a 100644 --- a/net/quic/crypto/proof_source_chromium.h +++ b/net/quic/crypto/proof_source_chromium.h
@@ -26,9 +26,11 @@ ~ProofSourceChromium() override; // Initializes this object based on the certificate chain in |cert_path|, - // and the PKCS#8 RSA private key in |key_path|. + // and the PKCS#8 RSA private key in |key_path|. Signed certificate + // timestamp may be loaded from |sct_path| if it is non-empty. bool Initialize(const base::FilePath& cert_path, - const base::FilePath& key_path); + const base::FilePath& key_path, + const base::FilePath& sct_path); // ProofSource interface bool GetProof(const IPAddressNumber& server_ip, @@ -36,11 +38,13 @@ const std::string& server_config, bool ecdsa_ok, const std::vector<std::string>** out_certs, - std::string* out_signature) override; + std::string* out_signature, + std::string* out_leaf_cert_sct) override; private: scoped_ptr<crypto::RSAPrivateKey> private_key_; std::vector<std::string> certificates_; + std::string signed_certificate_timestamp_; DISALLOW_COPY_AND_ASSIGN(ProofSourceChromium); };
diff --git a/net/quic/crypto/proof_source_chromium_nss.cc b/net/quic/crypto/proof_source_chromium_nss.cc index f73a6ac..407089a 100644 --- a/net/quic/crypto/proof_source_chromium_nss.cc +++ b/net/quic/crypto/proof_source_chromium_nss.cc
@@ -14,7 +14,8 @@ ProofSourceChromium::~ProofSourceChromium() {} bool ProofSourceChromium::Initialize(const base::FilePath& cert_path, - const base::FilePath& key_path) { + const base::FilePath& key_path, + const base::FilePath& sct_path) { return false; } @@ -23,7 +24,8 @@ const string& server_config, bool ecdsa_ok, const vector<string>** out_certs, - string* out_signature) { + string* out_signature, + string* out_leaf_cert_sct) { return false; }
diff --git a/net/quic/crypto/proof_source_chromium_openssl.cc b/net/quic/crypto/proof_source_chromium_openssl.cc index c89f2d9..72017d2 100644 --- a/net/quic/crypto/proof_source_chromium_openssl.cc +++ b/net/quic/crypto/proof_source_chromium_openssl.cc
@@ -24,7 +24,8 @@ ProofSourceChromium::~ProofSourceChromium() {} bool ProofSourceChromium::Initialize(const base::FilePath& cert_path, - const base::FilePath& key_path) { + const base::FilePath& key_path, + const base::FilePath& sct_path) { crypto::EnsureOpenSSLInit(); std::string cert_data; @@ -64,6 +65,16 @@ DLOG(FATAL) << "Unable to create private key."; return false; } + + // Loading of the signed certificate timestamp is optional. + if (sct_path.empty()) + return true; + + if (!base::ReadFileToString(sct_path, &signed_certificate_timestamp_)) { + DLOG(FATAL) << "Unable to read signed certificate timestamp."; + return false; + } + return true; } @@ -72,7 +83,8 @@ const string& server_config, bool ecdsa_ok, const vector<string>** out_certs, - string* out_signature) { + string* out_signature, + string* out_leaf_cert_sct) { DCHECK(private_key_.get()) << " this: " << this; crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); @@ -108,6 +120,7 @@ *out_certs = &certificates_; VLOG(1) << "signature: " << base::HexEncode(out_signature->data(), out_signature->size()); + *out_leaf_cert_sct = signed_certificate_timestamp_; return true; }
diff --git a/net/quic/crypto/proof_test.cc b/net/quic/crypto/proof_test.cc index b493f225f..67055be 100644 --- a/net/quic/crypto/proof_test.cc +++ b/net/quic/crypto/proof_test.cc
@@ -118,18 +118,20 @@ const string hostname = "test.example.com"; const vector<string>* certs; const vector<string>* first_certs; - string error_details, signature, first_signature; + string error_details, signature, first_signature, first_cert_sct, cert_sct; IPAddressNumber server_ip; ASSERT_TRUE(source->GetProof(server_ip, hostname, server_config, false /* no ECDSA */, &first_certs, - &first_signature)); + &first_signature, &first_cert_sct)); ASSERT_TRUE(source->GetProof(server_ip, hostname, server_config, - false /* no ECDSA */, &certs, &signature)); + false /* no ECDSA */, &certs, &signature, + &cert_sct)); // Check that the proof source is caching correctly: ASSERT_EQ(first_certs, certs); ASSERT_EQ(signature, first_signature); + ASSERT_EQ(first_cert_sct, cert_sct); RunVerification( verifier.get(), hostname, server_config, *certs, signature, true);
diff --git a/net/quic/crypto/quic_crypto_client_config.cc b/net/quic/crypto/quic_crypto_client_config.cc index 8d46239..b9b0bcd4 100644 --- a/net/quic/crypto/quic_crypto_client_config.cc +++ b/net/quic/crypto/quic_crypto_client_config.cc
@@ -773,32 +773,10 @@ string* error_details) { DCHECK(error_details != nullptr); - if (server_hello.tag() != kSHLO) { - *error_details = "Bad tag"; - return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; - } - - const QuicTag* supported_version_tags; - size_t num_supported_versions; - - if (server_hello.GetTaglist(kVER, &supported_version_tags, - &num_supported_versions) != QUIC_NO_ERROR) { - *error_details = "server hello missing version list"; - return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; - } - if (!negotiated_versions.empty()) { - bool mismatch = num_supported_versions != negotiated_versions.size(); - for (size_t i = 0; i < num_supported_versions && !mismatch; ++i) { - mismatch = QuicTagToQuicVersion(supported_version_tags[i]) != - negotiated_versions[i]; - } - // The server sent a list of supported versions, and the connection - // reports that there was a version negotiation during the handshake. - // Ensure that these two lists are identical. - if (mismatch) { - *error_details = "Downgrade attack detected"; - return QUIC_VERSION_NEGOTIATION_MISMATCH; - } + QuicErrorCode valid = CryptoUtils::ValidateServerHello( + server_hello, negotiated_versions, error_details); + if (valid != QUIC_NO_ERROR) { + return valid; } // Learn about updated source address tokens.
diff --git a/net/quic/crypto/quic_crypto_server_config.cc b/net/quic/crypto/quic_crypto_server_config.cc index 173e9808..c523dd4 100644 --- a/net/quic/crypto/quic_crypto_server_config.cc +++ b/net/quic/crypto/quic_crypto_server_config.cc
@@ -223,7 +223,8 @@ source_address_token_future_secs_(3600), source_address_token_lifetime_secs_(86400), server_nonce_strike_register_max_entries_(1 << 10), - server_nonce_strike_register_window_secs_(120) { + server_nonce_strike_register_window_secs_(120), + enable_serving_sct_(false) { DCHECK(proof_source_.get()); default_source_address_token_boxer_.SetKey( DeriveSourceAddressTokenKey(source_address_token_secret)); @@ -611,13 +612,21 @@ if (!crypto_proof->certs && !proof_source_->GetProof(server_ip, info.sni.as_string(), primary_config->serialized, x509_ecdsa_supported, - &crypto_proof->certs, - &crypto_proof->signature)) { + &crypto_proof->certs, &crypto_proof->signature, + &crypto_proof->cert_sct)) { return QUIC_HANDSHAKE_FAILED; } + if (version > QUIC_VERSION_29) { + StringPiece cert_sct; + if (client_hello.GetStringPiece(kCertificateSCTTag, &cert_sct) && + cert_sct.empty()) { + params->sct_supported_by_client = true; + } + } + if (!info.reject_reasons.empty() || !requested_config.get()) { - BuildRejection(*primary_config, client_hello, info, + BuildRejection(version, *primary_config, client_hello, info, validate_chlo_result.cached_network_params, use_stateless_rejects, server_designated_connection_id, rand, params, *crypto_proof, out); @@ -1014,10 +1023,10 @@ bool x509_supported = false; bool x509_ecdsa_supported = false; ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported); - if (!proof_source_->GetProof(server_ip, info->sni.as_string(), - requested_config->serialized, - x509_ecdsa_supported, &crypto_proof->certs, - &crypto_proof->signature)) { + if (!proof_source_->GetProof( + server_ip, info->sni.as_string(), requested_config->serialized, + x509_ecdsa_supported, &crypto_proof->certs, + &crypto_proof->signature, &crypto_proof->cert_sct)) { found_error = true; info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE); } @@ -1115,6 +1124,7 @@ } bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage( + QuicVersion version, const SourceAddressTokens& previous_source_address_tokens, const IPAddressNumber& server_ip, const IPAddressNumber& client_ip, @@ -1134,9 +1144,10 @@ const vector<string>* certs; string signature; + string cert_sct; if (!proof_source_->GetProof( server_ip, params.sni, primary_config_->serialized, - params.x509_ecdsa_supported, &certs, &signature)) { + params.x509_ecdsa_supported, &certs, &signature, &cert_sct)) { DVLOG(1) << "Server: failed to get proof."; return false; } @@ -1147,10 +1158,19 @@ out->SetStringPiece(kCertificateTag, compressed); out->SetStringPiece(kPROF, signature); + if (params.sct_supported_by_client && version > QUIC_VERSION_29 && + enable_serving_sct_) { + if (cert_sct.empty()) { + DLOG(WARNING) << "SCT is expected but it is empty."; + } else { + out->SetStringPiece(kCertificateSCTTag, cert_sct); + } + } return true; } void QuicCryptoServerConfig::BuildRejection( + QuicVersion version, const Config& config, const CryptoHandshakeMessage& client_hello, const ClientHelloInfo& info, @@ -1215,19 +1235,30 @@ const size_t kREJOverheadBytes = 166; // kMultiplier is the multiple of the CHLO message size that a REJ message // must stay under when the client doesn't present a valid source-address - // token. + // token. This is used to protect QUIC from amplification attacks. const size_t kMultiplier = 2; - // max_unverified_size is the number of bytes that the certificate chain - // and signature can consume before we will demand a valid source-address - // token. + // max_unverified_size is the number of bytes that the certificate chain, + // signature, and (optionally) signed certificate timestamp can consume before + // we will demand a valid source-address token. const size_t max_unverified_size = client_hello.size() * kMultiplier - kREJOverheadBytes; static_assert(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes, - "overhead calculation may overflow"); + "overhead calculation may underflow"); + bool should_return_sct = params->sct_supported_by_client && + version > QUIC_VERSION_29 && enable_serving_sct_; + const size_t sct_size = should_return_sct ? crypto_proof.cert_sct.size() : 0; if (info.valid_source_address_token || - crypto_proof.signature.size() + compressed.size() < max_unverified_size) { + crypto_proof.signature.size() + compressed.size() + sct_size < + max_unverified_size) { out->SetStringPiece(kCertificateTag, compressed); out->SetStringPiece(kPROF, crypto_proof.signature); + if (should_return_sct) { + if (crypto_proof.cert_sct.empty()) { + DLOG(WARNING) << "SCT is expected but it is empty."; + } else { + out->SetStringPiece(kCertificateSCTTag, crypto_proof.cert_sct); + } + } } } @@ -1452,6 +1483,10 @@ server_nonce_strike_register_window_secs_ = window_secs; } +void QuicCryptoServerConfig::set_enable_serving_sct(bool enable_serving_sct) { + enable_serving_sct_ = enable_serving_sct; +} + void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb( PrimaryConfigChangedCallback* cb) { base::AutoLock locked(configs_lock_);
diff --git a/net/quic/crypto/quic_crypto_server_config.h b/net/quic/crypto/quic_crypto_server_config.h index 02d0523..3bf6d7c 100644 --- a/net/quic/crypto/quic_crypto_server_config.h +++ b/net/quic/crypto/quic_crypto_server_config.h
@@ -271,6 +271,7 @@ // // |cached_network_params| is optional, and can be nullptr. bool BuildServerConfigUpdateMessage( + QuicVersion version, const SourceAddressTokens& previous_source_address_tokens, const IPAddressNumber& server_ip, const IPAddressNumber& client_ip, @@ -338,6 +339,10 @@ // uniqueness. void set_server_nonce_strike_register_window_secs(uint32 window_secs); + // set_enable_serving_sct enables or disables serving signed cert timestamp + // (RFC6962) in server hello. + void set_enable_serving_sct(bool enable_serving_sct); + // Set and take ownership of the callback to invoke on primary config changes. void AcquirePrimaryConfigChangedCb(PrimaryConfigChangedCallback* cb); @@ -438,7 +443,8 @@ ValidateClientHelloResultCallback* done_cb) const; // BuildRejection sets |out| to be a REJ message in reply to |client_hello|. - void BuildRejection(const Config& config, + void BuildRejection(QuicVersion version, + const Config& config, const CryptoHandshakeMessage& client_hello, const ClientHelloInfo& info, const CachedNetworkParameters& cached_network_params, @@ -593,6 +599,9 @@ uint32 server_nonce_strike_register_max_entries_; uint32 server_nonce_strike_register_window_secs_; + // Enable serving SCT or not. + bool enable_serving_sct_; + DISALLOW_COPY_AND_ASSIGN(QuicCryptoServerConfig); };
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index 733154f3..41da420 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -337,6 +337,13 @@ static_cast<base::HistogramBase::Sample>(stats.max_sequence_reordering)); } +void QuicChromiumClientSession::OnHeadersHeadOfLineBlocking( + QuicTime::Delta delta) { + UMA_HISTOGRAM_TIMES( + "Net.QuicSession.HeadersHOLBlockedTime", + base::TimeDelta::FromMicroseconds(delta.ToMicroseconds())); +} + void QuicChromiumClientSession::OnStreamFrame(const QuicStreamFrame& frame) { // Record total number of stream frames. UMA_HISTOGRAM_COUNTS("Net.QuicNumStreamFramesInPacket", 1);
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h index b269684..9cae22c 100644 --- a/net/quic/quic_chromium_client_session.h +++ b/net/quic/quic_chromium_client_session.h
@@ -144,6 +144,9 @@ // Cancels the pending stream creation request. void CancelRequest(StreamRequest* request); + // QuicSpdySession methods: + void OnHeadersHeadOfLineBlocking(QuicTime::Delta delta) override; + // QuicSession methods: void OnStreamFrame(const QuicStreamFrame& frame) override; QuicReliableClientStream* CreateOutgoingDynamicStream() override;
diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc index faf6dbc..e21d265 100644 --- a/net/quic/quic_chromium_client_session_test.cc +++ b/net/quic/quic_chromium_client_session_test.cc
@@ -94,7 +94,7 @@ ASSERT_EQ(OK, callback_.WaitForResult()); } - MockHelper helper_; + MockConnectionHelper helper_; QuicCryptoClientConfig crypto_config_; PacketSavingConnection* connection_; TestNetLog net_log_;
diff --git a/net/quic/quic_clock.cc b/net/quic/quic_clock.cc index 9d5ac6d..b20b9c45 100644 --- a/net/quic/quic_clock.cc +++ b/net/quic/quic_clock.cc
@@ -24,7 +24,8 @@ } QuicWallTime QuicClock::WallNow() const { - return QuicWallTime::FromUNIXSeconds(base::Time::Now().ToTimeT()); + return QuicWallTime::FromUNIXMicroseconds(base::Time::Now().ToJavaTime() * + 1000); } } // namespace net
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc index 180e196..e29130a0 100644 --- a/net/quic/quic_connection.cc +++ b/net/quic/quic_connection.cc
@@ -278,6 +278,7 @@ largest_seen_packet_with_stop_waiting_(0), max_undecryptable_packets_(0), pending_version_negotiation_packet_(false), + save_crypto_packets_as_termination_packets_(false), silent_close_enabled_(false), received_packet_manager_(&stats_), ack_queued_(false), @@ -341,6 +342,9 @@ delete writer_; } STLDeleteElements(&undecryptable_packets_); + if (termination_packets_.get() != nullptr) { + STLDeleteElements(termination_packets_.get()); + } STLDeleteValues(&group_map_); ClearQueuedPackets(); } @@ -843,12 +847,12 @@ return false; } - for (QuicPacketNumber revived_packet : incoming_ack.revived_packets) { - if (!incoming_ack.missing_packets.Contains(revived_packet)) { - DLOG(ERROR) << ENDPOINT - << "Peer specified revived packet which was not missing."; - return false; - } + if (incoming_ack.latest_revived_packet != 0 && + !incoming_ack.missing_packets.Contains( + incoming_ack.latest_revived_packet)) { + DLOG(ERROR) << ENDPOINT + << "Peer specified revived packet which was not missing."; + return false; } return true; } @@ -1103,8 +1107,7 @@ self_address().address(), peer_address()); if (result.status == WRITE_STATUS_ERROR) { - // We can't send an error as the socket is presumably borked. - CloseConnection(QUIC_PACKET_WRITE_ERROR, false); + OnWriteError(result.error_code); return; } if (result.status == WRITE_STATUS_BLOCKED) { @@ -1340,6 +1343,15 @@ } if (peer_ip_changed_ || peer_port_changed_) { + PeerAddressChangeType type = DeterminePeerAddressChangeType(); + if (type != NO_CHANGE && type != UNKNOWN && + (FLAGS_quic_disable_non_nat_address_migration && + type != NAT_PORT_REBINDING && type != IPV4_SUBNET_REBINDING)) { + SendConnectionCloseWithDetails(QUIC_ERROR_MIGRATING_ADDRESS, + "Invalid peer address migration."); + return false; + } + IPEndPoint old_peer_address = peer_address_; peer_address_ = IPEndPoint( peer_ip_changed_ ? migrating_peer_ip_ : peer_address_.address(), @@ -1498,9 +1510,9 @@ ++stats_.packets_discarded; return true; } - // Connection close packets are encrypted and saved, so don't exit early. - const bool is_connection_close = IsConnectionClose(*packet); - if (writer_->IsWriteBlocked() && !is_connection_close) { + // Termination packets are encrypted and saved, so don't exit early. + const bool is_termination_packet = IsTerminationPacket(*packet); + if (writer_->IsWriteBlocked() && !is_termination_packet) { return false; } @@ -1509,12 +1521,14 @@ packet_number_of_last_sent_packet_ = packet_number; QuicEncryptedPacket* encrypted = packet->serialized_packet.packet; - // Connection close packets are eventually owned by TimeWaitListManager. + // Termination packets are eventually owned by TimeWaitListManager. // Others are deleted at the end of this call. - if (is_connection_close) { - DCHECK(connection_close_packet_.get() == nullptr); + if (is_termination_packet) { + if (termination_packets_.get() == nullptr) { + termination_packets_.reset(new std::vector<QuicEncryptedPacket*>); + } // Clone the packet so it's owned in the future. - connection_close_packet_.reset(encrypted->Clone()); + termination_packets_->push_back(encrypted->Clone()); // This assures we won't try to write *forced* packets when blocked. // Return true to stop processing. if (writer_->IsWriteBlocked()) { @@ -1523,9 +1537,7 @@ } } - if (!FLAGS_quic_allow_oversized_packets_for_test) { - DCHECK_LE(encrypted->length(), kMaxPacketSize); - } + DCHECK_LE(encrypted->length(), kMaxPacketSize); DCHECK_LE(encrypted->length(), packet_generator_.GetMaxPacketLength()); DVLOG(1) << ENDPOINT << "Sending packet " << packet_number << " : " << (packet->serialized_packet.is_fec_packet @@ -1738,6 +1750,10 @@ } } +PeerAddressChangeType QuicConnection::DeterminePeerAddressChangeType() { + return UNKNOWN; +} + void QuicConnection::SendPing() { if (retransmission_alarm_->IsSet()) { return; @@ -2027,6 +2043,10 @@ !queued_packets_.empty() || packet_generator_.HasQueuedFrames(); } +void QuicConnection::EnableSavingCryptoPackets() { + save_crypto_packets_as_termination_packets_ = true; +} + bool QuicConnection::CanWriteStreamData() { // Don't write stream data if there are negotiation or queued data packets // to send. Otherwise, continue and bundle as many frames as possible. @@ -2231,7 +2251,7 @@ } } -bool QuicConnection::IsConnectionClose(const QueuedPacket& packet) { +bool QuicConnection::IsTerminationPacket(const QueuedPacket& packet) { const RetransmittableFrames* retransmittable_frames = packet.serialized_packet.retransmittable_frames; if (retransmittable_frames == nullptr) { @@ -2241,6 +2261,11 @@ if (frame.type == CONNECTION_CLOSE_FRAME) { return true; } + if (save_crypto_packets_as_termination_packets_ && + frame.type == STREAM_FRAME && + frame.stream_frame->stream_id == kCryptoStreamId) { + return true; + } } return false; } @@ -2251,10 +2276,6 @@ QuicByteCount QuicConnection::LimitMaxPacketSize( QuicByteCount suggested_max_packet_size) { - if (FLAGS_quic_allow_oversized_packets_for_test) { - return suggested_max_packet_size; - } - if (peer_address_.address().empty()) { LOG(DFATAL) << "Attempted to use a connection without a valid peer address"; return suggested_max_packet_size;
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h index 8399747..674c5ff 100644 --- a/net/quic/quic_connection.h +++ b/net/quic/quic_connection.h
@@ -479,9 +479,9 @@ // Testing only. size_t NumQueuedPackets() const { return queued_packets_.size(); } - QuicEncryptedPacket* ReleaseConnectionClosePacket() { - return connection_close_packet_.release(); - } + // Once called, any sent crypto packets to be saved as the + // termination packet, for use with stateless rejections. + void EnableSavingCryptoPackets(); // Returns true if the underlying UDP socket is writable, there is // no queued data and the connection is not congestion-control @@ -622,6 +622,10 @@ // Return the id of the cipher of the primary decrypter of the framer. uint32 cipher_id() const { return framer_.decrypter()->cipher_id(); } + std::vector<QuicEncryptedPacket*>* termination_packets() { + return termination_packets_.get(); + } + protected: // Packets which have not been written to the wire. // Owns the QuicPacket* packet. @@ -652,6 +656,9 @@ QuicConnectionHelperInterface* helper() { return helper_; } + // On peer address changes, determine and return the change type. + virtual PeerAddressChangeType DeterminePeerAddressChangeType(); + // Selects and updates the version of the protocol being used by selecting a // version from |available_versions| which is also supported. Returns true if // such a version exists, false otherwise. @@ -661,6 +668,10 @@ bool peer_port_changed() const { return peer_port_changed_; } + const IPAddressNumber& migrating_peer_ip() const { + return migrating_peer_ip_; + } + private: friend class test::QuicConnectionPeer; friend class test::PacketSavingConnection; @@ -765,7 +776,7 @@ const IPEndPoint& peer_address); HasRetransmittableData IsRetransmittable(const QueuedPacket& packet); - bool IsConnectionClose(const QueuedPacket& packet); + bool IsTerminationPacket(const QueuedPacket& packet); // Set the size of the packet we are targeting while doing path MTU discovery. void SetMtuDiscoveryTarget(QuicByteCount target); @@ -835,8 +846,11 @@ // unacked_packets_ if they are to be retransmitted. QueuedPacketList queued_packets_; - // Contains the connection close packet if the connection has been closed. - scoped_ptr<QuicEncryptedPacket> connection_close_packet_; + // If true, then crypto packets will be saved as termination packets. + bool save_crypto_packets_as_termination_packets_; + + // Contains the connection close packets if the connection has been closed. + scoped_ptr<std::vector<QuicEncryptedPacket*>> termination_packets_; // When true, the connection does not send a close packet on timeout. bool silent_close_enabled_;
diff --git a/net/quic/quic_connection_logger.cc b/net/quic/quic_connection_logger.cc index c24bb6e..9288ed0a 100644 --- a/net/quic/quic_connection_logger.cc +++ b/net/quic/quic_connection_logger.cc
@@ -128,13 +128,8 @@ for (QuicPacketNumber packet : frame->missing_packets) missing->AppendString(base::Uint64ToString(packet)); - base::ListValue* revived = new base::ListValue(); - dict->Set("revived_packets", revived); - const PacketNumberSet& revived_packets = frame->revived_packets; - for (PacketNumberSet::const_iterator it = revived_packets.begin(); - it != revived_packets.end(); ++it) { - revived->AppendString(base::Uint64ToString(*it)); - } + dict->SetString("latest_revived_packet", + base::Int64ToString(frame->latest_revived_packet)); base::ListValue* received = new base::ListValue(); dict->Set("received_packet_times", received);
diff --git a/net/quic/quic_connection_logger_unittest.cc b/net/quic/quic_connection_logger_unittest.cc index 2348329..ebaa12d 100644 --- a/net/quic/quic_connection_logger_unittest.cc +++ b/net/quic/quic_connection_logger_unittest.cc
@@ -39,7 +39,7 @@ net_log_) {} BoundNetLog net_log_; - MockHelper helper_; + MockConnectionHelper helper_; MockQuicSpdySession session_; QuicConnectionLogger logger_; };
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc index 2ce6c834..765b5698 100644 --- a/net/quic/quic_connection_test.cc +++ b/net/quic/quic_connection_test.cc
@@ -455,13 +455,14 @@ ? new RetransmittableFrames(ENCRYPTION_NONE) : nullptr; char buffer[kMaxPacketSize]; - QuicEncryptedPacket* encrypted = + size_t encrypted_length = QuicConnectionPeer::GetFramer(this)->EncryptPayload( ENCRYPTION_NONE, packet_number, *packet, buffer, kMaxPacketSize); delete packet; - OnSerializedPacket(SerializedPacket( - packet_number, PACKET_6BYTE_PACKET_NUMBER, encrypted, entropy_hash, - retransmittable_frames, has_ack, has_pending_frames)); + OnSerializedPacket( + SerializedPacket(packet_number, PACKET_6BYTE_PACKET_NUMBER, buffer, + encrypted_length, false, entropy_hash, + retransmittable_frames, has_ack, has_pending_frames)); } QuicConsumedData SendStreamDataWithString( @@ -787,19 +788,23 @@ scoped_ptr<QuicPacket> packet(ConstructDataPacket(number, fec_group, entropy_flag)); char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> encrypted( - framer_.EncryptPayload(level, number, *packet, buffer, kMaxPacketSize)); - connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *encrypted); - return encrypted->length(); + size_t encrypted_length = + framer_.EncryptPayload(level, number, *packet, buffer, kMaxPacketSize); + connection_.ProcessUdpPacket( + kSelfAddress, kPeerAddress, + QuicEncryptedPacket(buffer, encrypted_length, false)); + return encrypted_length; } void ProcessClosePacket(QuicPacketNumber number, QuicFecGroupNumber fec_group) { scoped_ptr<QuicPacket> packet(ConstructClosePacket(number, fec_group)); char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPayload( - ENCRYPTION_NONE, number, *packet, buffer, kMaxPacketSize)); - connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *encrypted); + size_t encrypted_length = framer_.EncryptPayload( + ENCRYPTION_NONE, number, *packet, buffer, kMaxPacketSize); + connection_.ProcessUdpPacket( + kSelfAddress, kPeerAddress, + QuicEncryptedPacket(buffer, encrypted_length, false)); } size_t ProcessFecProtectedPacket(QuicPacketNumber number, @@ -859,11 +864,13 @@ scoped_ptr<QuicPacket> fec_packet( framer_.BuildFecPacket(header, data_packet->FecProtectedData())); char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPayload( - ENCRYPTION_NONE, number, *fec_packet, buffer, kMaxPacketSize)); + size_t encrypted_length = framer_.EncryptPayload( + ENCRYPTION_NONE, number, *fec_packet, buffer, kMaxPacketSize); - connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *encrypted); - return encrypted->length(); + connection_.ProcessUdpPacket( + kSelfAddress, kPeerAddress, + QuicEncryptedPacket(buffer, encrypted_length, false)); + return encrypted_length; } QuicByteCount SendStreamDataToPeer(QuicStreamId id, @@ -1087,13 +1094,15 @@ frames.push_back(QuicFrame(padding)); scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames)); char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPayload( - ENCRYPTION_NONE, 12, *packet, buffer, kMaxPacketSize)); - EXPECT_EQ(kMaxPacketSize, encrypted->length()); + size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet, + buffer, kMaxPacketSize); + EXPECT_EQ(kMaxPacketSize, encrypted_length); framer_.set_version(version()); EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); - connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *encrypted); + connection_.ProcessUdpPacket( + kSelfAddress, kPeerAddress, + QuicEncryptedPacket(buffer, encrypted_length, false)); EXPECT_EQ(kMaxPacketSize, connection_.max_packet_length()); } @@ -1118,13 +1127,15 @@ frames.push_back(QuicFrame(padding)); scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames)); char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPayload( - ENCRYPTION_NONE, 12, *packet, buffer, kMaxPacketSize)); - EXPECT_EQ(kMaxPacketSize, encrypted->length()); + size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet, + buffer, kMaxPacketSize); + EXPECT_EQ(kMaxPacketSize, encrypted_length); framer_.set_version(version()); EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); - connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *encrypted); + connection_.ProcessUdpPacket( + kSelfAddress, kPeerAddress, + QuicEncryptedPacket(buffer, encrypted_length, false)); // Here, the limit imposed by the writer is lower than the size of the packet // received, so the writer max packet size is used. @@ -4141,12 +4152,14 @@ frames.push_back(QuicFrame(&frame1_)); scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames)); char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPayload( - ENCRYPTION_NONE, 12, *packet, buffer, kMaxPacketSize)); + size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet, + buffer, kMaxPacketSize); framer_.set_version(version()); connection_.set_perspective(Perspective::IS_SERVER); - connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *encrypted); + connection_.ProcessUdpPacket( + kSelfAddress, kPeerAddress, + QuicEncryptedPacket(buffer, encrypted_length, false)); EXPECT_TRUE(writer_->version_negotiation_packet() != nullptr); size_t num_versions = arraysize(kSupportedQuicVersions); @@ -4174,13 +4187,15 @@ frames.push_back(QuicFrame(&frame1_)); scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames)); char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPayload( - ENCRYPTION_NONE, 12, *packet, buffer, kMaxPacketSize)); + size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet, + buffer, kMaxPacketSize); framer_.set_version(version()); connection_.set_perspective(Perspective::IS_SERVER); BlockOnNextWrite(); - connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *encrypted); + connection_.ProcessUdpPacket( + kSelfAddress, kPeerAddress, + QuicEncryptedPacket(buffer, encrypted_length, false)); EXPECT_EQ(0u, writer_->last_packet_size()); EXPECT_TRUE(connection_.HasQueuedData()); @@ -4214,14 +4229,16 @@ frames.push_back(QuicFrame(&frame1_)); scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames)); char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPayload( - ENCRYPTION_NONE, 12, *packet, buffer, kMaxPacketSize)); + size_t encryped_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet, + buffer, kMaxPacketSize); framer_.set_version(version()); connection_.set_perspective(Perspective::IS_SERVER); BlockOnNextWrite(); writer_->set_is_write_blocked_data_buffered(true); - connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *encrypted); + connection_.ProcessUdpPacket( + kSelfAddress, kPeerAddress, + QuicEncryptedPacket(buffer, encryped_length, false)); EXPECT_EQ(0u, writer_->last_packet_size()); EXPECT_FALSE(connection_.HasQueuedData()); } @@ -4254,11 +4271,14 @@ frames.push_back(QuicFrame(&frame1_)); scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames)); char buffer[kMaxPacketSize]; - encrypted.reset(framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet, buffer, - kMaxPacketSize)); + size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet, + buffer, kMaxPacketSize); + ASSERT_NE(0u, encrypted_length); EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *encrypted); + connection_.ProcessUdpPacket( + kSelfAddress, kPeerAddress, + QuicEncryptedPacket(buffer, encrypted_length, false)); ASSERT_FALSE(QuicPacketCreatorPeer::SendVersionInPacket(creator_)); } @@ -4389,14 +4409,16 @@ scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames)); EXPECT_TRUE(nullptr != packet.get()); char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPayload( - ENCRYPTION_NONE, 1, *packet, buffer, kMaxPacketSize)); + size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 1, *packet, + buffer, kMaxPacketSize); EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, true)); EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *encrypted); + connection_.ProcessUdpPacket( + kSelfAddress, kPeerAddress, + QuicEncryptedPacket(buffer, encrypted_length, false)); } TEST_P(QuicConnectionTest, SelectMutualVersion) { @@ -4630,7 +4652,7 @@ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); QuicAckFrame frame = InitAckFrame(2); NackPacket(1, &frame); - frame.revived_packets.insert(1); + frame.latest_revived_packet = 1; ProcessAckPacket(&frame); // If the ack is processed again, the notifier should not be called again. ProcessAckPacket(&frame);
diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc index 8884373..98668e24 100644 --- a/net/quic/quic_crypto_client_stream.cc +++ b/net/quic/quic_crypto_client_stream.cc
@@ -17,6 +17,10 @@ namespace net { +QuicCryptoClientStreamBase::QuicCryptoClientStreamBase( + QuicClientSessionBase* session) + : QuicCryptoStream(session) {} + QuicCryptoClientStream::ChannelIDSourceCallbackImpl:: ChannelIDSourceCallbackImpl(QuicCryptoClientStream* stream) : stream_(stream) {} @@ -77,7 +81,7 @@ QuicClientSessionBase* session, ProofVerifyContext* verify_context, QuicCryptoClientConfig* crypto_config) - : QuicCryptoStream(session), + : QuicCryptoClientStreamBase(session), next_state_(STATE_IDLE), num_client_hellos_(0), crypto_config_(crypto_config), @@ -103,7 +107,7 @@ void QuicCryptoClientStream::OnHandshakeMessage( const CryptoHandshakeMessage& message) { - QuicCryptoStream::OnHandshakeMessage(message); + QuicCryptoClientStreamBase::OnHandshakeMessage(message); if (message.tag() == kSCUP) { if (!handshake_confirmed()) { @@ -187,7 +191,7 @@ DoInitialize(cached); break; case STATE_SEND_CHLO: - DoSendCHLO(in, cached); + DoSendCHLO(cached); return; // return waiting to hear from server. case STATE_RECV_REJ: DoReceiveREJ(in, cached); @@ -237,7 +241,6 @@ } void QuicCryptoClientStream::DoSendCHLO( - const CryptoHandshakeMessage* in, QuicCryptoClientConfig::CachedState* cached) { if (stateless_reject_received_) { // If we've gotten to this point, we've sent at least one hello
diff --git a/net/quic/quic_crypto_client_stream.h b/net/quic/quic_crypto_client_stream.h index edfc1f5..634b281 100644 --- a/net/quic/quic_crypto_client_stream.h +++ b/net/quic/quic_crypto_client_stream.h
@@ -23,7 +23,23 @@ class QuicChromiumClientSessionPeer; } // namespace test -class NET_EXPORT_PRIVATE QuicCryptoClientStream : public QuicCryptoStream { +class NET_EXPORT_PRIVATE QuicCryptoClientStreamBase : public QuicCryptoStream { + public: + explicit QuicCryptoClientStreamBase(QuicClientSessionBase* session); + + ~QuicCryptoClientStreamBase() override{}; + + // Performs a crypto handshake with the server. + virtual void CryptoConnect() = 0; + + // num_sent_client_hellos returns the number of client hello messages that + // have been sent. If the handshake has completed then this is one greater + // than the number of round-trips needed for the handshake. + virtual int num_sent_client_hellos() const = 0; +}; + +class NET_EXPORT_PRIVATE QuicCryptoClientStream + : public QuicCryptoClientStreamBase { public: // kMaxClientHellos is the maximum number of times that we'll send a client // hello. The value 3 accounts for: @@ -32,24 +48,20 @@ // the server being unwilling to send it without a valid source-address // token. static const int kMaxClientHellos = 3; - QuicCryptoClientStream(const QuicServerId& server_id, QuicClientSessionBase* session, ProofVerifyContext* verify_context, QuicCryptoClientConfig* crypto_config); + ~QuicCryptoClientStream() override; + // From QuicCryptoClientStreamBase + void CryptoConnect() override; + int num_sent_client_hellos() const override; + // CryptoFramerVisitorInterface implementation void OnHandshakeMessage(const CryptoHandshakeMessage& message) override; - // Performs a crypto handshake with the server. - virtual void CryptoConnect(); - - // num_sent_client_hellos returns the number of client hello messages that - // have been sent. If the handshake has completed then this is one greater - // than the number of round-trips needed for the handshake. - int num_sent_client_hellos() const; - // Returns true if a channel ID was sent on this connection. bool WasChannelIDSent() const; @@ -128,8 +140,7 @@ void DoInitialize(QuicCryptoClientConfig::CachedState* cached); // Send either InchoateClientHello or ClientHello message to the server. - void DoSendCHLO(const CryptoHandshakeMessage* in, - QuicCryptoClientConfig::CachedState* cached); + void DoSendCHLO(QuicCryptoClientConfig::CachedState* cached); // Process REJ message from the server. void DoReceiveREJ(const CryptoHandshakeMessage* in,
diff --git a/net/quic/quic_crypto_client_stream_test.cc b/net/quic/quic_crypto_client_stream_test.cc index 0754f480..7d98f47b 100644 --- a/net/quic/quic_crypto_client_stream_test.cc +++ b/net/quic/quic_crypto_client_stream_test.cc
@@ -58,7 +58,7 @@ QuicCryptoClientStream* stream() { return session_->GetCryptoStream(); } - MockHelper helper_; + MockConnectionHelper helper_; PacketSavingConnection* connection_; scoped_ptr<TestQuicSpdyClientSession> session_; QuicServerId server_id_; @@ -237,10 +237,10 @@ CryptoTestUtils::SetupCryptoServerConfigForTest( server_connection_->clock(), server_connection_->random_generator(), server_session_->config(), &server_crypto_config_); - server_stream()->set_use_stateless_rejects_if_peer_supported(true); + FLAGS_enable_quic_stateless_reject_support = true; } - MockHelper helper_; + MockConnectionHelper helper_; // Client crypto stream state PacketSavingConnection* client_connection_;
diff --git a/net/quic/quic_crypto_server_stream.cc b/net/quic/quic_crypto_server_stream.cc index d4758336..30ba158 100644 --- a/net/quic/quic_crypto_server_stream.cc +++ b/net/quic/quic_crypto_server_stream.cc
@@ -38,7 +38,8 @@ num_handshake_messages_(0), num_handshake_messages_with_server_nonces_(0), num_server_config_update_messages_sent_(0), - use_stateless_rejects_if_peer_supported_(false), + use_stateless_rejects_if_peer_supported_( + FLAGS_enable_quic_stateless_reject_support), peer_supports_stateless_rejects_(false) { DCHECK_EQ(Perspective::IS_SERVER, session->connection()->perspective()); } @@ -93,7 +94,7 @@ DCHECK(validate_client_hello_cb_ != nullptr); validate_client_hello_cb_ = nullptr; - if (FLAGS_enable_quic_stateless_reject_support) { + if (use_stateless_rejects_if_peer_supported_) { peer_supports_stateless_rejects_ = DoesPeerSupportStatelessRejects(message); } @@ -108,9 +109,17 @@ } if (reply.tag() != kSHLO) { + if (reply.tag() == kSREJ) { + DCHECK(use_stateless_rejects_if_peer_supported()); + DCHECK(peer_supports_stateless_rejects()); + // Before sending the SREJ, cause the connection to save crypto packets + // so that they can be added to the time wait list manager and + // retransmitted. + session()->connection()->EnableSavingCryptoPackets(); + } SendHandshakeMessage(reply); - if (FLAGS_enable_quic_stateless_reject_support && reply.tag() == kSREJ) { + if (reply.tag() == kSREJ) { DCHECK(use_stateless_rejects_if_peer_supported()); DCHECK(peer_supports_stateless_rejects()); DCHECK(!handshake_confirmed()); @@ -180,7 +189,7 @@ CryptoHandshakeMessage server_config_update_message; if (!crypto_config_->BuildServerConfigUpdateMessage( - previous_source_address_tokens_, + session()->connection()->version(), previous_source_address_tokens_, session()->connection()->self_address().address(), session()->connection()->peer_address().address(), session()->connection()->clock(), @@ -255,7 +264,6 @@ previous_source_address_tokens_ = result.info.source_address_tokens; const bool use_stateless_rejects_in_crypto_config = - FLAGS_enable_quic_stateless_reject_support && use_stateless_rejects_if_peer_supported_ && peer_supports_stateless_rejects_; QuicConnection* connection = session()->connection();
diff --git a/net/quic/quic_crypto_server_stream.h b/net/quic/quic_crypto_server_stream.h index dfd8c95..f3d9c92 100644 --- a/net/quic/quic_crypto_server_stream.h +++ b/net/quic/quic_crypto_server_stream.h
@@ -92,15 +92,6 @@ return use_stateless_rejects_if_peer_supported_; } - // Used by the quic dispatcher to indicate that this crypto server - // stream should use stateless rejects, so long as stateless rejects - // are supported by the client. - void set_use_stateless_rejects_if_peer_supported( - bool use_stateless_rejects_if_peer_supported) { - use_stateless_rejects_if_peer_supported_ = - use_stateless_rejects_if_peer_supported; - } - bool peer_supports_stateless_rejects() const { return peer_supports_stateless_rejects_; }
diff --git a/net/quic/quic_crypto_server_stream_test.cc b/net/quic/quic_crypto_server_stream_test.cc index af3bcb3..01a2db8 100644 --- a/net/quic/quic_crypto_server_stream_test.cc +++ b/net/quic/quic_crypto_server_stream_test.cc
@@ -74,6 +74,7 @@ CryptoTestUtils::ProofSourceForTesting()), server_id_(kServerHostname, kServerPort, PRIVACY_MODE_DISABLED), client_crypto_config_(CryptoTestUtils::ProofVerifierForTesting()) { + FLAGS_enable_quic_stateless_reject_support = false; server_crypto_config_.set_strike_register_no_startup_period(); InitializeServer(); @@ -99,7 +100,8 @@ // called multiple times. void InitializeServer() { TestQuicSpdyServerSession* server_session = nullptr; - helpers_.push_back(new MockHelper); + helpers_.push_back(new MockConnectionHelper); + CreateServerSessionForTest(server_id_, QuicTime::Delta::FromSeconds(100000), helpers_.back(), &server_crypto_config_, &server_connection_, &server_session); @@ -122,7 +124,7 @@ // testing. May be called multiple times. void InitializeFakeClient(bool supports_stateless_rejects) { TestQuicSpdyClientSession* client_session = nullptr; - helpers_.push_back(new MockHelper); + helpers_.push_back(new MockConnectionHelper); CreateClientSessionForTest(server_id_, supports_stateless_rejects, QuicTime::Delta::FromSeconds(100000), helpers_.back(), &client_crypto_config_, @@ -164,9 +166,10 @@ } protected: - // Every connection gets its own MockHelper, tracked separately from the - // server and client state so their lifetimes persist through the whole test. - std::vector<MockHelper*> helpers_; + // Every connection gets its own MockConnectionHelper, tracked separately + // from the server and client state so their lifetimes persist through the + // whole test. + std::vector<MockConnectionHelper*> helpers_; // Server state PacketSavingConnection* server_connection_; @@ -210,7 +213,7 @@ TEST_P(QuicCryptoServerStreamTest, StatelessRejectAfterCHLO) { ValueRestore<bool> old_flag(&FLAGS_enable_quic_stateless_reject_support, true); - server_stream()->set_use_stateless_rejects_if_peer_supported(true); + InitializeServer(); InitializeFakeClient(/* supports_stateless_rejects= */ true); AdvanceHandshakeWithFakeClient(); @@ -242,7 +245,7 @@ TEST_P(QuicCryptoServerStreamTest, ConnectedAfterStatelessHandshake) { ValueRestore<bool> old_flag(&FLAGS_enable_quic_stateless_reject_support, true); - server_stream()->set_use_stateless_rejects_if_peer_supported(true); + InitializeServer(); InitializeFakeClient(/* supports_stateless_rejects= */ true); AdvanceHandshakeWithFakeClient(); @@ -269,7 +272,6 @@ // Now create new client and server streams with the existing config // and try the handshake again (0-RTT handshake). InitializeServer(); - server_stream()->set_use_stateless_rejects_if_peer_supported(true); InitializeFakeClient(/* supports_stateless_rejects= */ true); @@ -290,7 +292,7 @@ TEST_P(QuicCryptoServerStreamTest, NoStatelessRejectIfNoClientSupport) { ValueRestore<bool> old_flag(&FLAGS_enable_quic_stateless_reject_support, true); - server_stream()->set_use_stateless_rejects_if_peer_supported(true); + InitializeServer(); // The server is configured to use stateless rejects, but the client does not // support it.
diff --git a/net/quic/quic_crypto_stream_test.cc b/net/quic/quic_crypto_stream_test.cc index 7225030c..a6ffdbe 100644 --- a/net/quic/quic_crypto_stream_test.cc +++ b/net/quic/quic_crypto_stream_test.cc
@@ -61,7 +61,7 @@ } protected: - MockHelper helper_; + MockConnectionHelper helper_; MockConnection* connection_; MockQuicSpdySession session_; MockQuicCryptoStream stream_;
diff --git a/net/quic/quic_fec_group.cc b/net/quic/quic_fec_group.cc index 35251d9..37c3e5a 100644 --- a/net/quic/quic_fec_group.cc +++ b/net/quic/quic_fec_group.cc
@@ -190,4 +190,8 @@ return effective_encryption_level_; } +QuicFecGroupNumber QuicFecGroup::FecGroupNumber() const { + return min_protected_packet_; +} + } // namespace net
diff --git a/net/quic/quic_fec_group.h b/net/quic/quic_fec_group.h index 732e703b..c35835ca 100644 --- a/net/quic/quic_fec_group.h +++ b/net/quic/quic_fec_group.h
@@ -38,6 +38,7 @@ const base::StringPiece PayloadParity() const override; QuicPacketCount NumReceivedPackets() const override; EncryptionLevel EffectiveEncryptionLevel() const override; + QuicFecGroupNumber FecGroupNumber() const override; private: bool UpdateParity(base::StringPiece payload);
diff --git a/net/quic/quic_fec_group_interface.h b/net/quic/quic_fec_group_interface.h index 159662ad..87914f7 100644 --- a/net/quic/quic_fec_group_interface.h +++ b/net/quic/quic_fec_group_interface.h
@@ -63,6 +63,9 @@ // Returns the effective encryption level of the FEC group. virtual EncryptionLevel EffectiveEncryptionLevel() const = 0; + // Return the FEC group number of this group. + virtual QuicFecGroupNumber FecGroupNumber() const = 0; + // An optimized version of running |output| ^= |input|, where ^ is // byte-by-byte XOR and both |output| and |input| are of size |size_in_bytes|. static void XorBuffers(const char* input, size_t size_in_bytes, char* output);
diff --git a/net/quic/quic_flags.cc b/net/quic/quic_flags.cc index fe97495..767c1db 100644 --- a/net/quic/quic_flags.cc +++ b/net/quic/quic_flags.cc
@@ -111,3 +111,7 @@ // If true, use the unrolled prefetch path in QuicPacketCreator::CopyToBuffer. bool FLAGS_quic_packet_creator_prefetch = false; + +// If true, only migrate QUIC connections when client address changes are +// considered to be caused by NATs. +bool FLAGS_quic_disable_non_nat_address_migration = true;
diff --git a/net/quic/quic_flags.h b/net/quic/quic_flags.h index 7b7b0f42..a0e242a 100644 --- a/net/quic/quic_flags.h +++ b/net/quic/quic_flags.h
@@ -35,5 +35,6 @@ NET_EXPORT_PRIVATE extern bool FLAGS_quic_no_ack_notifier; NET_EXPORT_PRIVATE extern bool FLAGS_quic_count_unfinished_as_open_streams; NET_EXPORT_PRIVATE extern bool FLAGS_quic_packet_creator_prefetch; +NET_EXPORT_PRIVATE extern bool FLAGS_quic_disable_non_nat_address_migration; #endif // NET_QUIC_QUIC_FLAGS_H_
diff --git a/net/quic/quic_flow_controller.cc b/net/quic/quic_flow_controller.cc index 72f4c7fa..e2eaf3e 100644 --- a/net/quic/quic_flow_controller.cc +++ b/net/quic/quic_flow_controller.cc
@@ -176,7 +176,7 @@ if (available_window >= threshold) { DVLOG(1) << ENDPOINT << "Not sending WindowUpdate for stream " << id_ << ", available window: " << available_window - << ">= threshold: " << threshold; + << " >= threshold: " << threshold; return; }
diff --git a/net/quic/quic_flow_controller_test.cc b/net/quic/quic_flow_controller_test.cc index 9a7e452f..64705765 100644 --- a/net/quic/quic_flow_controller_test.cc +++ b/net/quic/quic_flow_controller_test.cc
@@ -40,7 +40,7 @@ QuicByteCount send_window_; QuicByteCount receive_window_; scoped_ptr<QuicFlowController> flow_controller_; - MockHelper helper_; + MockConnectionHelper helper_; MockConnection connection_; };
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc index 56aaaad..1d062fd7 100644 --- a/net/quic/quic_framer.cc +++ b/net/quic/quic_framer.cc
@@ -304,11 +304,7 @@ DVLOG(1) << "Truncating large frame, free bytes: " << free_bytes; return free_bytes; } - if (!FLAGS_quic_allow_oversized_packets_for_test) { - return 0; - } - LOG(DFATAL) << "Packet size too small to fit frame."; - return frame_len; + return 0; } QuicFramer::AckFrameInfo::AckFrameInfo() : max_delta(0) {} @@ -1363,6 +1359,7 @@ } // Parse the revived packets list. + // TODO(ianswett): Change the ack frame so it only expresses one revived. uint8 num_revived_packets; if (!reader->ReadBytes(&num_revived_packets, 1)) { set_detailed_error("Unable to read num revived packets."); @@ -1376,8 +1373,7 @@ set_detailed_error("Unable to read revived packet."); return false; } - - ack_frame->revived_packets.insert(revived_packet); + ack_frame->latest_revived_packet = revived_packet; } return true; @@ -1614,44 +1610,28 @@ encrypter_[level].reset(encrypter); } -QuicEncryptedPacket* QuicFramer::EncryptPayload(EncryptionLevel level, - QuicPacketNumber packet_number, - const QuicPacket& packet, - char* buffer, - size_t buffer_len) { +size_t QuicFramer::EncryptPayload(EncryptionLevel level, + QuicPacketNumber packet_number, + const QuicPacket& packet, + char* buffer, + size_t buffer_len) { DCHECK(encrypter_[level].get() != nullptr); - const size_t encrypted_len = - encrypter_[level]->GetCiphertextSize(packet.Plaintext().length()); StringPiece header_data = packet.BeforePlaintext(); - const size_t total_len = header_data.length() + encrypted_len; - - char* encryption_buffer = buffer; - // Allocate a large enough buffer for the header and the encrypted data. - const bool is_new_buffer = total_len > buffer_len; - if (is_new_buffer) { - if (!FLAGS_quic_allow_oversized_packets_for_test) { - LOG(DFATAL) << "Buffer of length:" << buffer_len - << " is not large enough to encrypt length " << total_len; - return nullptr; - } - encryption_buffer = new char[total_len]; - } // Copy in the header, because the encrypter only populates the encrypted // plaintext content. - memcpy(encryption_buffer, header_data.data(), header_data.length()); + const size_t header_len = header_data.length(); + memcpy(buffer, header_data.data(), header_len); // Encrypt the plaintext into the buffer. size_t output_length = 0; if (!encrypter_[level]->EncryptPacket( packet_number, packet.AssociatedData(), packet.Plaintext(), - encryption_buffer + header_data.length(), &output_length, - encrypted_len)) { + buffer + header_len, &output_length, buffer_len - header_len)) { RaiseError(QUIC_ENCRYPTION_FAILURE); - return nullptr; + return 0; } - return new QuicEncryptedPacket( - encryption_buffer, header_data.length() + output_length, is_new_buffer); + return header_len + output_length; } size_t QuicFramer::GetMaxPlaintextSize(size_t ciphertext_size) { @@ -1733,8 +1713,9 @@ ack_size += kNumberOfNackRangesSize + kNumberOfRevivedPacketsSize; ack_size += min(ack_info.nack_ranges.size(), kMaxNackRanges) * (missing_packet_number_length + PACKET_1BYTE_PACKET_NUMBER); - ack_size += min(ack.revived_packets.size(), - kMaxRevivedPackets) * largest_observed_length; + if (ack.latest_revived_packet != 0) { + ack_size += largest_observed_length; + } } // In version 23, if the ack will be truncated due to too many nack ranges, @@ -2026,20 +2007,20 @@ // Append revived packets. // If not all the revived packets fit, only mention the ones that do. - uint8 num_revived_packets = - static_cast<uint8>(min(frame.revived_packets.size(), kMaxRevivedPackets)); - num_revived_packets = static_cast<uint8>(min( - static_cast<size_t>(num_revived_packets), - (writer->capacity() - writer->length()) / largest_observed_length)); + uint8 num_revived_packets = frame.latest_revived_packet == 0 ? 0 : 1; + if (((writer->capacity() - writer->length()) / largest_observed_length) == + 0) { + num_revived_packets = 0; + } if (!writer->WriteBytes(&num_revived_packets, 1)) { return false; } - PacketNumberSet::const_iterator iter = frame.revived_packets.begin(); - for (int i = 0; i < num_revived_packets; ++i, ++iter) { - LOG_IF(DFATAL, !frame.missing_packets.Contains(*iter)); + if (num_revived_packets > 0) { + LOG_IF(DFATAL, + !frame.missing_packets.Contains(frame.latest_revived_packet)); if (!AppendPacketSequenceNumber(largest_observed_length, - *iter, writer)) { + frame.latest_revived_packet, writer)) { return false; } }
diff --git a/net/quic/quic_framer.h b/net/quic/quic_framer.h index 26e6995..0bc3299 100644 --- a/net/quic/quic_framer.h +++ b/net/quic/quic_framer.h
@@ -332,14 +332,13 @@ // takes ownership of |encrypter|. void SetEncrypter(EncryptionLevel level, QuicEncrypter* encrypter); - // Returns a new encrypted packet, owned by the caller. - // Encrypts into |buffer| if |buffer_len| is long enough, and otherwise - // constructs a new buffer owned by the EncryptedPacket. - QuicEncryptedPacket* EncryptPayload(EncryptionLevel level, - QuicPacketNumber packet_number, - const QuicPacket& packet, - char* buffer, - size_t buffer_len); + // Returns the length of the data encrypted into |buffer| if |buffer_len| is + // long enough, and otherwise 0. + size_t EncryptPayload(EncryptionLevel level, + QuicPacketNumber packet_number, + const QuicPacket& packet, + char* buffer, + size_t buffer_len); // Returns the maximum length of plaintext that can be encrypted // to ciphertext no larger than |ciphertext_size|.
diff --git a/net/quic/quic_framer_test.cc b/net/quic/quic_framer_test.cc index 51430b3..4a3d3be 100644 --- a/net/quic/quic_framer_test.cc +++ b/net/quic/quic_framer_test.cc
@@ -2186,7 +2186,7 @@ QuicAckFrame* frame = visitor_.ack_frames_[0]; EXPECT_EQ(0xBA, frame->entropy_hash); EXPECT_EQ(UINT64_C(0x0123456789ABF), frame->largest_observed); - EXPECT_EQ(0u, frame->revived_packets.size()); + EXPECT_EQ(0u, frame->latest_revived_packet); ASSERT_EQ(500u, frame->missing_packets.NumPacketsSlow()); EXPECT_EQ(UINT64_C(0x0123456789ABE) - 499, frame->missing_packets.Min()); EXPECT_EQ(UINT64_C(0x0123456789ABE), frame->missing_packets.Max()); @@ -4023,10 +4023,10 @@ AsChars(packet), arraysize(packet), false, PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_PACKET_NUMBER)); char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPayload( - ENCRYPTION_NONE, packet_number, *raw, buffer, kMaxPacketSize)); + size_t encrypted_length = framer_.EncryptPayload( + ENCRYPTION_NONE, packet_number, *raw, buffer, kMaxPacketSize); - ASSERT_TRUE(encrypted.get() != nullptr); + ASSERT_NE(0u, encrypted_length); EXPECT_TRUE(CheckEncryption(packet_number, raw.get())); } @@ -4061,10 +4061,10 @@ AsChars(packet), arraysize(packet), false, PACKET_8BYTE_CONNECTION_ID, kIncludeVersion, PACKET_6BYTE_PACKET_NUMBER)); char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPayload( - ENCRYPTION_NONE, packet_number, *raw, buffer, kMaxPacketSize)); + size_t encrypted_length = framer_.EncryptPayload( + ENCRYPTION_NONE, packet_number, *raw, buffer, kMaxPacketSize); - ASSERT_TRUE(encrypted.get() != nullptr); + ASSERT_NE(0u, encrypted_length); EXPECT_TRUE(CheckEncryption(packet_number, raw.get())); } @@ -4090,11 +4090,13 @@ scoped_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames)); ASSERT_TRUE(raw_ack_packet != nullptr); char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> ack_packet( + size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, header.packet_number, - *raw_ack_packet, buffer, kMaxPacketSize)); + *raw_ack_packet, buffer, kMaxPacketSize); + ASSERT_NE(0u, encrypted_length); // Now make sure we can turn our ack packet back into an ack frame. - ASSERT_TRUE(framer_.ProcessPacket(*ack_packet)); + ASSERT_TRUE(framer_.ProcessPacket( + QuicEncryptedPacket(buffer, encrypted_length, false))); ASSERT_EQ(1u, visitor_.ack_frames_.size()); QuicAckFrame& processed_ack_frame = *visitor_.ack_frames_[0]; EXPECT_TRUE(processed_ack_frame.is_truncated); @@ -4126,11 +4128,13 @@ scoped_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames, 500)); ASSERT_TRUE(raw_ack_packet != nullptr); char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> ack_packet( + size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, header.packet_number, - *raw_ack_packet, buffer, kMaxPacketSize)); + *raw_ack_packet, buffer, kMaxPacketSize); + ASSERT_NE(0u, encrypted_length); // Now make sure we can turn our ack packet back into an ack frame. - ASSERT_TRUE(framer_.ProcessPacket(*ack_packet)); + ASSERT_TRUE(framer_.ProcessPacket( + QuicEncryptedPacket(buffer, encrypted_length, false))); ASSERT_EQ(1u, visitor_.ack_frames_.size()); QuicAckFrame& processed_ack_frame = *visitor_.ack_frames_[0]; EXPECT_TRUE(processed_ack_frame.is_truncated); @@ -4165,12 +4169,14 @@ ASSERT_TRUE(raw_ack_packet != nullptr); char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> ack_packet( + size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, header.packet_number, - *raw_ack_packet, buffer, kMaxPacketSize)); + *raw_ack_packet, buffer, kMaxPacketSize); + ASSERT_NE(0u, encrypted_length); // Now make sure we can turn our ack packet back into an ack frame. - ASSERT_TRUE(framer_.ProcessPacket(*ack_packet)); + ASSERT_TRUE(framer_.ProcessPacket( + QuicEncryptedPacket(buffer, encrypted_length, false))); // Test for clean truncation of the ack by comparing the length of the // original packets to the re-serialized packets.
diff --git a/net/quic/quic_headers_stream.cc b/net/quic/quic_headers_stream.cc index d86437f..c47f14f 100644 --- a/net/quic/quic_headers_stream.cc +++ b/net/quic/quic_headers_stream.cc
@@ -73,6 +73,16 @@ CloseConnection("SPDY frame padding received."); } + SpdyHeadersHandlerInterface* OnHeaderFrameStart( + SpdyStreamId stream_id) override { + LOG(FATAL); + return nullptr; + } + + void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) override { + LOG(FATAL); + } + void OnError(SpdyFramer* framer) override { CloseConnection(base::StringPrintf( "SPDY framing error: %s", @@ -289,9 +299,7 @@ DVLOG(1) << "stream " << stream_id << ": Net.QuicSession.HeadersHOLBlockedTime " << delta.ToMilliseconds(); - UMA_HISTOGRAM_TIMES( - "Net.QuicSession.HeadersHOLBlockedTime", - base::TimeDelta::FromMicroseconds(delta.ToMicroseconds())); + spdy_session_->OnHeadersHeadOfLineBlocking(delta); } prev_max_timestamp_ = std::max(prev_max_timestamp_, cur_max_timestamp_); cur_max_timestamp_ = QuicTime::Zero();
diff --git a/net/quic/quic_headers_stream_test.cc b/net/quic/quic_headers_stream_test.cc index 9b93bbd..b5ca189 100644 --- a/net/quic/quic_headers_stream_test.cc +++ b/net/quic/quic_headers_stream_test.cc
@@ -4,7 +4,6 @@ #include "net/quic/quic_headers_stream.h" -#include "base/test/histogram_tester.h" #include "net/quic/quic_utils.h" #include "net/quic/spdy_utils.h" #include "net/quic/test_tools/quic_connection_peer.h" @@ -15,8 +14,6 @@ #include "net/spdy/spdy_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" -using base::Bucket; -using base::HistogramTester; using base::StringPiece; using std::ostream; using std::string; @@ -46,6 +43,9 @@ size_t len, bool fin)); MOCK_METHOD2(OnStreamPadding, void(SpdyStreamId stream_id, size_t len)); + MOCK_METHOD1(OnHeaderFrameStart, + SpdyHeadersHandlerInterface*(SpdyStreamId stream_id)); + MOCK_METHOD2(OnHeaderFrameEnd, void(SpdyStreamId stream_id, bool end)); MOCK_METHOD3(OnControlFrameHeaderData, bool(SpdyStreamId stream_id, const char* header_data, size_t len)); @@ -226,7 +226,7 @@ static const bool kFrameComplete = true; static const bool kHasPriority = true; - MockHelper helper_; + MockConnectionHelper helper_; StrictMock<MockConnection>* connection_; StrictMock<MockQuicSpdySession> session_; QuicHeadersStream* headers_stream_; @@ -303,17 +303,8 @@ } TEST_P(QuicHeadersStreamTest, EmptyHeaderHOLBlockedTime) { -// In the absence of surfacing HOL measurements externally, via UMA -// or tcp connection stats, log messages are the only indication. -// This test verifies that false positives are not generated when -// headers arrive in order. -#if 0 - ScopedMockLog log(kDoNotCaptureLogsYet); - EXPECT_CALL(log, Log(_, _, _)).Times(0); - log.StartCapturingLogs(); -#endif - InSequence seq; - HistogramTester histogram_tester; + EXPECT_CALL(session_, OnHeadersHeadOfLineBlocking(_)).Times(0); + testing::InSequence seq; bool fin = true; for (int stream_num = 0; stream_num < 10; stream_num++) { QuicStreamId stream_id = QuicClientDataStreamId(stream_num); @@ -340,18 +331,9 @@ connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); stream_frame_.offset += frame->size(); } - histogram_tester.ExpectTotalCount("Net.QuicSession.HeadersHOLBlockedTime", 0); } TEST_P(QuicHeadersStreamTest, NonEmptyHeaderHOLBlockedTime) { -// In the absence of surfacing HOL measurements externally, via UMA -// or tcp connection stats, log messages are the only indication. -// This test verifies that HOL blocking log messages are correct -// when there are out of order arrivals. -#if 0 - ScopedMockLog log(kDoNotCaptureLogsYet); -#endif - HistogramTester histogram_tester; QuicStreamId stream_id; bool fin = true; QuicStreamFrame stream_frames[10]; @@ -385,36 +367,16 @@ .Times(1); } } -#if 0 - // Actually writing the frames in reverse order will trigger log messages. - { - InSequence seq; - for (int stream_num = 0; stream_num < 10; ++stream_num) { - stream_id = QuicClientDataStreamId(stream_num); - if (stream_num > 0) { - string expected_msg = StringPrintf( - "stream %d: Net.QuicSession.HeadersHOLBlockedTime %d", - stream_id, stream_num); -#ifndef NDEBUG - EXPECT_CALL(log, Log(INFO, _, expected_msg)); -#endif - } - } - } - log.StartCapturingLogs(); -#endif + + // Actually writing the frames in reverse order will cause HOL blocking. + EXPECT_CALL(session_, OnHeadersHeadOfLineBlocking(_)).Times(9); + for (int stream_num = 9; stream_num >= 0; --stream_num) { DVLOG(1) << "OnStreamFrame for stream " << stream_num << " offset " << stream_frames[stream_num].offset; headers_stream_->OnStreamFrame(stream_frames[stream_num]); connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); } - // We expect 1 sample each for delays from 1 to 9 ms (8 and 9 go - // into the same bucket). - EXPECT_THAT( - histogram_tester.GetAllSamples("Net.QuicSession.HeadersHOLBlockedTime"), - ElementsAre(Bucket(1, 1), Bucket(2, 1), Bucket(3, 1), Bucket(4, 1), - Bucket(5, 1), Bucket(6, 1), Bucket(7, 1), Bucket(8, 2))); } TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) {
diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc index 3679d19..ccbf7e9 100644 --- a/net/quic/quic_packet_creator.cc +++ b/net/quic/quic_packet_creator.cc
@@ -76,7 +76,6 @@ random_bool_source_(new QuicRandomBoolSource(random_generator)), packet_number_(0), should_fec_protect_(false), - fec_group_number_(0), send_version_in_packet_(framer->perspective() == Perspective::IS_CLIENT), max_packet_length_(0), max_packets_per_fec_group_(kDefaultMaxPacketsPerFecGroup), @@ -130,6 +129,10 @@ DCHECK_LT(0u, max_packets_per_fec_group_); } +QuicFecGroupNumber QuicPacketCreator::fec_group_number() { + return fec_group_ != nullptr ? fec_group_->FecGroupNumber() : 0; +} + bool QuicPacketCreator::ShouldSendFec(bool force_close) const { DCHECK(!HasPendingFrames()); return fec_group_.get() != nullptr && fec_group_->NumReceivedPackets() > 0 && @@ -175,7 +178,6 @@ } DCHECK(should_fec_protect_); should_fec_protect_ = false; - fec_group_number_ = 0; } bool QuicPacketCreator::IsFecProtected() const { @@ -205,8 +207,7 @@ } // Start a new FEC group since protection is on. Set the fec group number to // the packet number of the next packet. - fec_group_number_ = packet_number() + 1; - fec_group_.reset(new QuicFecGroup(fec_group_number_)); + fec_group_.reset(new QuicFecGroup(packet_number_ + 1)); return IN_FEC_GROUP; } @@ -479,9 +480,12 @@ DCHECK_LT(0u, encrypted_buffer_len); LOG_IF(DFATAL, queued_frames_.empty()) << "Attempt to serialize empty packet"; - DCHECK_GE(packet_number_ + 1, fec_group_number_); + if (fec_group_.get() != nullptr) { + DCHECK_GE(packet_number_ + 1, fec_group_->FecGroupNumber()); + } QuicPacketHeader header; - FillPacketHeader(should_fec_protect_ ? fec_group_number_ : 0, false, &header); + // FillPacketHeader increments packet_number_. + FillPacketHeader(fec_group_number(), false, &header); MaybeAddPadding(); @@ -500,17 +504,8 @@ ALIGNAS(64) char buffer[kMaxPacketSize]; // Use the packet_size_ instead of the buffer size to ensure smaller // packet sizes are properly used. - scoped_ptr<char[]> large_buffer; - size_t length = 0; - const bool use_stack_buffer = packet_size_ <= kMaxPacketSize; - if (use_stack_buffer) { - length = - framer_->BuildDataPacket(header, queued_frames_, buffer, packet_size_); - } else { - large_buffer.reset(new char[packet_size_]); - length = framer_->BuildDataPacket(header, queued_frames_, - large_buffer.get(), packet_size_); - } + size_t length = + framer_->BuildDataPacket(header, queued_frames_, buffer, packet_size_); if (length == 0) { LOG(DFATAL) << "Failed to serialize " << queued_frames_.size() << " frames."; @@ -519,7 +514,7 @@ // TODO(ianswett) Consider replacing QuicPacket with something else, // since it's only used to provide convenience methods to FEC and encryption. - QuicPacket packet(use_stack_buffer ? buffer : large_buffer.get(), length, + QuicPacket packet(buffer, length, /* owns_buffer */ false, header.public_header.connection_id_length, header.public_header.version_flag, @@ -533,10 +528,10 @@ } // Immediately encrypt the packet, to ensure we don't encrypt the same packet // packet number multiple times. - QuicEncryptedPacket* encrypted = + size_t encrypted_length = framer_->EncryptPayload(encryption_level_, packet_number_, packet, encrypted_buffer, encrypted_buffer_len); - if (encrypted == nullptr) { + if (encrypted_length == 0) { LOG(DFATAL) << "Failed to encrypt packet number " << packet_number_; return NoPacket(); } @@ -561,7 +556,8 @@ needs_padding_ = false; return SerializedPacket( header.packet_number, header.public_header.packet_number_length, - encrypted, QuicFramer::GetPacketEntropyHash(header), + encrypted_buffer, encrypted_length, /* owns_buffer*/ false, + QuicFramer::GetPacketEntropyHash(header), queued_retransmittable_frames_.release(), has_ack, has_stop_waiting); } @@ -575,26 +571,27 @@ } DCHECK_EQ(0u, queued_frames_.size()); QuicPacketHeader header; - FillPacketHeader(fec_group_number_, true, &header); + FillPacketHeader(fec_group_->FecGroupNumber(), true, &header); scoped_ptr<QuicPacket> packet( framer_->BuildFecPacket(header, fec_group_->PayloadParity())); fec_group_.reset(nullptr); packet_size_ = 0; LOG_IF(DFATAL, packet == nullptr) - << "Failed to serialize fec packet for group:" << fec_group_number_; + << "Failed to serialize fec packet for group:" + << fec_group_->FecGroupNumber(); DCHECK_GE(max_packet_length_, packet->length()); // Immediately encrypt the packet, to ensure we don't encrypt the same packet // packet number multiple times. - QuicEncryptedPacket* encrypted = framer_->EncryptPayload( + size_t encrypted_length = framer_->EncryptPayload( encryption_level_, packet_number_, *packet, buffer, buffer_len); - if (encrypted == nullptr) { + if (encrypted_length == 0) { LOG(DFATAL) << "Failed to encrypt packet number " << packet_number_; return NoPacket(); } SerializedPacket serialized( - header.packet_number, header.public_header.packet_number_length, - encrypted, QuicFramer::GetPacketEntropyHash(header), nullptr, false, - false); + header.packet_number, header.public_header.packet_number_length, buffer, + encrypted_length, /* owns_buffer */ false, + QuicFramer::GetPacketEntropyHash(header), nullptr, false, false); serialized.is_fec_packet = true; return serialized; }
diff --git a/net/quic/quic_packet_creator.h b/net/quic/quic_packet_creator.h index da667854..31646ec7 100644 --- a/net/quic/quic_packet_creator.h +++ b/net/quic/quic_packet_creator.h
@@ -226,10 +226,9 @@ // To turn off FEC protection, use StopFecProtectingPackets(). void set_max_packets_per_fec_group(size_t max_packets_per_fec_group); - // Returns the currently open FEC group's number. If there isn't an open FEC - // group, returns the last closed FEC group number. Returns 0 when FEC is - // disabled or no FEC group has been created yet. - QuicFecGroupNumber fec_group_number() { return fec_group_number_; } + // Returns the currently open FEC group's number. Returns 0 when FEC is + // disabled or no FEC group is open. + QuicFecGroupNumber fec_group_number(); private: friend class test::QuicPacketCreatorPeer; @@ -276,7 +275,6 @@ QuicPacketNumber packet_number_; // If true, any created packets will be FEC protected. bool should_fec_protect_; - QuicFecGroupNumber fec_group_number_; scoped_ptr<QuicFecGroup> fec_group_; // Controls whether protocol version should be included while serializing the // packet.
diff --git a/net/quic/quic_packet_generator.cc b/net/quic/quic_packet_generator.cc index a5e707e..12ebcfb 100644 --- a/net/quic/quic_packet_generator.cc +++ b/net/quic/quic_packet_generator.cc
@@ -288,28 +288,28 @@ void QuicPacketGenerator::MaybeSendFecPacketAndCloseGroup(bool force, bool is_fec_timeout) { - if (!ShouldSendFecPacket(force)) { - return; + if (ShouldSendFecPacket(force)) { + // If we want to send FEC packet only when FEC alaram goes off and if it is + // not a FEC timeout then close the group and dont send FEC packet. + if (fec_send_policy_ == FEC_ALARM_TRIGGER && !is_fec_timeout) { + ResetFecGroup(); + } else { + // TODO(jri): SerializeFec can return a NULL packet, and this should cause + // an early return, with a call to delegate_->OnPacketGenerationError. + char buffer[kMaxPacketSize]; + SerializedPacket serialized_fec = + packet_creator_.SerializeFec(buffer, kMaxPacketSize); + DCHECK(serialized_fec.packet); + delegate_->OnSerializedPacket(serialized_fec); + } } - // If we want to send FEC packet only when FEC alaram goes off and if it is - // not a FEC timeout then close the group and dont send FEC packet. - if (fec_send_policy_ == FEC_ALARM_TRIGGER && !is_fec_timeout) { - ResetFecGroup(); - } else { - // TODO(jri): SerializeFec can return a NULL packet, and this should - // cause an early return, with a call to delegate_->OnPacketGenerationError. - char buffer[kMaxPacketSize]; - SerializedPacket serialized_fec = - packet_creator_.SerializeFec(buffer, kMaxPacketSize); - DCHECK(serialized_fec.packet); - delegate_->OnSerializedPacket(serialized_fec); - } // Turn FEC protection off if creator's protection is on and the creator // does not have an open FEC group. // Note: We only wait until the frames queued in the creator are flushed; // pending frames in the generator will not keep us from turning FEC off. - if (!should_fec_protect_ && !packet_creator_.IsFecGroupOpen()) { + if (!should_fec_protect_ && packet_creator_.IsFecProtected() && + !packet_creator_.IsFecGroupOpen()) { packet_creator_.StopFecProtectingPackets(); DCHECK(!packet_creator_.IsFecProtected()); }
diff --git a/net/quic/quic_packet_generator_test.cc b/net/quic/quic_packet_generator_test.cc index 044dfa4..0dcf229 100644 --- a/net/quic/quic_packet_generator_test.cc +++ b/net/quic/quic_packet_generator_test.cc
@@ -1217,7 +1217,35 @@ // FEC_ANY_TRIGGER. CheckPacketIsFec(8, 7); } - EXPECT_TRUE(creator_->IsFecProtected()); + EXPECT_FALSE(creator_->IsFecProtected()); + + // Do the another send (with MAY_FEC_PROTECT) on a different stream id, which + // should not produce an FEC packet because the last FEC group has been + // closed. + { + InSequence dummy; + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); + } + consumed = generator_.ConsumeData(9, CreateData(data_len), 0, true, + MAY_FEC_PROTECT, nullptr); + EXPECT_EQ(data_len, consumed.bytes_consumed); + EXPECT_TRUE(consumed.fin_consumed); + EXPECT_FALSE(generator_.HasQueuedFrames()); + if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { + CheckPacketHasSingleStreamFrame(6); + CheckPacketHasSingleStreamFrame(7); + CheckPacketHasSingleStreamFrame(8); + } else { + CheckPacketHasSingleStreamFrame(9); + CheckPacketHasSingleStreamFrame(10); + CheckPacketHasSingleStreamFrame(11); + } + EXPECT_FALSE(creator_->IsFecProtected()); } // 1. Create and send one packet with MUST_FEC_PROTECT.
diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc index c241f4e..762523a4 100644 --- a/net/quic/quic_protocol.cc +++ b/net/quic/quic_protocol.cc
@@ -142,6 +142,10 @@ return MakeQuicTag('Q', '0', '2', '7'); case QUIC_VERSION_28: return MakeQuicTag('Q', '0', '2', '8'); + case QUIC_VERSION_29: + return MakeQuicTag('Q', '0', '2', '9'); + case QUIC_VERSION_30: + return MakeQuicTag('Q', '0', '3', '0'); default: // This shold be an ERROR because we should never attempt to convert an // invalid QuicVersion to be written to the wire. @@ -172,6 +176,8 @@ RETURN_STRING_LITERAL(QUIC_VERSION_26); RETURN_STRING_LITERAL(QUIC_VERSION_27); RETURN_STRING_LITERAL(QUIC_VERSION_28); + RETURN_STRING_LITERAL(QUIC_VERSION_29); + RETURN_STRING_LITERAL(QUIC_VERSION_30); default: return "QUIC_VERSION_UNSUPPORTED"; } @@ -235,7 +241,8 @@ : entropy_hash(0), is_truncated(false), largest_observed(0), - delta_time_largest_observed(QuicTime::Delta::Infinite()) {} + delta_time_largest_observed(QuicTime::Delta::Infinite()), + latest_revived_packet(0) {} QuicAckFrame::~QuicAckFrame() {} @@ -468,13 +475,9 @@ << " delta_time_largest_observed: " << ack_frame.delta_time_largest_observed.ToMicroseconds() << " missing_packets: [ " << ack_frame.missing_packets - << " ] is_truncated: " << ack_frame.is_truncated; - os << " revived_packets: [ "; - for (PacketNumberSet::const_iterator it = ack_frame.revived_packets.begin(); - it != ack_frame.revived_packets.end(); ++it) { - os << *it << " "; - } - os << " ] received_packets: [ "; + << " ] is_truncated: " << ack_frame.is_truncated + << " revived_packet: " << ack_frame.latest_revived_packet + << " received_packets: [ "; for (const std::pair<QuicPacketNumber, QuicTime>& p : ack_frame.received_packet_times) { os << p.first << " at " << p.second.ToDebuggingValue() << " "; @@ -775,6 +778,26 @@ has_ack(has_ack), has_stop_waiting(has_stop_waiting) {} +SerializedPacket::SerializedPacket( + QuicPacketNumber packet_number, + QuicPacketNumberLength packet_number_length, + char* encrypted_buffer, + size_t encrypted_length, + bool owns_buffer, + QuicPacketEntropyHash entropy_hash, + RetransmittableFrames* retransmittable_frames, + bool has_ack, + bool has_stop_waiting) + : SerializedPacket(packet_number, + packet_number_length, + new QuicEncryptedPacket(encrypted_buffer, + encrypted_length, + owns_buffer), + entropy_hash, + retransmittable_frames, + has_ack, + has_stop_waiting) {} + SerializedPacket::~SerializedPacket() {} QuicEncryptedPacket* QuicEncryptedPacket::Clone() const {
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h index aa008c4b..1286b9a 100644 --- a/net/quic/quic_protocol.h +++ b/net/quic/quic_protocol.h
@@ -346,6 +346,8 @@ QUIC_VERSION_26 = 26, // In CHLO, send XLCT tag containing hash of leaf cert QUIC_VERSION_27 = 27, // Sends a nonce in the SHLO. QUIC_VERSION_28 = 28, // Receiver can refuse to create a requested stream. + QUIC_VERSION_29 = 29, // Server and client honor QUIC_STREAM_NO_ERROR. + QUIC_VERSION_30 = 30, // Add server side support of cert transparency. }; // This vector contains QUIC versions which we currently support. @@ -356,7 +358,8 @@ // IMPORTANT: if you are adding to this list, follow the instructions at // http://sites/quic/adding-and-removing-versions static const QuicVersion kSupportedQuicVersions[] = { - QUIC_VERSION_28, QUIC_VERSION_27, QUIC_VERSION_26, QUIC_VERSION_25}; + QUIC_VERSION_30, QUIC_VERSION_29, QUIC_VERSION_28, + QUIC_VERSION_27, QUIC_VERSION_26, QUIC_VERSION_25}; typedef std::vector<QuicVersion> QuicVersionVector; @@ -418,6 +421,8 @@ QuicPacketNumberLength packet_number_length); enum QuicRstStreamErrorCode { + // Complete response has been sent, sending a RST to ask the other endpoint + // to stop sending request data without discarding the response. QUIC_STREAM_NO_ERROR = 0, // There was some error which halted stream processing. @@ -490,8 +495,6 @@ // ACK frame data is malformed. QUIC_INVALID_ACK_DATA = 9, - // deprecated: QUIC_INVALID_CONGESTION_FEEDBACK_DATA = 47, - // Version negotiation packet is malformed. QUIC_INVALID_VERSION_NEGOTIATION_PACKET = 10, // Public RST packet is malformed. @@ -502,8 +505,6 @@ QUIC_ENCRYPTION_FAILURE = 13, // The packet exceeded kMaxPacketSize. QUIC_PACKET_TOO_LARGE = 14, - // Data was sent for a stream which did not exist. - QUIC_PACKET_FOR_NONEXISTENT_STREAM = 15, // The peer is going away. May be a client or server. QUIC_PEER_GOING_AWAY = 16, // A stream ID was invalid. @@ -521,8 +522,6 @@ // Invalid protocol version. QUIC_INVALID_VERSION = 20, - // deprecated: QUIC_STREAM_RST_BEFORE_HEADERS_DECOMPRESSED = 21 - // The Header ID for a stream was too far from the previous. QUIC_INVALID_HEADER_ID = 22, // Negotiable parameter received during handshake had invalid value. @@ -868,9 +867,9 @@ // The set of packets which we're expecting and have not received. PacketNumberQueue missing_packets; - // Packets which have been revived via FEC. - // All of these must also be in missing_packets. - PacketNumberSet revived_packets; + // Packet most recently revived via FEC, 0 if no packet was revived by FEC. + // If non-zero, must be present in missing_packets. + QuicPacketNumber latest_revived_packet; }; // True if the packet number is greater than largest_observed or is listed @@ -988,6 +987,23 @@ NUM_ENCRYPTION_LEVELS, }; +enum PeerAddressChangeType { + NO_CHANGE, + // Peer address changes which are considered to be cause by NATs. Currently, + // IPv4 address change with /24 does not change is considered to be cause by + // NATs. + NAT_PORT_REBINDING, + IPV4_SUBNET_REBINDING, + // IPv6 related address changes. + IPV4_TO_IPV6, + IPV6_TO_IPV4, + IPV6_TO_IPV6, + // This type is used when we always allow peer address changes. + UNKNOWN, + // All other peer address change types. + UNSPECIFIED, +}; + struct NET_EXPORT_PRIVATE QuicFrame { QuicFrame(); explicit QuicFrame(QuicPaddingFrame padding_frame); @@ -1154,6 +1170,15 @@ RetransmittableFrames* retransmittable_frames, bool has_ack, bool has_stop_waiting); + SerializedPacket(QuicPacketNumber packet_number, + QuicPacketNumberLength packet_number_length, + char* encrypted_buffer, + size_t encrypted_length, + bool owns_buffer, + QuicPacketEntropyHash entropy_hash, + RetransmittableFrames* retransmittable_frames, + bool has_ack, + bool has_stop_waiting); ~SerializedPacket(); QuicEncryptedPacket* packet;
diff --git a/net/quic/quic_received_packet_manager.cc b/net/quic/quic_received_packet_manager.cc index f49391c2..98cc86b18 100644 --- a/net/quic/quic_received_packet_manager.cc +++ b/net/quic/quic_received_packet_manager.cc
@@ -179,13 +179,15 @@ ack_frame_.received_packet_times.push_back( std::make_pair(packet_number, receipt_time)); - ack_frame_.revived_packets.erase(packet_number); + if (ack_frame_.latest_revived_packet == packet_number) { + ack_frame_.latest_revived_packet = 0; + } } void QuicReceivedPacketManager::RecordPacketRevived( QuicPacketNumber packet_number) { LOG_IF(DFATAL, !IsAwaitingPacket(packet_number)); - ack_frame_.revived_packets.insert(packet_number); + ack_frame_.latest_revived_packet = packet_number; } bool QuicReceivedPacketManager::IsMissing(QuicPacketNumber packet_number) { @@ -253,9 +255,9 @@ bool QuicReceivedPacketManager::DontWaitForPacketsBefore( QuicPacketNumber least_unacked) { - ack_frame_.revived_packets.erase( - ack_frame_.revived_packets.begin(), - ack_frame_.revived_packets.lower_bound(least_unacked)); + if (ack_frame_.latest_revived_packet < least_unacked) { + ack_frame_.latest_revived_packet = 0; + } return ack_frame_.missing_packets.RemoveUpTo(least_unacked); }
diff --git a/net/quic/quic_received_packet_manager_test.cc b/net/quic/quic_received_packet_manager_test.cc index 31ff8a06..b5a3542 100644 --- a/net/quic/quic_received_packet_manager_test.cc +++ b/net/quic/quic_received_packet_manager_test.cc
@@ -355,8 +355,7 @@ received_manager_.UpdateReceivedPacketInfo(&ack, QuicTime::Zero()); EXPECT_EQ(1u, ack.missing_packets.NumPacketsSlow()); EXPECT_EQ(2u, ack.missing_packets.Min()); - EXPECT_EQ(1u, ack.revived_packets.size()); - EXPECT_EQ(2u, *ack.revived_packets.begin()); + EXPECT_EQ(2u, ack.latest_revived_packet); } TEST_F(QuicReceivedPacketManagerTest, PacketRevivedThenReceived) { @@ -368,7 +367,7 @@ QuicAckFrame ack; received_manager_.UpdateReceivedPacketInfo(&ack, QuicTime::Zero()); EXPECT_TRUE(ack.missing_packets.Empty()); - EXPECT_TRUE(ack.revived_packets.empty()); + EXPECT_EQ(0u, ack.latest_revived_packet); }
diff --git a/net/quic/quic_reliable_client_stream_test.cc b/net/quic/quic_reliable_client_stream_test.cc index db5331f..9162ba9a 100644 --- a/net/quic/quic_reliable_client_stream_test.cc +++ b/net/quic/quic_reliable_client_stream_test.cc
@@ -98,7 +98,7 @@ QuicCryptoClientConfig crypto_config_; testing::StrictMock<MockDelegate> delegate_; - MockHelper helper_; + MockConnectionHelper helper_; MockQuicSpdySession session_; QuicReliableClientStream* stream_; SpdyHeaderBlock headers_;
diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc index 3d4fb9b..586d27a 100644 --- a/net/quic/quic_sent_packet_manager.cc +++ b/net/quic/quic_sent_packet_manager.cc
@@ -326,10 +326,8 @@ } // Discard any retransmittable frames associated with revived packets. - for (PacketNumberSet::const_iterator revived_it = - ack_frame.revived_packets.begin(); - revived_it != ack_frame.revived_packets.end(); ++revived_it) { - MarkPacketRevived(*revived_it, delta_largest_observed); + if (ack_frame.latest_revived_packet != 0) { + MarkPacketRevived(ack_frame.latest_revived_packet, delta_largest_observed); } }
diff --git a/net/quic/quic_sent_packet_manager_test.cc b/net/quic/quic_sent_packet_manager_test.cc index 6f12f785..deb076e 100644 --- a/net/quic/quic_sent_packet_manager_test.cc +++ b/net/quic/quic_sent_packet_manager_test.cc
@@ -501,7 +501,7 @@ QuicAckFrame ack_frame; ack_frame.largest_observed = 3; ack_frame.missing_packets.Add(1); - ack_frame.revived_packets.insert(1); + ack_frame.latest_revived_packet = 1; QuicPacketNumber acked[] = {2, 3}; ExpectAcksAndLosses(true, acked, arraysize(acked), nullptr, 0); manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()); @@ -547,7 +547,7 @@ // Ack 5th packet (FEC) and revive 1st packet. 1st packet should now be // removed from pending retransmissions map. ack_frame.largest_observed = 5; - ack_frame.revived_packets.insert(1); + ack_frame.latest_revived_packet = 1; ExpectAck(5); manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc index 39259240..2a325d6 100644 --- a/net/quic/quic_session.cc +++ b/net/quic/quic_session.cc
@@ -157,7 +157,7 @@ return; } - ReliableQuicStream* stream = GetDynamicStream(frame.stream_id); + ReliableQuicStream* stream = GetOrCreateDynamicStream(frame.stream_id); if (!stream) { // The RST frame contains the final byte offset for the stream: we can now // update the connection level flow controller if needed. @@ -570,7 +570,7 @@ if (it != static_stream_map_.end()) { return it->second; } - return GetDynamicStream(stream_id); + return GetOrCreateDynamicStream(stream_id); } void QuicSession::StreamDraining(QuicStreamId stream_id) { @@ -586,10 +586,11 @@ } } -ReliableQuicStream* QuicSession::GetDynamicStream( +ReliableQuicStream* QuicSession::GetOrCreateDynamicStream( const QuicStreamId stream_id) { - if (static_stream_map_.find(stream_id) != static_stream_map_.end()) { - DLOG(FATAL) << "Attempt to call GetDynamicStream for a static stream"; + if (ContainsKey(static_stream_map_, stream_id)) { + DLOG(FATAL) + << "Attempt to call GetOrCreateDynamicStream for a static stream"; return nullptr; } @@ -603,31 +604,14 @@ } if (stream_id % 2 == next_outgoing_stream_id_ % 2) { - // We've received a frame for a locally-created stream that is not - // currently active. This is an error. - CloseConnection(QUIC_PACKET_FOR_NONEXISTENT_STREAM); + // Received a frame for a locally-created stream that is not currently + // active. This is an error. + CloseConnection(QUIC_INVALID_STREAM_ID); return nullptr; } - return GetIncomingDynamicStream(stream_id); -} - -ReliableQuicStream* QuicSession::GetIncomingDynamicStream( - QuicStreamId stream_id) { - if (IsClosedStream(stream_id)) { - return nullptr; - } available_streams_.erase(stream_id); - // Legitimate streams created by the peer are alternately-numbered. - if (FLAGS_allow_many_available_streams && - stream_id % 2 != largest_peer_created_stream_id_ % 2) { - // Close the connection. - DVLOG(1) << "Invalid incoming stream_id " << stream_id; - connection()->SendConnectionClose(QUIC_INVALID_STREAM_ID); - return nullptr; - } - if (stream_id > largest_peer_created_stream_id_) { if (FLAGS_allow_many_available_streams) { // Check if the new number of available streams would cause the number of
diff --git a/net/quic/quic_session.h b/net/quic/quic_session.h index 8c3f079..cbdfb05 100644 --- a/net/quic/quic_session.h +++ b/net/quic/quic_session.h
@@ -53,6 +53,7 @@ HANDSHAKE_CONFIRMED, }; + // Takes ownership of |connection|. QuicSession(QuicConnection* connection, const QuicConfig& config); ~QuicSession() override; @@ -225,9 +226,11 @@ // underlying counter. QuicStreamId GetNextOutgoingStreamId(); - ReliableQuicStream* GetIncomingDynamicStream(QuicStreamId stream_id); - - ReliableQuicStream* GetDynamicStream(const QuicStreamId stream_id); + // Returns existing stream with id = |stream_id|. If no such stream exists, + // and |stream_id| is a peer-created id, then a new stream is created and + // returned. However if |stream_id| is a locally-created id and no such stream + // exists, the connection is closed. + ReliableQuicStream* GetOrCreateDynamicStream(QuicStreamId stream_id); // This is called after every call other than OnConnectionClose from the // QuicConnectionVisitor to allow post-processing once the work has been done.
diff --git a/net/quic/quic_session_test.cc b/net/quic/quic_session_test.cc index 244743e2..6d29f23 100644 --- a/net/quic/quic_session_test.cc +++ b/net/quic/quic_session_test.cc
@@ -147,8 +147,8 @@ return QuicSession::IsClosedStream(id); } - ReliableQuicStream* GetIncomingDynamicStream(QuicStreamId stream_id) { - return QuicSpdySession::GetIncomingDynamicStream(stream_id); + ReliableQuicStream* GetOrCreateDynamicStream(QuicStreamId stream_id) { + return QuicSpdySession::GetOrCreateDynamicStream(stream_id); } QuicConsumedData WritevData( @@ -245,7 +245,7 @@ QuicVersion version() const { return connection_->version(); } - MockHelper helper_; + MockConnectionHelper helper_; StrictMock<MockConnection>* connection_; TestSession session_; set<QuicStreamId> closed_streams_; @@ -280,12 +280,12 @@ } TEST_P(QuicSessionTestServer, AvailableStreams) { - ASSERT_TRUE(session_.GetIncomingDynamicStream(9) != nullptr); + ASSERT_TRUE(session_.GetOrCreateDynamicStream(9) != nullptr); // Both 5 and 7 should be available. EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 5)); EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 7)); - ASSERT_TRUE(session_.GetIncomingDynamicStream(7) != nullptr); - ASSERT_TRUE(session_.GetIncomingDynamicStream(5) != nullptr); + ASSERT_TRUE(session_.GetOrCreateDynamicStream(7) != nullptr); + ASSERT_TRUE(session_.GetOrCreateDynamicStream(5) != nullptr); } TEST_P(QuicSessionTestServer, IsClosedStreamLocallyCreated) { @@ -304,8 +304,8 @@ TEST_P(QuicSessionTestServer, IsClosedStreamPeerCreated) { QuicStreamId stream_id1 = kClientDataStreamId1; QuicStreamId stream_id2 = kClientDataStreamId2; - session_.GetIncomingDynamicStream(stream_id1); - session_.GetIncomingDynamicStream(stream_id2); + session_.GetOrCreateDynamicStream(stream_id1); + session_.GetOrCreateDynamicStream(stream_id2); CheckClosedStreams(); CloseStream(stream_id1); @@ -313,7 +313,7 @@ CloseStream(stream_id2); // Create a stream, and make another available. ReliableQuicStream* stream3 = - session_.GetIncomingDynamicStream(stream_id2 + 4); + session_.GetOrCreateDynamicStream(stream_id2 + 4); CheckClosedStreams(); // Close one, but make sure the other is still not closed CloseStream(stream3->id()); @@ -322,17 +322,17 @@ TEST_P(QuicSessionTestServer, MaximumAvailableOpenedStreams) { QuicStreamId stream_id = kClientDataStreamId1; - session_.GetIncomingDynamicStream(stream_id); + session_.GetOrCreateDynamicStream(stream_id); EXPECT_CALL(*connection_, SendConnectionClose(_)).Times(0); EXPECT_NE(nullptr, - session_.GetIncomingDynamicStream( + session_.GetOrCreateDynamicStream( stream_id + 2 * (session_.get_max_open_streams() - 1))); } TEST_P(QuicSessionTestServer, TooManyAvailableStreams) { QuicStreamId stream_id1 = kClientDataStreamId1; QuicStreamId stream_id2; - EXPECT_NE(nullptr, session_.GetIncomingDynamicStream(stream_id1)); + EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id1)); // A stream ID which is too large to create. if (FLAGS_allow_many_available_streams) { stream_id2 = stream_id1 + 2 * session_.get_max_available_streams() + 4; @@ -342,7 +342,7 @@ stream_id2 = stream_id1 + 2 * session_.get_max_open_streams(); EXPECT_CALL(*connection_, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS)); } - EXPECT_EQ(nullptr, session_.GetIncomingDynamicStream(stream_id2)); + EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(stream_id2)); } TEST_P(QuicSessionTestServer, ManyAvailableStreams) { @@ -351,10 +351,10 @@ QuicSessionPeer::SetMaxOpenStreams(&session_, 200); QuicStreamId stream_id = kClientDataStreamId1; // Create one stream. - session_.GetIncomingDynamicStream(stream_id); + session_.GetOrCreateDynamicStream(stream_id); EXPECT_CALL(*connection_, SendConnectionClose(_)).Times(0); // Create the largest stream ID of a threatened total of 200 streams. - session_.GetIncomingDynamicStream(stream_id + 2 * (200 - 1)); + session_.GetOrCreateDynamicStream(stream_id + 2 * (200 - 1)); } TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) { @@ -593,7 +593,7 @@ EXPECT_CALL(*connection_, SendRstStream(kTestStreamId, QUIC_STREAM_PEER_GOING_AWAY, 0)) .Times(0); - EXPECT_TRUE(session_.GetIncomingDynamicStream(kTestStreamId)); + EXPECT_TRUE(session_.GetOrCreateDynamicStream(kTestStreamId)); } TEST_P(QuicSessionTestServer, IncreasedTimeoutAfterCryptoHandshake) { @@ -612,7 +612,8 @@ EXPECT_EQ(1u, session_.GetNumOpenStreams()); EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, _, _)); - QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_STREAM_NO_ERROR, 0); + QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, + 0); session_.OnRstStream(rst1); EXPECT_EQ(0u, session_.GetNumOpenStreams()); // Connection should remain alive. @@ -1081,12 +1082,12 @@ ::testing::ValuesIn(QuicSupportedVersions())); TEST_P(QuicSessionTestClient, AvailableStreamsClient) { - ASSERT_TRUE(session_.GetIncomingDynamicStream(6) != nullptr); + ASSERT_TRUE(session_.GetOrCreateDynamicStream(6) != nullptr); // Both 2 and 4 should be available. EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 2)); EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 4)); - ASSERT_TRUE(session_.GetIncomingDynamicStream(2) != nullptr); - ASSERT_TRUE(session_.GetIncomingDynamicStream(4) != nullptr); + ASSERT_TRUE(session_.GetOrCreateDynamicStream(2) != nullptr); + ASSERT_TRUE(session_.GetOrCreateDynamicStream(4) != nullptr); // And 5 should be not available. EXPECT_FALSE(QuicSessionPeer::IsStreamAvailable(&session_, 5)); }
diff --git a/net/quic/quic_spdy_session.cc b/net/quic/quic_spdy_session.cc index 459a37e9..ca0e67f 100644 --- a/net/quic/quic_spdy_session.cc +++ b/net/quic/quic_spdy_session.cc
@@ -72,9 +72,13 @@ ack_notifier_delegate); } +void QuicSpdySession::OnHeadersHeadOfLineBlocking(QuicTime::Delta delta) { + // Implemented in Chromium for stats tracking. +} + QuicSpdyStream* QuicSpdySession::GetSpdyDataStream( const QuicStreamId stream_id) { - return static_cast<QuicSpdyStream*>(GetDynamicStream(stream_id)); + return static_cast<QuicSpdyStream*>(GetOrCreateDynamicStream(stream_id)); } } // namespace net
diff --git a/net/quic/quic_spdy_session.h b/net/quic/quic_spdy_session.h index 77ebe2e..6f7b4a0 100644 --- a/net/quic/quic_spdy_session.h +++ b/net/quic/quic_spdy_session.h
@@ -51,6 +51,10 @@ QuicHeadersStream* headers_stream() { return headers_stream_.get(); } + // Called when Head of Line Blocking happens in the headers stream. + // |delta| indicates how long that piece of data has been blocked. + virtual void OnHeadersHeadOfLineBlocking(QuicTime::Delta delta); + protected: // Override CreateIncomingDynamicStream() and CreateOutgoingDynamicStream() // with QuicSpdyStream return type to make sure that all data streams are
diff --git a/net/quic/quic_spdy_stream.cc b/net/quic/quic_spdy_stream.cc index 374405bc..746e96a8 100644 --- a/net/quic/quic_spdy_stream.cc +++ b/net/quic/quic_spdy_stream.cc
@@ -113,6 +113,19 @@ } } +void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) { + if (frame.error_code != QUIC_STREAM_NO_ERROR || + version() <= QUIC_VERSION_28) { + ReliableQuicStream::OnStreamReset(frame); + return; + } + DVLOG(1) << "Received QUIC_STREAM_NO_ERROR, not discarding response"; + set_rst_received(true); + MaybeIncreaseHighestReceivedOffset(frame.byte_offset); + set_stream_error(frame.error_code); + CloseWriteSide(); +} + void QuicSpdyStream::OnClose() { ReliableQuicStream::OnClose();
diff --git a/net/quic/quic_spdy_stream.h b/net/quic/quic_spdy_stream.h index 781b005..48e74b1 100644 --- a/net/quic/quic_spdy_stream.h +++ b/net/quic/quic_spdy_stream.h
@@ -78,6 +78,10 @@ // should be closed; no more data will be sent by the peer. virtual void OnStreamHeadersComplete(bool fin, size_t frame_len); + // Override the base class to not discard response when receiving + // QUIC_STREAM_NO_ERROR on QUIC_VERSION_29 and later versions. + void OnStreamReset(const QuicRstStreamFrame& frame) override; + // Writes the headers contained in |header_block| to the dedicated // headers stream. virtual size_t WriteHeaders(const SpdyHeaderBlock& header_block,
diff --git a/net/quic/quic_spdy_stream_test.cc b/net/quic/quic_spdy_stream_test.cc index da94274..75c5238 100644 --- a/net/quic/quic_spdy_stream_test.cc +++ b/net/quic/quic_spdy_stream_test.cc
@@ -58,7 +58,7 @@ string data_; }; -class QuicSpdyStreamTest : public ::testing::Test { +class QuicSpdyStreamTest : public ::testing::TestWithParam<QuicVersion> { public: QuicSpdyStreamTest() { headers_[":host"] = "www.google.com"; @@ -92,7 +92,7 @@ void Initialize(bool stream_should_process_data) { connection_ = new testing::StrictMock<MockConnection>( - &helper_, Perspective::IS_SERVER); + &helper_, Perspective::IS_SERVER, SupportedVersions(GetParam())); session_.reset(new testing::StrictMock<MockQuicSpdySession>(connection_)); stream_.reset(new TestStream(kClientDataStreamId1, session_.get(), stream_should_process_data)); @@ -103,7 +103,7 @@ } protected: - MockHelper helper_; + MockConnectionHelper helper_; MockConnection* connection_; scoped_ptr<MockQuicSpdySession> session_; scoped_ptr<TestStream> stream_; @@ -112,7 +112,11 @@ QuicWriteBlockedList* write_blocked_list_; }; -TEST_F(QuicSpdyStreamTest, ProcessHeaders) { +INSTANTIATE_TEST_CASE_P(Tests, + QuicSpdyStreamTest, + ::testing::ValuesIn(QuicSupportedVersions())); + +TEST_P(QuicSpdyStreamTest, ProcessHeaders) { Initialize(kShouldProcessData); string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); @@ -127,7 +131,7 @@ EXPECT_FALSE(stream_->IsDoneReading()); } -TEST_F(QuicSpdyStreamTest, ProcessHeadersWithFin) { +TEST_P(QuicSpdyStreamTest, ProcessHeadersWithFin) { Initialize(kShouldProcessData); string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); @@ -143,7 +147,7 @@ EXPECT_TRUE(stream_->HasFinalReceivedByteOffset()); } -TEST_F(QuicSpdyStreamTest, MarkHeadersConsumed) { +TEST_P(QuicSpdyStreamTest, MarkHeadersConsumed) { Initialize(kShouldProcessData); string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); @@ -161,7 +165,7 @@ EXPECT_EQ("", stream_->decompressed_headers()); } -TEST_F(QuicSpdyStreamTest, ProcessHeadersAndBody) { +TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBody) { Initialize(kShouldProcessData); string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); @@ -179,7 +183,7 @@ EXPECT_EQ(body, stream_->data()); } -TEST_F(QuicSpdyStreamTest, ProcessHeadersAndBodyFragments) { +TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyFragments) { string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); string body = "this is the body"; @@ -207,7 +211,7 @@ } } -TEST_F(QuicSpdyStreamTest, ProcessHeadersAndBodyFragmentsSplit) { +TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyFragmentsSplit) { string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); string body = "this is the body"; @@ -238,7 +242,7 @@ } } -TEST_F(QuicSpdyStreamTest, ProcessHeadersAndBodyReadv) { +TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyReadv) { Initialize(!kShouldProcessData); string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); @@ -261,7 +265,7 @@ EXPECT_EQ(body, string(buffer, bytes_read)); } -TEST_F(QuicSpdyStreamTest, ProcessHeadersAndBodyMarkConsumed) { +TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyMarkConsumed) { Initialize(!kShouldProcessData); string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); @@ -283,7 +287,7 @@ EXPECT_EQ(body.length(), stream_->flow_controller()->bytes_consumed()); } -TEST_F(QuicSpdyStreamTest, ProcessHeadersAndBodyIncrementalReadv) { +TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyIncrementalReadv) { Initialize(!kShouldProcessData); string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); @@ -306,7 +310,7 @@ } } -TEST_F(QuicSpdyStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) { +TEST_P(QuicSpdyStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) { Initialize(!kShouldProcessData); string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); @@ -333,7 +337,7 @@ } } -TEST_F(QuicSpdyStreamTest, StreamFlowControlBlocked) { +TEST_P(QuicSpdyStreamTest, StreamFlowControlBlocked) { // Tests that we send a BLOCKED frame to the peer when we attempt to write, // but are flow control blocked. Initialize(kShouldProcessData); @@ -364,7 +368,7 @@ EXPECT_EQ(kOverflow, ReliableQuicStreamPeer::SizeOfQueuedData(stream_.get())); } -TEST_F(QuicSpdyStreamTest, StreamFlowControlNoWindowUpdateIfNotConsumed) { +TEST_P(QuicSpdyStreamTest, StreamFlowControlNoWindowUpdateIfNotConsumed) { // The flow control receive window decreases whenever we add new bytes to the // sequencer, whether they are consumed immediately or buffered. However we // only send WINDOW_UPDATE frames based on increasing number of bytes @@ -408,7 +412,7 @@ QuicFlowControllerPeer::ReceiveWindowSize(stream_->flow_controller())); } -TEST_F(QuicSpdyStreamTest, StreamFlowControlWindowUpdate) { +TEST_P(QuicSpdyStreamTest, StreamFlowControlWindowUpdate) { // Tests that on receipt of data, the stream updates its receive window offset // appropriately, and sends WINDOW_UPDATE frames when its receive window drops // too low. @@ -452,7 +456,7 @@ stream_->flow_controller())); } -TEST_F(QuicSpdyStreamTest, ConnectionFlowControlWindowUpdate) { +TEST_P(QuicSpdyStreamTest, ConnectionFlowControlWindowUpdate) { // Tests that on receipt of data, the connection updates its receive window // offset appropriately, and sends WINDOW_UPDATE frames when its receive // window drops too low. @@ -505,7 +509,7 @@ stream_->OnStreamFrame(frame3); } -TEST_F(QuicSpdyStreamTest, StreamFlowControlViolation) { +TEST_P(QuicSpdyStreamTest, StreamFlowControlViolation) { // Tests that on if the peer sends too much data (i.e. violates the flow // control protocol), then we terminate the connection. @@ -531,7 +535,22 @@ stream_->OnStreamFrame(frame); } -TEST_F(QuicSpdyStreamTest, ConnectionFlowControlViolation) { +TEST_P(QuicSpdyStreamTest, TestHandlingQuicRstStreamNoError) { + Initialize(kShouldProcessData); + string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); + stream_->OnStreamHeaders(headers); + stream_->OnStreamHeadersComplete(false, headers.size()); + stream_->OnStreamReset( + QuicRstStreamFrame(stream_->id(), QUIC_STREAM_NO_ERROR, 0)); + EXPECT_TRUE(stream_->write_side_closed()); + if (GetParam() > QUIC_VERSION_28) { + EXPECT_FALSE(stream_->reading_stopped()); + } else { + EXPECT_TRUE(stream_->reading_stopped()); + } +} + +TEST_P(QuicSpdyStreamTest, ConnectionFlowControlViolation) { // Tests that on if the peer sends too much data (i.e. violates the flow // control protocol), at the connection level (rather than the stream level) // then we terminate the connection. @@ -563,7 +582,7 @@ stream_->OnStreamFrame(frame); } -TEST_F(QuicSpdyStreamTest, StreamFlowControlFinNotBlocked) { +TEST_P(QuicSpdyStreamTest, StreamFlowControlFinNotBlocked) { // An attempt to write a FIN with no data should not be flow control blocked, // even if the send window is 0.
diff --git a/net/quic/quic_stream_sequencer_buffer_interface.h b/net/quic/quic_stream_sequencer_buffer_interface.h index e03ea79..22b4ed81 100644 --- a/net/quic/quic_stream_sequencer_buffer_interface.h +++ b/net/quic/quic_stream_sequencer_buffer_interface.h
@@ -5,7 +5,6 @@ #ifndef NET_QUIC_QUIC_STREAM_SEQUENCER_BUFFER_INTERFACE_H_ #define NET_QUIC_QUIC_STREAM_SEQUENCER_BUFFER_INTERFACE_H_ -#include "net/quic/quic_frame_list.h" #include "net/quic/quic_protocol.h" using base::StringPiece;
diff --git a/net/quic/quic_stream_sequencer_test.cc b/net/quic/quic_stream_sequencer_test.cc index 6c2910e..aaf1d26 100644 --- a/net/quic/quic_stream_sequencer_test.cc +++ b/net/quic/quic_stream_sequencer_test.cc
@@ -147,7 +147,7 @@ return QuicStreamSequencerPeer::GetNumBufferedBytes(sequencer_.get()); } - MockHelper helper_; + MockConnectionHelper helper_; MockConnection* connection_; MockClock clock_; MockQuicSpdySession session_;
diff --git a/net/quic/quic_time.cc b/net/quic/quic_time.cc index cd59953..83217180 100644 --- a/net/quic/quic_time.cc +++ b/net/quic/quic_time.cc
@@ -11,51 +11,55 @@ namespace net { uint64 QuicWallTime::ToUNIXSeconds() const { - return seconds_; + return microseconds_ / 1000000; +} + +uint64 QuicWallTime::ToUNIXMicroseconds() const { + return microseconds_; } bool QuicWallTime::IsAfter(QuicWallTime other) const { - return seconds_ > other.seconds_; + return microseconds_ > other.microseconds_; } bool QuicWallTime::IsBefore(QuicWallTime other) const { - return seconds_ < other.seconds_; + return microseconds_ < other.microseconds_; } bool QuicWallTime::IsZero() const { - return seconds_ == 0; + return microseconds_ == 0; } QuicTime::Delta QuicWallTime::AbsoluteDifference(QuicWallTime other) const { uint64 d; - if (seconds_ > other.seconds_) { - d = seconds_ - other.seconds_; + if (microseconds_ > other.microseconds_) { + d = microseconds_ - other.microseconds_; } else { - d = other.seconds_ - seconds_; + d = other.microseconds_ - microseconds_; } if (d > static_cast<uint64>(kint64max)) { d = kint64max; } - return QuicTime::Delta::FromSeconds(d); + return QuicTime::Delta::FromMicroseconds(d); } QuicWallTime QuicWallTime::Add(QuicTime::Delta delta) const { - uint64 seconds = seconds_ + delta.ToSeconds(); - if (seconds < seconds_) { - seconds = kuint64max; + uint64 microseconds = microseconds_ + delta.ToMicroseconds(); + if (microseconds < microseconds_) { + microseconds = kuint64max; } - return QuicWallTime(seconds); + return QuicWallTime(microseconds); } // TODO(ianswett) Test this. QuicWallTime QuicWallTime::Subtract(QuicTime::Delta delta) const { - uint64 seconds = seconds_ - delta.ToSeconds(); - if (seconds > seconds_) { - seconds = 0; + uint64 microseconds = microseconds_ - delta.ToMicroseconds(); + if (microseconds > microseconds_) { + microseconds = 0; } - return QuicWallTime(seconds); + return QuicWallTime(microseconds); } } // namespace net
diff --git a/net/quic/quic_time.h b/net/quic/quic_time.h index 99b3afd5..5637837d 100644 --- a/net/quic/quic_time.h +++ b/net/quic/quic_time.h
@@ -159,24 +159,30 @@ int64 time_; }; -// A QuicWallTime represents an absolute time that is globally consistent. It -// provides, at most, one second granularity and, in practice, clock-skew means -// that you shouldn't even depend on that. +// A QuicWallTime represents an absolute time that is globally consistent. In +// practice, clock-skew means that comparing values from different machines +// requires some flexibility in interpretation. class NET_EXPORT_PRIVATE QuicWallTime { public: // FromUNIXSeconds constructs a QuicWallTime from a count of the seconds // since the UNIX epoch. static QUICTIME_CONSTEXPR QuicWallTime FromUNIXSeconds(uint64 seconds) { - return QuicWallTime(seconds); + return QuicWallTime(seconds * 1000000); + } + + static QUICTIME_CONSTEXPR QuicWallTime + FromUNIXMicroseconds(uint64 microseconds) { + return QuicWallTime(microseconds); } // Zero returns a QuicWallTime set to zero. IsZero will return true for this // value. static QUICTIME_CONSTEXPR QuicWallTime Zero() { return QuicWallTime(0); } - // ToUNIXSeconds converts a QuicWallTime into a count of seconds since the - // UNIX epoch. + // Returns the number of seconds since the UNIX epoch. uint64 ToUNIXSeconds() const; + // Returns the number of microseconds since the UNIX epoch. + uint64 ToUNIXMicroseconds() const; bool IsAfter(QuicWallTime other) const; bool IsBefore(QuicWallTime other) const; @@ -197,10 +203,10 @@ QuicWallTime Subtract(QuicTime::Delta delta) const WARN_UNUSED_RESULT; private: - explicit QUICTIME_CONSTEXPR QuicWallTime(uint64 seconds) - : seconds_(seconds) {} + explicit QUICTIME_CONSTEXPR QuicWallTime(uint64 microseconds) + : microseconds_(microseconds) {} - uint64 seconds_; + uint64 microseconds_; }; // Non-member relational operators for QuicTime::Delta.
diff --git a/net/quic/quic_utils.cc b/net/quic/quic_utils.cc index b336202..b821633 100644 --- a/net/quic/quic_utils.cc +++ b/net/quic/quic_utils.cc
@@ -179,7 +179,6 @@ RETURN_STRING_LITERAL(QUIC_DECRYPTION_FAILURE); RETURN_STRING_LITERAL(QUIC_ENCRYPTION_FAILURE); RETURN_STRING_LITERAL(QUIC_PACKET_TOO_LARGE); - RETURN_STRING_LITERAL(QUIC_PACKET_FOR_NONEXISTENT_STREAM); RETURN_STRING_LITERAL(QUIC_PEER_GOING_AWAY); RETURN_STRING_LITERAL(QUIC_HANDSHAKE_FAILED); RETURN_STRING_LITERAL(QUIC_CRYPTO_TAGS_OUT_OF_ORDER);
diff --git a/net/quic/reliable_quic_stream.h b/net/quic/reliable_quic_stream.h index 1c696af..a608c32 100644 --- a/net/quic/reliable_quic_stream.h +++ b/net/quic/reliable_quic_stream.h
@@ -114,6 +114,9 @@ void set_fec_policy(FecPolicy fec_policy) { fec_policy_ = fec_policy; } FecPolicy fec_policy() const { return fec_policy_; } + void set_rst_received(bool rst_received) { rst_received_ = rst_received; } + void set_stream_error(QuicRstStreamErrorCode error) { stream_error_ = error; } + // Adjust the flow control window according to new offset in |frame|. virtual void OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame);
diff --git a/net/quic/reliable_quic_stream_test.cc b/net/quic/reliable_quic_stream_test.cc index 8fe2be6..46a3fff5 100644 --- a/net/quic/reliable_quic_stream_test.cc +++ b/net/quic/reliable_quic_stream_test.cc
@@ -141,7 +141,7 @@ } protected: - MockHelper helper_; + MockConnectionHelper helper_; MockConnection* connection_; scoped_ptr<MockQuicSpdySession> session_; TestStream* stream_;
diff --git a/net/quic/stream_sequencer_buffer.cc b/net/quic/stream_sequencer_buffer.cc new file mode 100644 index 0000000..9e723f9 --- /dev/null +++ b/net/quic/stream_sequencer_buffer.cc
@@ -0,0 +1,453 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/quic/stream_sequencer_buffer.h" + +#include "base/basictypes.h" +#include "base/logging.h" + +using std::min; + +namespace net { + +StreamSequencerBuffer::Gap::Gap(QuicStreamOffset begin_offset, + QuicStreamOffset end_offset) + : begin_offset(begin_offset), end_offset(end_offset) {} + +StreamSequencerBuffer::FrameInfo::FrameInfo() + : length(1), timestamp(QuicTime::Zero()) {} + +StreamSequencerBuffer::FrameInfo::FrameInfo(size_t length, QuicTime timestamp) + : length(length), timestamp(timestamp) {} + +StreamSequencerBuffer::StreamSequencerBuffer(size_t max_capacity_bytes) + : max_buffer_capacity_bytes_(max_capacity_bytes), + blocks_count_( + ceil(static_cast<double>(max_capacity_bytes) / kBlockSizeBytes)), + total_bytes_read_(0), + blocks_(blocks_count_) { + Clear(); +} + +StreamSequencerBuffer::~StreamSequencerBuffer() { + Clear(); +} + +void StreamSequencerBuffer::Clear() { + for (size_t i = 0; i < blocks_count_; ++i) { + if (blocks_[i] != nullptr) { + RetireBlock(i); + } + } + num_bytes_buffered_ = 0; + // Reset gaps_ so that buffer is in a state as if all data before + // total_bytes_read_ has been consumed, and those after total_bytes_read_ + // has never arrived. + gaps_ = std::list<Gap>( + 1, Gap(total_bytes_read_, std::numeric_limits<QuicStreamOffset>::max())), + frame_arrival_time_map_.clear(); +} + +void StreamSequencerBuffer::RetireBlock(size_t idx) { + DCHECK(blocks_[idx] != nullptr); + delete blocks_[idx]; + blocks_[idx] = nullptr; + DVLOG(1) << "Retired block" << idx; +} + +QuicErrorCode StreamSequencerBuffer::OnStreamData( + QuicStreamOffset starting_offset, + base::StringPiece data, + QuicTime timestamp, + size_t* const bytes_buffered) { + *bytes_buffered = 0; + QuicStreamOffset offset = starting_offset; + size_t size = data.size(); + if (size == 0) { + LOG(DFATAL) << "Attempted to write 0 bytes of data."; + return QUIC_INVALID_STREAM_FRAME; + } + + // Find the first gap not ending before |offset|. This gap maybe the gap to + // fill if the arriving frame doesn't overlaps with previous ones. + std::list<Gap>::iterator current_gap = gaps_.begin(); + while (current_gap != gaps_.end() && current_gap->end_offset <= offset) { + ++current_gap; + } + + DCHECK(current_gap != gaps_.end()); + + // "duplication": might duplicate with data alread filled,but also might + // overlap across different base::StringPiece objects already written. + // In both cases, don't write the data, + // and allow the caller of this method to handle the result. + if (offset < current_gap->begin_offset && + offset + size <= current_gap->begin_offset) { + DVLOG(1) << "duplicated data at offset:" << offset << " len: " << size; + return QUIC_NO_ERROR; + } + if (offset < current_gap->begin_offset && + offset + size > current_gap->begin_offset) { + // Beginning of new data overlaps data before current gap. + return QUIC_INVALID_STREAM_DATA; + } + if (offset + size > current_gap->end_offset) { + // End of new data overlaps with data after current gap. + return QUIC_INVALID_STREAM_DATA; + } + + // Write beyond the current range this buffer is covering. + if (offset + size > total_bytes_read_ + max_buffer_capacity_bytes_) { + return QUIC_INTERNAL_ERROR; + } + + size_t total_written = 0; + size_t source_remaining = size; + const char* source = data.data(); + // Write data block by block. If corresponding block has not created yet, + // create it first. + // Stop when all data are written or reaches the logical end of the buffer. + while (source_remaining > 0) { + const size_t write_block_num = GetBlockIndex(offset); + const size_t write_block_offset = GetInBlockOffset(offset); + DCHECK_GT(blocks_count_, write_block_num); + + size_t block_capacity = GetBlockCapacity(write_block_num); + size_t bytes_avail = block_capacity - write_block_offset; + + // If this write meets the upper boundary of the buffer, + // reduce the available free bytes. + if (offset + bytes_avail > total_bytes_read_ + max_buffer_capacity_bytes_) { + bytes_avail = total_bytes_read_ + max_buffer_capacity_bytes_ - offset; + } + + if (blocks_[write_block_num] == nullptr) { + // TODO(danzh): Investigate if using a freelist would improve performance. + // Same as RetireBlock(). + blocks_[write_block_num] = new BufferBlock(); + } + + const size_t bytes_to_copy = min<size_t>(bytes_avail, source_remaining); + char* dest = blocks_[write_block_num]->buffer + write_block_offset; + DVLOG(1) << "write at offset: " << offset << " len: " << bytes_to_copy; + memcpy(dest, source, bytes_to_copy); + source += bytes_to_copy; + source_remaining -= bytes_to_copy; + offset += bytes_to_copy; + total_written += bytes_to_copy; + } + + DCHECK_GT(total_written, 0u); + *bytes_buffered = total_written; + UpdateGapList(current_gap, starting_offset, total_written); + + frame_arrival_time_map_.insert( + std::make_pair(starting_offset, FrameInfo(size, timestamp))); + num_bytes_buffered_ += total_written; + return QUIC_NO_ERROR; +} + +inline void StreamSequencerBuffer::UpdateGapList( + std::list<Gap>::iterator gap_with_new_data_written, + QuicStreamOffset start_offset, + size_t bytes_written) { + if (gap_with_new_data_written->begin_offset == start_offset && + gap_with_new_data_written->end_offset > start_offset + bytes_written) { + // New data has been written into the left part of the buffer. + gap_with_new_data_written->begin_offset = start_offset + bytes_written; + } else if (gap_with_new_data_written->begin_offset < start_offset && + gap_with_new_data_written->end_offset == + start_offset + bytes_written) { + // New data has been written into the right part of the buffer. + gap_with_new_data_written->end_offset = start_offset; + } else if (gap_with_new_data_written->begin_offset < start_offset && + gap_with_new_data_written->end_offset > + start_offset + bytes_written) { + // New data has been written into the middle of the buffer. + auto current = gap_with_new_data_written++; + size_t current_end = current->end_offset; + current->end_offset = start_offset; + gaps_.insert(gap_with_new_data_written, + Gap(start_offset + bytes_written, current_end)); + } else if (gap_with_new_data_written->begin_offset == start_offset && + gap_with_new_data_written->end_offset == + start_offset + bytes_written) { + // This gap has been filled with new data. So it's no longer a gap. + gaps_.erase(gap_with_new_data_written); + } +} + +size_t StreamSequencerBuffer::Readv(const iovec* dest_iov, size_t dest_count) { + size_t bytes_read = 0; + for (size_t i = 0; i < dest_count && ReadableBytes() > 0; ++i) { + char* dest = reinterpret_cast<char*>(dest_iov[i].iov_base); + size_t dest_remaining = dest_iov[i].iov_len; + while (dest_remaining > 0 && ReadableBytes() > 0) { + size_t block_idx = NextBlockToRead(); + size_t start_offset_in_block = ReadOffset(); + size_t block_capacity = GetBlockCapacity(block_idx); + size_t bytes_available_in_block = + min<size_t>(ReadableBytes(), block_capacity - start_offset_in_block); + size_t bytes_to_copy = + min<size_t>(bytes_available_in_block, dest_remaining); + DCHECK_GT(bytes_to_copy, 0u); + DCHECK_NE(static_cast<BufferBlock*>(nullptr), blocks_[block_idx]); + memcpy(dest, blocks_[block_idx]->buffer + start_offset_in_block, + bytes_to_copy); + dest += bytes_to_copy; + dest_remaining -= bytes_to_copy; + num_bytes_buffered_ -= bytes_to_copy; + total_bytes_read_ += bytes_to_copy; + bytes_read += bytes_to_copy; + + // Retire the block if all the data is read out + // and no other data is stored in this block. + if (bytes_to_copy == bytes_available_in_block) { + RetireBlockIfEmpty(block_idx); + } + } + } + + if (bytes_read > 0) { + UpdateFrameArrivalMap(total_bytes_read_); + } + return bytes_read; +} + +int StreamSequencerBuffer::GetReadableRegions(struct iovec* iov, + int iov_count) const { + DCHECK(iov != nullptr); + DCHECK_GT(iov_count, 0); + + if (ReadableBytes() == 0) { + iov[0].iov_base = nullptr; + iov[0].iov_len = 0; + return 0; + } + + size_t start_block_idx = NextBlockToRead(); + QuicStreamOffset readable_offset_end = gaps_.front().begin_offset - 1; + DCHECK_GE(readable_offset_end + 1, total_bytes_read_); + size_t end_block_offset = GetInBlockOffset(readable_offset_end); + size_t end_block_idx = GetBlockIndex(readable_offset_end); + + // If readable region is within one block, deal with it seperately. + if (start_block_idx == end_block_idx && ReadOffset() <= end_block_offset) { + iov[0].iov_base = blocks_[start_block_idx]->buffer + ReadOffset(); + iov[0].iov_len = ReadableBytes(); + DVLOG(1) << "get only block" << start_block_idx; + return 1; + } + + // Get first block + iov[0].iov_base = blocks_[start_block_idx]->buffer + ReadOffset(); + iov[0].iov_len = GetBlockCapacity(start_block_idx) - ReadOffset(); + DVLOG(1) << "get first block" << start_block_idx << " with len " + << iov[0].iov_len; + DCHECK_GT(readable_offset_end + 1, total_bytes_read_ + iov[0].iov_len) + << "there should be more available data"; + + // Get readable regions of the rest blocks till either 2nd to last block + // before gap is met or |iov| is filled. For these blocks, one whole block is + // a region. + int iov_used = 1; + size_t block_idx = (start_block_idx + iov_used) % blocks_count_; + while (block_idx != end_block_idx && iov_used < iov_count) { + DCHECK_NE(static_cast<BufferBlock*>(nullptr), blocks_[block_idx]); + iov[iov_used].iov_base = blocks_[block_idx]->buffer; + iov[iov_used].iov_len = GetBlockCapacity(block_idx); + DVLOG(1) << "get block" << block_idx; + ++iov_used; + block_idx = (start_block_idx + iov_used) % blocks_count_; + } + + // Deal with last block if |iov| can hold more. + if (iov_used < iov_count) { + DCHECK_NE(static_cast<BufferBlock*>(nullptr), blocks_[block_idx]); + iov[iov_used].iov_base = blocks_[end_block_idx]->buffer; + iov[iov_used].iov_len = end_block_offset + 1; + DVLOG(1) << "get last block " << end_block_idx; + ++iov_used; + } + return iov_used; +} + +bool StreamSequencerBuffer::GetReadableRegion(iovec* iov, + QuicTime* timestamp) const { + if (ReadableBytes() == 0) { + iov[0].iov_base = nullptr; + iov[0].iov_len = 0; + return false; + } + + size_t start_block_idx = NextBlockToRead(); + iov->iov_base = blocks_[start_block_idx]->buffer + ReadOffset(); + size_t readable_bytes_in_block = min<size_t>( + GetBlockCapacity(start_block_idx) - ReadOffset(), ReadableBytes()); + size_t region_len = 0; + auto iter = frame_arrival_time_map_.begin(); + *timestamp = iter->second.timestamp; + DVLOG(1) << "readable bytes in block: " << readable_bytes_in_block; + for (; iter != frame_arrival_time_map_.end() && + region_len + iter->second.length <= readable_bytes_in_block; + ++iter) { + if (iter->second.timestamp != *timestamp) { + // If reaches a frame arrive at another timestamp, stop expanding current + // region. + DVLOG(1) << "Meet frame with different timestamp."; + break; + } + region_len += iter->second.length; + DVLOG(1) << "Add bytes to region: " << iter->second.length; + } + if (iter == frame_arrival_time_map_.end() || + iter->second.timestamp == *timestamp) { + // If encountered the end of readable bytes before reaching a different + // timestamp. + DVLOG(1) << "Get all readable bytes in first block."; + region_len = readable_bytes_in_block; + } + iov->iov_len = region_len; + return true; +} + +bool StreamSequencerBuffer::MarkConsumed(size_t bytes_used) { + if (bytes_used > ReadableBytes()) { + return false; + } + size_t bytes_to_consume = bytes_used; + while (bytes_to_consume > 0) { + size_t block_idx = NextBlockToRead(); + size_t offset_in_block = ReadOffset(); + size_t bytes_available = min<size_t>( + ReadableBytes(), GetBlockCapacity(block_idx) - offset_in_block); + size_t bytes_read = min<size_t>(bytes_to_consume, bytes_available); + total_bytes_read_ += bytes_read; + num_bytes_buffered_ -= bytes_read; + bytes_to_consume -= bytes_read; + // If advanced to the end of current block and end of buffer hasn't wrapped + // to this block yet. + if (bytes_available == bytes_read) { + RetireBlockIfEmpty(block_idx); + } + } + if (bytes_used > 0) { + UpdateFrameArrivalMap(total_bytes_read_); + } + return true; +} + +size_t StreamSequencerBuffer::FlushBufferedFrames() { + size_t prev_total_bytes_read = total_bytes_read_; + total_bytes_read_ = gaps_.back().begin_offset; + Clear(); + return total_bytes_read_ - prev_total_bytes_read; +} + +size_t StreamSequencerBuffer::ReadableBytes() const { + return gaps_.front().begin_offset - total_bytes_read_; +} + +bool StreamSequencerBuffer::HasBytesToRead() const { + return ReadableBytes() > 0; +} + +QuicStreamOffset StreamSequencerBuffer::BytesConsumed() const { + return total_bytes_read_; +} + +size_t StreamSequencerBuffer::BytesBuffered() const { + return num_bytes_buffered_; +} + +size_t StreamSequencerBuffer::GetBlockIndex(QuicStreamOffset offset) const { + return (offset % max_buffer_capacity_bytes_) / kBlockSizeBytes; +} + +size_t StreamSequencerBuffer::GetInBlockOffset(QuicStreamOffset offset) const { + return (offset % max_buffer_capacity_bytes_) % kBlockSizeBytes; +} + +size_t StreamSequencerBuffer::ReadOffset() const { + return GetInBlockOffset(total_bytes_read_); +} + +size_t StreamSequencerBuffer::NextBlockToRead() const { + return GetBlockIndex(total_bytes_read_); +} + +void StreamSequencerBuffer::RetireBlockIfEmpty(size_t block_index) { + DCHECK(ReadableBytes() == 0 || GetInBlockOffset(total_bytes_read_) == 0) + << "RetireBlockIfEmpty() should only be called when advancing to next " + "block" + " or a gap has been reached."; + // If the whole buffer becomes empty, the last piece of data has been read. + if (Empty()) { + RetireBlock(block_index); + return; + } + + // Check where the logical end of this buffer is. + // Not empty if the end of circular buffer has been wrapped to this block. + if (GetBlockIndex(gaps_.back().begin_offset - 1) == block_index) { + return; + } + + // Read index remains in this block, which means a gap has been reached. + if (NextBlockToRead() == block_index) { + Gap first_gap = gaps_.front(); + DCHECK(first_gap.begin_offset == total_bytes_read_); + // Check where the next piece data is. + // Not empty if next piece of data is still in this chunk. + bool gap_extends_to_infinity = + (first_gap.end_offset != std::numeric_limits<QuicStreamOffset>::max()); + bool gap_ends_in_this_block = + (GetBlockIndex(first_gap.end_offset) == block_index); + if (gap_extends_to_infinity || gap_ends_in_this_block) { + return; + } + } + RetireBlock(block_index); +} + +bool StreamSequencerBuffer::Empty() const { + return gaps_.size() == 1 && gaps_.front().begin_offset == total_bytes_read_; +} + +size_t StreamSequencerBuffer::GetBlockCapacity(size_t block_index) const { + if ((block_index + 1) == blocks_count_) { + size_t result = max_buffer_capacity_bytes_ % kBlockSizeBytes; + if (result == 0) { // whole block + result = kBlockSizeBytes; + } + return result; + } else { + return kBlockSizeBytes; + } +} + +void StreamSequencerBuffer::UpdateFrameArrivalMap(QuicStreamOffset offset) { + // Get the frame before which all frames should be removed. + auto next_frame = frame_arrival_time_map_.upper_bound(offset); + DCHECK(next_frame != frame_arrival_time_map_.begin()); + auto iter = frame_arrival_time_map_.begin(); + while (iter != next_frame) { + auto erased = *iter; + iter = frame_arrival_time_map_.erase(iter); + DVLOG(1) << "remove FrameInfo with offsest: " << erased.first + << " len: " << erased.second.length; + if (erased.first + erased.second.length > offset) { + // If last frame is partially read out, update this FrameInfo and insert + // it back. + auto updated = std::make_pair( + offset, FrameInfo(erased.first + erased.second.length - offset, + erased.second.timestamp)); + DVLOG(1) << "insert back FrameInfo with offset: " << updated.first + << " len: " << updated.second.length; + frame_arrival_time_map_.insert(updated); + } + } +} + +} // namespace net
diff --git a/net/quic/stream_sequencer_buffer.h b/net/quic/stream_sequencer_buffer.h new file mode 100644 index 0000000..07df630 --- /dev/null +++ b/net/quic/stream_sequencer_buffer.h
@@ -0,0 +1,201 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_QUIC_STREAM_SEQUENCER_BUFFER_H_ +#define NET_QUIC_STREAM_SEQUENCER_BUFFER_H_ + +// StreamSequencerBuffer implements QuicStreamSequencerBufferInterface. +// It is a circular stream buffer with random write and +// in-sequence read. It consists of an std::vector of pointers pointing +// to memory blocks created as needed and a std::list of Gaps to indicate +// the missing data between the data already written into the buffer. +// - Data are written in with offset indicating where it should be in the +// stream, and the buffer grown as needed (up to the maximum buffer capacity), +// without expensive copying (extra blocks are allocated). +// - Data can be read from the buffer if there is no gap before it, +// and the buffer shrinks as the data are consumed. +// - An upper limit on the number of blocks in the buffer provides an upper +// bound on memory use. +// +// This class is thread-unsafe. +// +// StreamSequencerBuffer maintains a concept of the readable region, which +// contains all written data that has not been read. +// It promises stability of the underlying memory addresses in the readable +// region, so pointers into it can be maintained, and the offset of a pointer +// from the start of the read region can be calculated. +// +// Expected Use: +// StreamSequencerBuffer buffer(2.5 * 8 * 1024); +// std::string source(1024, 'a'); +// base::StringPiece std::string_piece(source.data(), source.size()); +// size_t written = 0; +// buffer.OnStreamData(800, std::string_piece, GetEpollClockNow(), &written); +// source = std::string{800, 'b'}; +// base::StringPiece std::string_piece1(source.data(), 800); +// // Try to write to [1, 801), but should fail due to overlapping, +// // res should be QUIC_INVALID_STREAM_DATA +// auto res = buffer.OnStreamData(1, std::string_piece1, &written)); +// // write to [0, 800), res should be QUIC_NO_ERROR +// auto res = buffer.OnStreamData(0, std::string_piece1, GetEpollClockNow(), +// &written); +// +// // Read into a iovec array with total capacity of 120 bytes. +// char dest[120]; +// iovec iovecs[3]{iovec{dest, 40}, iovec{dest + 40, 40}, +// iovec{dest + 80, 40}}; +// size_t read = buffer.Readv(iovecs, 3); +// +// // Get single readable region with timestamp. +// QuicTime t; +// iovec iov; +// buffer.GetReadableRegion(iov, &t); +// +// // Get readable regions from [256, 1024) and consume some of it. +// iovec iovs[2]; +// int iov_count = buffer.GetReadableRegions(iovs, 2); +// // Consume some bytes in iovs, returning number of bytes having been +// consumed. +// size_t consumed = consume_iovs(iovs, iov_count); +// buffer.MarkConsumed(consumed); + +#include <functional> +#include <list> +#include <memory> + +#include "base/macros.h" +#include "net/quic/quic_protocol.h" +#include "net/quic/quic_stream_sequencer_buffer_interface.h" + +namespace net { + +namespace test { +class StreamSequencerBufferPeer; +} // namespace test + +class NET_EXPORT_PRIVATE StreamSequencerBuffer + : public QuicStreamSequencerBufferInterface { + public: + // A Gap indicates a missing chunk of bytes between + // [begin_offset, end_offset) in the stream + struct Gap { + Gap(QuicStreamOffset begin_offset, QuicStreamOffset end_offset); + QuicStreamOffset begin_offset; + QuicStreamOffset end_offset; + }; + + // A FrameInfo stores the length of a frame and the time it arrived. + struct NET_EXPORT_PRIVATE FrameInfo { + FrameInfo(); + FrameInfo(size_t length, QuicTime timestamp); + + size_t length; + QuicTime timestamp; + }; + + // Size of blocks used by this buffer. + // Choose 8K to make block large enough to hold multiple frames, each of + // which could be up to 1.5 KB. + static const size_t kBlockSizeBytes = 8 * 1024; // 8KB + + // The basic storage block used by this buffer. + struct BufferBlock { + char buffer[kBlockSizeBytes]; + }; + + explicit StreamSequencerBuffer(size_t max_capacity_bytes); + + ~StreamSequencerBuffer() override; + + // QuicStreamSequencerBufferInterface implementation. + void Clear() override; + bool Empty() const override; + QuicErrorCode OnStreamData(QuicStreamOffset offset, + base::StringPiece data, + QuicTime timestamp, + size_t* bytes_buffered) override; + size_t Readv(const struct iovec* dest_iov, size_t dest_count) override; + int GetReadableRegions(struct iovec* iov, int iov_len) const override; + bool GetReadableRegion(iovec* iov, QuicTime* timestamp) const override; + bool MarkConsumed(size_t bytes_buffered) override; + size_t FlushBufferedFrames() override; + bool HasBytesToRead() const override; + QuicStreamOffset BytesConsumed() const override; + size_t BytesBuffered() const override; + + private: + friend class test::StreamSequencerBufferPeer; + + // Dispose the given buffer block. + // After calling this method, blocks_[index] is set to nullptr + // in order to indicate that no memory set is allocated for that block. + void RetireBlock(size_t index); + + // Should only be called after the indexed block is read till the end of the + // block or a gap has been reached. + // If the block at |block_index| contains no buffered data, then the block is + // retired. + void RetireBlockIfEmpty(size_t block_index); + + // Called within OnStreamData() to update the gap OnStreamData() writes into + // (remove, split or change begin/end offset). + void UpdateGapList(std::list<Gap>::iterator gap_with_new_data_written, + QuicStreamOffset start_offset, + size_t bytes_written); + + // Calculate the capacity of block at specified index. + // Return value should be either kBlockSizeBytes for non-trailing blocks and + // max_buffer_capacity % kBlockSizeBytes for trailing block. + size_t GetBlockCapacity(size_t index) const; + + // Does not check if offset is within reasonable range. + size_t GetBlockIndex(QuicStreamOffset offset) const; + + // Given an offset in the stream, return the offset from the beginning of the + // block which contains this data. + size_t GetInBlockOffset(QuicStreamOffset offset) const; + + // Get offset relative to index 0 in logical 1st block to start next read. + size_t ReadOffset() const; + + // Get the index of the logical 1st block to start next read. + size_t NextBlockToRead() const; + + // Returns number of bytes available to be read out. + size_t ReadableBytes() const; + + // Called after Readv() and MarkConsumed() to keep frame_arrival_time_map_ + // up to date. + // |offset| is the byte next read should start from. All frames before it + // should be removed from the map. + void UpdateFrameArrivalMap(QuicStreamOffset offset); + + // The maximum total capacity of this buffer in byte, as constructed. + const size_t max_buffer_capacity_bytes_; + + // How many blocks this buffer would need when it reaches full capacity. + const size_t blocks_count_; + + // Number of bytes read out of buffer. + QuicStreamOffset total_bytes_read_; + + // Contains Gaps which represents currently missing data. + std::list<Gap> gaps_; + + // An ordered, variable-length std::list of blocks, with the length limited + // such that the number of blocks never exceeds blocks_count_. + // Each std::list entry can hold up to kBlockSizeBytes bytes. + std::vector<BufferBlock*> blocks_; + + // Number of bytes in buffer. + size_t num_bytes_buffered_; + + // Stores all the buffered frames' start offset, length and arrival time. + std::map<QuicStreamOffset, FrameInfo> frame_arrival_time_map_; + + DISALLOW_COPY_AND_ASSIGN(StreamSequencerBuffer); +}; +} // namespace net + +#endif // NET_QUIC_STREAM_SEQUENCER_BUFFER_H_
diff --git a/net/quic/stream_sequencer_buffer_test.cc b/net/quic/stream_sequencer_buffer_test.cc new file mode 100644 index 0000000..c85de86 --- /dev/null +++ b/net/quic/stream_sequencer_buffer_test.cc
@@ -0,0 +1,981 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/quic/stream_sequencer_buffer.h" + +#include "base/logging.h" +#include "base/macros.h" +#include "base/rand_util.h" +#include "net/quic/test_tools/mock_clock.h" +#include "net/quic/test_tools/quic_test_utils.h" +#include "net/test/gtest_util.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gmock_mutant.h" +#include "testing/gtest/include/gtest/gtest.h" + +using std::min; + +namespace net { + +namespace test { + +char GetCharFromIOVecs(size_t offset, iovec iov[], size_t count) { + size_t start_offset = 0; + for (size_t i = 0; i < count; i++) { + if (iov[i].iov_len == 0) { + continue; + } + size_t end_offset = start_offset + iov[i].iov_len - 1; + if (offset >= start_offset && offset <= end_offset) { + const char* buf = reinterpret_cast<const char*>(iov[i].iov_base); + return buf[offset - start_offset]; + } + start_offset += iov[i].iov_len; + } + LOG(ERROR) << "Could not locate char at offset " << offset << " in " << count + << " iovecs"; + for (size_t i = 0; i < count; ++i) { + LOG(ERROR) << " iov[" << i << "].iov_len = " << iov[i].iov_len; + } + return '\0'; +} + +static const size_t kBlockSizeBytes = StreamSequencerBuffer::kBlockSizeBytes; +typedef StreamSequencerBuffer::BufferBlock BufferBlock; +typedef StreamSequencerBuffer::Gap Gap; +typedef StreamSequencerBuffer::FrameInfo FrameInfo; + +class StreamSequencerBufferPeer { + public: + explicit StreamSequencerBufferPeer(StreamSequencerBuffer* buffer) + : buffer_(buffer) {} + + // Read from this buffer_->into the given destination buffer_-> up to the + // size of the destination. Returns the number of bytes read. Reading from + // an empty buffer_->returns 0. + size_t Read(char* dest_buffer, size_t size) { + iovec dest; + dest.iov_base = dest_buffer, dest.iov_len = size; + return buffer_->Readv(&dest, 1); + } + + // If buffer is empty, the blocks_ array must be empty, which means all + // blocks are deallocated. + bool CheckEmptyInvariants() { + return !buffer_->Empty() || IsBlockArrayEmpty(); + } + + bool IsBlockArrayEmpty() { + size_t count = buffer_->blocks_count_; + for (size_t i = 0; i < count; i++) { + if (buffer_->blocks_[i] != nullptr) { + return false; + } + } + return true; + } + + bool CheckInitialState() { + EXPECT_TRUE(buffer_->Empty() && buffer_->total_bytes_read_ == 0 && + buffer_->num_bytes_buffered_ == 0); + return CheckBufferInvariants(); + } + + bool CheckBufferInvariants() { + QuicStreamOffset data_span = + buffer_->gaps_.back().begin_offset - buffer_->total_bytes_read_; + bool capacity_sane = data_span <= buffer_->max_buffer_capacity_bytes_ && + data_span >= buffer_->num_bytes_buffered_; + if (!capacity_sane) { + LOG(ERROR) << "data span is larger than capacity."; + LOG(ERROR) << "total read: " << buffer_->total_bytes_read_ + << " last byte: " << buffer_->gaps_.back().begin_offset; + } + bool total_read_sane = + buffer_->gaps_.front().begin_offset >= buffer_->total_bytes_read_; + if (!total_read_sane) { + LOG(ERROR) << "read across 1st gap."; + } + bool read_offset_sane = buffer_->ReadOffset() < kBlockSizeBytes; + if (!capacity_sane) { + LOG(ERROR) << "read offset go beyond 1st block"; + } + bool block_match_capacity = + (buffer_->max_buffer_capacity_bytes_ <= + buffer_->blocks_count_ * kBlockSizeBytes) && + (buffer_->max_buffer_capacity_bytes_ > + (buffer_->blocks_count_ - 1) * kBlockSizeBytes); + if (!capacity_sane) { + LOG(ERROR) << "block number not match capcaity."; + } + bool block_retired_when_empty = CheckEmptyInvariants(); + if (!block_retired_when_empty) { + LOG(ERROR) << "block is not retired after use."; + } + return capacity_sane && total_read_sane && read_offset_sane && + block_match_capacity && block_retired_when_empty; + } + + size_t GetInBlockOffset(QuicStreamOffset offset) { + return buffer_->GetInBlockOffset(offset); + } + + BufferBlock* GetBlock(size_t index) { return buffer_->blocks_[index]; } + + int GapSize() { return buffer_->gaps_.size(); } + + std::list<Gap> GetGaps() { return buffer_->gaps_; } + + size_t max_buffer_capacity() { return buffer_->max_buffer_capacity_bytes_; } + + size_t ReadableBytes() { return buffer_->ReadableBytes(); } + + std::map<QuicStreamOffset, FrameInfo>* frame_arrival_time_map() { + return &(buffer_->frame_arrival_time_map_); + } + + private: + StreamSequencerBuffer* buffer_; +}; + +namespace { + +class StreamSequencerBufferTest : public testing::Test { + public: + void SetUp() override { Initialize(); } + + void ResetMaxCapacityBytes(size_t max_capacity_bytes) { + max_capacity_bytes_ = max_capacity_bytes; + Initialize(); + } + + protected: + void Initialize() { + buffer_.reset(new StreamSequencerBuffer(max_capacity_bytes_)); + helper_.reset(new StreamSequencerBufferPeer(buffer_.get())); + } + + // Use 2.5 here to make sure the buffer has more than one block and its end + // doesn't align with the end of a block in order to test all the offset + // calculation. + size_t max_capacity_bytes_ = 2.5 * kBlockSizeBytes; + + MockClock clock_; + std::unique_ptr<StreamSequencerBuffer> buffer_; + std::unique_ptr<StreamSequencerBufferPeer> helper_; +}; + +TEST_F(StreamSequencerBufferTest, InitializationWithDifferentSizes) { + const size_t kCapacity = 2 * StreamSequencerBuffer::kBlockSizeBytes; + ResetMaxCapacityBytes(kCapacity); + EXPECT_EQ(max_capacity_bytes_, helper_->max_buffer_capacity()); + EXPECT_TRUE(helper_->CheckInitialState()); + + const size_t kCapacity1 = 8 * StreamSequencerBuffer::kBlockSizeBytes; + ResetMaxCapacityBytes(kCapacity1); + EXPECT_EQ(kCapacity1, helper_->max_buffer_capacity()); + EXPECT_TRUE(helper_->CheckInitialState()); +} + +TEST_F(StreamSequencerBufferTest, ClearOnEmpty) { + buffer_->Clear(); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +TEST_F(StreamSequencerBufferTest, OnStreamData0length) { + std::string source; + size_t written; + EXPECT_DFATAL( + buffer_->OnStreamData(800, source, clock_.ApproximateNow(), &written), + "Attempted to write 0 bytes of data."); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +TEST_F(StreamSequencerBufferTest, OnStreamDataWithinBlock) { + std::string source(1024, 'a'); + size_t written; + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); + QuicTime t = clock_.ApproximateNow(); + EXPECT_EQ(QUIC_NO_ERROR, buffer_->OnStreamData(800, source, t, &written)); + BufferBlock* block_ptr = helper_->GetBlock(0); + for (size_t i = 0; i < source.size(); ++i) { + ASSERT_EQ('a', block_ptr->buffer[helper_->GetInBlockOffset(800) + i]); + } + EXPECT_EQ(2, helper_->GapSize()); + std::list<Gap> gaps = helper_->GetGaps(); + EXPECT_EQ(800u, gaps.front().end_offset); + EXPECT_EQ(1824u, gaps.back().begin_offset); + auto frame_map = helper_->frame_arrival_time_map(); + EXPECT_EQ(1u, frame_map->size()); + EXPECT_EQ(800u, frame_map->begin()->first); + EXPECT_EQ(t, (*frame_map)[800].timestamp); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +TEST_F(StreamSequencerBufferTest, OnStreamDataWithOverlap) { + std::string source(1024, 'a'); + // Write something into [800, 1824) + size_t written; + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); + QuicTime t1 = clock_.ApproximateNow(); + EXPECT_EQ(QUIC_NO_ERROR, buffer_->OnStreamData(800, source, t1, &written)); + // Try to write to [0, 1024) and [1024, 2048). + // But no byte will be written since overlap. + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); + QuicTime t2 = clock_.ApproximateNow(); + EXPECT_EQ(QUIC_INVALID_STREAM_DATA, + buffer_->OnStreamData(0, source, t2, &written)); + EXPECT_EQ(QUIC_INVALID_STREAM_DATA, + buffer_->OnStreamData(1024, source, t2, &written)); + auto frame_map = helper_->frame_arrival_time_map(); + EXPECT_EQ(1u, frame_map->size()); + EXPECT_EQ(t1, (*frame_map)[800].timestamp); +} + +TEST_F(StreamSequencerBufferTest, OnStreamDataOverlapAndDuplicateCornerCases) { + std::string source(1024, 'a'); + // Write something into [800, 1824) + size_t written; + buffer_->OnStreamData(800, source, clock_.ApproximateNow(), &written); + source = std::string(800, 'b'); + // Try to write to [1, 801), but should fail due to overlapping + EXPECT_EQ( + QUIC_INVALID_STREAM_DATA, + buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written)); + // write to [0, 800) + EXPECT_EQ(QUIC_NO_ERROR, buffer_->OnStreamData( + 0, source, clock_.ApproximateNow(), &written)); + // Try to write one byte to [1823, 1824), but should count as duplicate + std::string one_byte = "c"; + EXPECT_EQ( + QUIC_NO_ERROR, + buffer_->OnStreamData(1823, one_byte, clock_.ApproximateNow(), &written)); + EXPECT_EQ(0u, written); + // write one byte to [1824, 1825) + EXPECT_EQ( + QUIC_NO_ERROR, + buffer_->OnStreamData(1824, one_byte, clock_.ApproximateNow(), &written)); + auto frame_map = helper_->frame_arrival_time_map(); + EXPECT_EQ(3u, frame_map->size()); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +TEST_F(StreamSequencerBufferTest, OnStreamDataWithoutOverlap) { + std::string source(1024, 'a'); + // Write something into [800, 1824). + size_t written; + EXPECT_EQ(QUIC_NO_ERROR, buffer_->OnStreamData( + 800, source, clock_.ApproximateNow(), &written)); + source = std::string(100, 'b'); + // Write something into [kBlockSizeBytes * 2 - 20, kBlockSizeBytes * 2 + 80). + EXPECT_EQ(QUIC_NO_ERROR, + buffer_->OnStreamData(kBlockSizeBytes * 2 - 20, source, + clock_.ApproximateNow(), &written)); + EXPECT_EQ(3, helper_->GapSize()); + EXPECT_EQ(1024u + 100u, buffer_->BytesBuffered()); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +TEST_F(StreamSequencerBufferTest, OnStreamDataTillEnd) { + // Write 50 bytes to the end. + const size_t kBytesToWrite = 50; + std::string source(kBytesToWrite, 'a'); + size_t written; + EXPECT_EQ(QUIC_NO_ERROR, + buffer_->OnStreamData(max_capacity_bytes_ - kBytesToWrite, source, + clock_.ApproximateNow(), &written)); + EXPECT_EQ(50u, buffer_->BytesBuffered()); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +TEST_F(StreamSequencerBufferTest, OnStreamDataTillEndCorner) { + // Write 1 byte to the end. + const size_t kBytesToWrite = 1; + std::string source(kBytesToWrite, 'a'); + size_t written; + EXPECT_EQ(QUIC_NO_ERROR, + buffer_->OnStreamData(max_capacity_bytes_ - kBytesToWrite, source, + clock_.ApproximateNow(), &written)); + EXPECT_EQ(1u, buffer_->BytesBuffered()); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +TEST_F(StreamSequencerBufferTest, OnStreamDataBeyondCapacity) { + std::string source(60, 'a'); + size_t written; + EXPECT_EQ(QUIC_INTERNAL_ERROR, + buffer_->OnStreamData(max_capacity_bytes_ - 50, source, + clock_.ApproximateNow(), &written)); + EXPECT_TRUE(helper_->CheckBufferInvariants()); + + source = "b"; + EXPECT_EQ(QUIC_INTERNAL_ERROR, + buffer_->OnStreamData(max_capacity_bytes_, source, + clock_.ApproximateNow(), &written)); + EXPECT_TRUE(helper_->CheckBufferInvariants()); + + EXPECT_EQ(QUIC_INTERNAL_ERROR, + buffer_->OnStreamData(max_capacity_bytes_ * 1000, source, + clock_.ApproximateNow(), &written)); + EXPECT_TRUE(helper_->CheckBufferInvariants()); + EXPECT_EQ(0u, buffer_->BytesBuffered()); +} + +TEST_F(StreamSequencerBufferTest, Readv100Bytes) { + std::string source(1024, 'a'); + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); + QuicTime t1 = clock_.ApproximateNow(); + // Write something into [kBlockSizeBytes, kBlockSizeBytes + 1024). + size_t written; + buffer_->OnStreamData(kBlockSizeBytes, source, t1, &written); + EXPECT_FALSE(buffer_->HasBytesToRead()); + source = std::string(100, 'b'); + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); + QuicTime t2 = clock_.ApproximateNow(); + // Write something into [0, 100). + buffer_->OnStreamData(0, source, t2, &written); + EXPECT_TRUE(buffer_->HasBytesToRead()); + EXPECT_EQ(2u, helper_->frame_arrival_time_map()->size()); + // Read into a iovec array with total capacity of 120 bytes. + char dest[120]; + iovec iovecs[3]{iovec{dest, 40}, iovec{dest + 40, 40}, iovec{dest + 80, 40}}; + size_t read = buffer_->Readv(iovecs, 3); + EXPECT_EQ(100u, read); + EXPECT_EQ(100u, buffer_->BytesConsumed()); + EXPECT_EQ(source, std::string(dest, read)); + EXPECT_EQ(1u, helper_->frame_arrival_time_map()->size()); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +TEST_F(StreamSequencerBufferTest, ReadvAcrossBlocks) { + std::string source(kBlockSizeBytes + 50, 'a'); + // Write 1st block to full and extand 50 bytes to next block. + size_t written; + buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written); + EXPECT_EQ(source.size(), helper_->ReadableBytes()); + // Iteratively read 512 bytes from buffer_-> Overwrite dest[] each time. + char dest[512]; + while (helper_->ReadableBytes()) { + std::fill(dest, dest + 512, 0); + iovec iovecs[2]{iovec{dest, 256}, iovec{dest + 256, 256}}; + buffer_->Readv(iovecs, 2); + } + // The last read only reads the rest 50 bytes in 2nd block. + EXPECT_EQ(std::string(50, 'a'), std::string(dest, 50)); + EXPECT_EQ(0, dest[50]) << "Dest[50] shouln't be filled."; + EXPECT_EQ(source.size(), buffer_->BytesConsumed()); + EXPECT_TRUE(buffer_->Empty()); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +TEST_F(StreamSequencerBufferTest, ClearAfterRead) { + std::string source(kBlockSizeBytes + 50, 'a'); + // Write 1st block to full with 'a'. + size_t written; + buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written); + // Read first 512 bytes from buffer to make space at the beginning. + char dest[512]{0}; + const iovec iov{dest, 512}; + buffer_->Readv(&iov, 1); + // Clear() should make buffer empty while preserving BytesConsumed() + buffer_->Clear(); + EXPECT_TRUE(buffer_->Empty()); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +TEST_F(StreamSequencerBufferTest, OnStreamDataAcrossLastBlockAndFillCapacity) { + std::string source(kBlockSizeBytes + 50, 'a'); + // Write 1st block to full with 'a'. + size_t written; + buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written); + // Read first 512 bytes from buffer to make space at the beginning. + char dest[512]{0}; + const iovec iov{dest, 512}; + buffer_->Readv(&iov, 1); + EXPECT_EQ(source.size(), written); + + // Write more than half block size of bytes in the last block with 'b', which + // will wrap to the beginning and reaches the full capacity. + source = std::string(0.5 * kBlockSizeBytes + 512, 'b'); + EXPECT_EQ(QUIC_NO_ERROR, + buffer_->OnStreamData(2 * kBlockSizeBytes, source, + clock_.ApproximateNow(), &written)); + EXPECT_EQ(source.size(), written); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +TEST_F(StreamSequencerBufferTest, + OnStreamDataAcrossLastBlockAndExceedCapacity) { + std::string source(kBlockSizeBytes + 50, 'a'); + // Write 1st block to full. + size_t written; + buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written); + // Read first 512 bytes from buffer to make space at the beginning. + char dest[512]{0}; + const iovec iov{dest, 512}; + buffer_->Readv(&iov, 1); + + // Try to write from [max_capacity_bytes_ - 0.5 * kBlockSizeBytes, + // max_capacity_bytes_ + 512 + 1). But last bytes exceeds current capacity. + source = std::string(0.5 * kBlockSizeBytes + 512 + 1, 'b'); + EXPECT_EQ(QUIC_INTERNAL_ERROR, + buffer_->OnStreamData(2 * kBlockSizeBytes, source, + clock_.ApproximateNow(), &written)); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +TEST_F(StreamSequencerBufferTest, ReadvAcrossLastBlock) { + // Write to full capacity and read out 512 bytes at beginning and continue + // appending 256 bytes. + std::string source(max_capacity_bytes_, 'a'); + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); + QuicTime t = clock_.ApproximateNow(); + size_t written; + buffer_->OnStreamData(0, source, t, &written); + char dest[512]{0}; + const iovec iov{dest, 512}; + buffer_->Readv(&iov, 1); + source = std::string(256, 'b'); + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); + QuicTime t2 = clock_.ApproximateNow(); + buffer_->OnStreamData(max_capacity_bytes_, source, t2, &written); + EXPECT_TRUE(helper_->CheckBufferInvariants()); + EXPECT_EQ(2u, helper_->frame_arrival_time_map()->size()); + + // Read all data out. + std::unique_ptr<char[]> dest1{new char[max_capacity_bytes_]{0}}; + const iovec iov1{dest1.get(), max_capacity_bytes_}; + EXPECT_EQ(max_capacity_bytes_ - 512 + 256, buffer_->Readv(&iov1, 1)); + EXPECT_EQ(max_capacity_bytes_ + 256, buffer_->BytesConsumed()); + EXPECT_TRUE(buffer_->Empty()); + EXPECT_TRUE(helper_->CheckBufferInvariants()); + EXPECT_EQ(0u, helper_->frame_arrival_time_map()->size()); +} + +TEST_F(StreamSequencerBufferTest, ReadvEmpty) { + char dest[512]{0}; + iovec iov{dest, 512}; + size_t read = buffer_->Readv(&iov, 1); + EXPECT_EQ(0u, read); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +TEST_F(StreamSequencerBufferTest, GetReadableRegionsEmpty) { + iovec iovs[2]; + int iov_count = buffer_->GetReadableRegions(iovs, 2); + EXPECT_EQ(0, iov_count); + EXPECT_EQ(nullptr, iovs[iov_count].iov_base); + EXPECT_EQ(0u, iovs[iov_count].iov_len); +} + +TEST_F(StreamSequencerBufferTest, GetReadableRegionsBlockedByGap) { + // Write into [1, 1024). + std::string source(1023, 'a'); + size_t written; + buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written); + // Try to get readable regions, but none is there. + iovec iovs[2]; + int iov_count = buffer_->GetReadableRegions(iovs, 2); + EXPECT_EQ(0, iov_count); +} + +TEST_F(StreamSequencerBufferTest, GetReadableRegionsTillEndOfBlock) { + // Write first block to full with [0, 256) 'a' and the rest 'b' then read out + // [0, 256) + std::string source(kBlockSizeBytes, 'a'); + size_t written; + buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written); + char dest[256]; + helper_->Read(dest, 256); + // Get readable region from [256, 1024) + iovec iovs[2]; + int iov_count = buffer_->GetReadableRegions(iovs, 2); + EXPECT_EQ(1, iov_count); + EXPECT_EQ(std::string(kBlockSizeBytes - 256, 'a'), + std::string(reinterpret_cast<const char*>(iovs[0].iov_base), + iovs[0].iov_len)); +} + +TEST_F(StreamSequencerBufferTest, GetReadableRegionsWithinOneBlock) { + // Write into [0, 1024) and then read out [0, 256) + std::string source(1024, 'a'); + size_t written; + buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written); + char dest[256]; + helper_->Read(dest, 256); + // Get readable region from [256, 1024) + iovec iovs[2]; + int iov_count = buffer_->GetReadableRegions(iovs, 2); + EXPECT_EQ(1, iov_count); + EXPECT_EQ(std::string(1024 - 256, 'a'), + std::string(reinterpret_cast<const char*>(iovs[0].iov_base), + iovs[0].iov_len)); +} + +TEST_F(StreamSequencerBufferTest, GetReadableRegionsAcrossBlockWithLongIOV) { + // Write into [0, 2 * kBlockSizeBytes + 1024) and then read out [0, 1024) + std::string source(2 * kBlockSizeBytes + 1024, 'a'); + size_t written; + buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written); + char dest[1024]; + helper_->Read(dest, 1024); + + iovec iovs[4]; + int iov_count = buffer_->GetReadableRegions(iovs, 4); + EXPECT_EQ(3, iov_count); + EXPECT_EQ(kBlockSizeBytes - 1024, iovs[0].iov_len); + EXPECT_EQ(kBlockSizeBytes, iovs[1].iov_len); + EXPECT_EQ(1024u, iovs[2].iov_len); +} + +TEST_F(StreamSequencerBufferTest, GetReadableRegionsWithMultipleIOVsAcrossEnd) { + // Write into [0, 2 * kBlockSizeBytes + 1024) and then read out [0, 1024) + // and then append 1024 + 512 bytes. + std::string source(2.5 * kBlockSizeBytes - 1024, 'a'); + size_t written; + buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written); + char dest[1024]; + helper_->Read(dest, 1024); + // Write across the end. + source = std::string(1024 + 512, 'b'); + buffer_->OnStreamData(2.5 * kBlockSizeBytes - 1024, source, + clock_.ApproximateNow(), &written); + // Use short iovec's. + iovec iovs[2]; + int iov_count = buffer_->GetReadableRegions(iovs, 2); + EXPECT_EQ(2, iov_count); + EXPECT_EQ(kBlockSizeBytes - 1024, iovs[0].iov_len); + EXPECT_EQ(kBlockSizeBytes, iovs[1].iov_len); + // Use long iovec's and wrap the end of buffer. + iovec iovs1[5]; + EXPECT_EQ(4, buffer_->GetReadableRegions(iovs1, 5)); + EXPECT_EQ(0.5 * kBlockSizeBytes, iovs1[2].iov_len); + EXPECT_EQ(512u, iovs1[3].iov_len); + EXPECT_EQ(std::string(512, 'b'), + std::string(reinterpret_cast<const char*>(iovs1[3].iov_base), + iovs1[3].iov_len)); +} + +TEST_F(StreamSequencerBufferTest, GetReadableRegionEmpty) { + iovec iov; + QuicTime t = QuicTime::Zero(); + EXPECT_FALSE(buffer_->GetReadableRegion(&iov, &t)); + EXPECT_EQ(nullptr, iov.iov_base); + EXPECT_EQ(0u, iov.iov_len); +} + +TEST_F(StreamSequencerBufferTest, GetReadableRegionBeforeGap) { + // Write into [1, 1024). + std::string source(1023, 'a'); + size_t written; + buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written); + // GetReadableRegion should return false because range [0,1) hasn't been + // filled yet. + iovec iov; + QuicTime t = QuicTime::Zero(); + EXPECT_FALSE(buffer_->GetReadableRegion(&iov, &t)); +} + +TEST_F(StreamSequencerBufferTest, GetReadableRegionTillEndOfBlock) { + // Write into [0, kBlockSizeBytes + 1) and then read out [0, 256) + std::string source(kBlockSizeBytes + 1, 'a'); + size_t written; + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); + QuicTime t = clock_.ApproximateNow(); + buffer_->OnStreamData(0, source, t, &written); + char dest[256]; + helper_->Read(dest, 256); + // Get readable region from [256, 1024) + iovec iov; + QuicTime t2 = QuicTime::Zero(); + EXPECT_TRUE(buffer_->GetReadableRegion(&iov, &t2)); + EXPECT_EQ(t, t2); + EXPECT_EQ( + std::string(kBlockSizeBytes - 256, 'a'), + std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len)); +} + +TEST_F(StreamSequencerBufferTest, GetReadableRegionTillGap) { + // Write into [0, kBlockSizeBytes - 1) and then read out [0, 256) + std::string source(kBlockSizeBytes - 1, 'a'); + size_t written; + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); + QuicTime t = clock_.ApproximateNow(); + buffer_->OnStreamData(0, source, t, &written); + char dest[256]; + helper_->Read(dest, 256); + // Get readable region from [256, 1023) + iovec iov; + QuicTime t2 = QuicTime::Zero(); + EXPECT_TRUE(buffer_->GetReadableRegion(&iov, &t2)); + EXPECT_EQ(t, t2); + EXPECT_EQ( + std::string(kBlockSizeBytes - 1 - 256, 'a'), + std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len)); +} + +TEST_F(StreamSequencerBufferTest, GetReadableRegionByArrivalTime) { + // Write into [0, kBlockSizeBytes - 100) and then read out [0, 256) + std::string source(kBlockSizeBytes - 100, 'a'); + size_t written; + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); + QuicTime t = clock_.ApproximateNow(); + buffer_->OnStreamData(0, source, t, &written); + char dest[256]; + helper_->Read(dest, 256); + // Write into [kBlockSizeBytes - 100, kBlockSizeBytes - 50)] in same time + std::string source2(50, 'b'); + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); + buffer_->OnStreamData(kBlockSizeBytes - 100, source2, t, &written); + + // Write into [kBlockSizeBytes - 50, kBlockSizeBytes)] in another time + std::string source3(50, 'c'); + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); + QuicTime t3 = clock_.ApproximateNow(); + buffer_->OnStreamData(kBlockSizeBytes - 50, source3, t3, &written); + + // Get readable region from [256, 1024 - 50) + iovec iov; + QuicTime t4 = QuicTime::Zero(); + EXPECT_TRUE(buffer_->GetReadableRegion(&iov, &t4)); + EXPECT_EQ(t, t4); + EXPECT_EQ( + std::string(kBlockSizeBytes - 100 - 256, 'a') + source2, + std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len)); +} + +TEST_F(StreamSequencerBufferTest, MarkConsumedInOneBlock) { + // Write into [0, 1024) and then read out [0, 256) + std::string source(1024, 'a'); + size_t written; + buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written); + char dest[256]; + helper_->Read(dest, 256); + + EXPECT_TRUE(buffer_->MarkConsumed(512)); + EXPECT_EQ(256u + 512u, buffer_->BytesConsumed()); + EXPECT_EQ(256u, helper_->ReadableBytes()); + EXPECT_EQ(1u, helper_->frame_arrival_time_map()->size()); + buffer_->MarkConsumed(256); + EXPECT_EQ(0u, helper_->frame_arrival_time_map()->size()); + EXPECT_TRUE(buffer_->Empty()); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +TEST_F(StreamSequencerBufferTest, MarkConsumedNotEnoughBytes) { + // Write into [0, 1024) and then read out [0, 256) + std::string source(1024, 'a'); + size_t written; + QuicTime t = clock_.ApproximateNow(); + buffer_->OnStreamData(0, source, t, &written); + char dest[256]; + helper_->Read(dest, 256); + + // Consume 1st 512 bytes + EXPECT_TRUE(buffer_->MarkConsumed(512)); + EXPECT_EQ(256u + 512u, buffer_->BytesConsumed()); + EXPECT_EQ(256u, helper_->ReadableBytes()); + // Try to consume one bytes more than available. Should return false. + EXPECT_FALSE(buffer_->MarkConsumed(257)); + EXPECT_EQ(256u + 512u, buffer_->BytesConsumed()); + QuicTime t2 = QuicTime::Zero(); + iovec iov; + EXPECT_TRUE(buffer_->GetReadableRegion(&iov, &t2)); + EXPECT_EQ(t, t2); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +TEST_F(StreamSequencerBufferTest, MarkConsumedAcrossBlock) { + // Write into [0, 2 * kBlockSizeBytes + 1024) and then read out [0, 1024) + std::string source(2 * kBlockSizeBytes + 1024, 'a'); + size_t written; + buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written); + char dest[1024]; + helper_->Read(dest, 1024); + + buffer_->MarkConsumed(2 * kBlockSizeBytes); + EXPECT_EQ(source.size(), buffer_->BytesConsumed()); + EXPECT_TRUE(buffer_->Empty()); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +TEST_F(StreamSequencerBufferTest, MarkConsumedAcrossEnd) { + // Write into [0, 2.5 * kBlockSizeBytes - 1024) and then read out [0, 1024) + // and then append 1024 + 512 bytes. + std::string source(2.5 * kBlockSizeBytes - 1024, 'a'); + size_t written; + buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written); + char dest[1024]; + helper_->Read(dest, 1024); + source = std::string(1024 + 512, 'b'); + buffer_->OnStreamData(2.5 * kBlockSizeBytes - 1024, source, + clock_.ApproximateNow(), &written); + EXPECT_EQ(1024u, buffer_->BytesConsumed()); + + // Consume to the end of 2nd block. + buffer_->MarkConsumed(2 * kBlockSizeBytes - 1024); + EXPECT_EQ(2 * kBlockSizeBytes, buffer_->BytesConsumed()); + // Consume across the physical end of buffer + buffer_->MarkConsumed(0.5 * kBlockSizeBytes + 500); + EXPECT_EQ(max_capacity_bytes_ + 500, buffer_->BytesConsumed()); + EXPECT_EQ(12u, helper_->ReadableBytes()); + // Consume to the logical end of buffer + buffer_->MarkConsumed(12); + EXPECT_EQ(max_capacity_bytes_ + 512, buffer_->BytesConsumed()); + EXPECT_TRUE(buffer_->Empty()); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +TEST_F(StreamSequencerBufferTest, FlushBufferedFrames) { + // Write into [0, 2.5 * kBlockSizeBytes - 1024) and then read out [0, 1024). + std::string source(max_capacity_bytes_ - 1024, 'a'); + size_t written; + buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written); + char dest[1024]; + helper_->Read(dest, 1024); + EXPECT_EQ(1024u, buffer_->BytesConsumed()); + // Write [1024, 512) to the physical beginning. + source = std::string(512, 'b'); + buffer_->OnStreamData(max_capacity_bytes_, source, clock_.ApproximateNow(), + &written); + EXPECT_EQ(512u, written); + EXPECT_EQ(max_capacity_bytes_ - 1024 + 512, buffer_->FlushBufferedFrames()); + EXPECT_EQ(max_capacity_bytes_ + 512, buffer_->BytesConsumed()); + EXPECT_TRUE(buffer_->Empty()); + EXPECT_TRUE(helper_->CheckBufferInvariants()); + // Clear buffer at this point should still preserve BytesConsumed(). + buffer_->Clear(); + EXPECT_EQ(max_capacity_bytes_ + 512, buffer_->BytesConsumed()); + EXPECT_TRUE(helper_->CheckBufferInvariants()); +} + +class StreamSequencerBufferRandomIOTest : public StreamSequencerBufferTest { + public: + typedef std::pair<QuicStreamOffset, size_t> OffsetSizePair; + + void SetUp() override { + // Test against a larger capacity then above tests. Also make sure the last + // block is partially available to use. + max_capacity_bytes_ = 6.25 * kBlockSizeBytes; + // Stream to be buffered should be larger than the capacity to test wrap + // around. + bytes_to_buffer_ = 2 * max_capacity_bytes_; + Initialize(); + + uint32 seed = base::RandInt(0, std::numeric_limits<int32>::max()); + LOG(INFO) << "RandomWriteAndProcessInPlace test seed is " << seed; + rng_.set_seed(seed); + } + + // Create an out-of-order source stream with given size to populate + // shuffled_buf_. + void CreateSourceAndShuffle(size_t max_chunk_size_bytes) { + max_chunk_size_bytes_ = max_chunk_size_bytes; + std::unique_ptr<OffsetSizePair[]> chopped_stream( + new OffsetSizePair[bytes_to_buffer_]); + + // Split stream into small chunks with random length. chopped_stream will be + // populated with segmented stream chunks. + size_t start_chopping_offset = 0; + size_t iterations = 0; + while (start_chopping_offset < bytes_to_buffer_) { + size_t max_chunk = min<size_t>(max_chunk_size_bytes_, + bytes_to_buffer_ - start_chopping_offset); + size_t chunk_size = rng_.RandUint64() % max_chunk + 1; + chopped_stream[iterations] = + OffsetSizePair(start_chopping_offset, chunk_size); + start_chopping_offset += chunk_size; + ++iterations; + } + DCHECK(start_chopping_offset == bytes_to_buffer_); + size_t chunk_num = iterations; + + // Randomly change the sequence of in-ordered OffsetSizePairs to make a + // out-of-order array of OffsetSizePairs. + for (int i = chunk_num - 1; i >= 0; --i) { + size_t random_idx = rng_.RandUint64() % (i + 1); + DVLOG(1) << "chunk offset " << chopped_stream[random_idx].first + << " size " << chopped_stream[random_idx].second; + shuffled_buf_.push_front(chopped_stream[random_idx]); + chopped_stream[random_idx] = chopped_stream[i]; + } + } + + // Write the currently first chunk of data in the out-of-order stream into + // StreamSequencerBuffer. If current chuck cannot be written into buffer + // because it goes beyond current capacity, move it to the end of + // shuffled_buf_ and write it later. + void WriteNextChunkToBuffer() { + OffsetSizePair& chunk = shuffled_buf_.front(); + QuicStreamOffset offset = chunk.first; + const size_t num_to_write = chunk.second; + std::unique_ptr<char[]> write_buf{new char[max_chunk_size_bytes_]}; + for (size_t i = 0; i < num_to_write; ++i) { + write_buf[i] = (offset + i) % 256; + } + base::StringPiece string_piece_w(write_buf.get(), num_to_write); + size_t written; + auto result = buffer_->OnStreamData(offset, string_piece_w, + clock_.ApproximateNow(), &written); + if (result == QUIC_NO_ERROR) { + shuffled_buf_.pop_front(); + total_bytes_written_ += num_to_write; + } else { + // This chunk offset exceeds window size. + shuffled_buf_.push_back(chunk); + shuffled_buf_.pop_front(); + } + DVLOG(1) << " write at offset: " << offset + << " len to write: " << num_to_write << " write result: " << result + << " left over: " << shuffled_buf_.size(); + } + + protected: + std::list<OffsetSizePair> shuffled_buf_; + size_t max_chunk_size_bytes_; + QuicStreamOffset bytes_to_buffer_; + size_t total_bytes_written_ = 0; + size_t total_bytes_read_ = 0; + SimpleRandom rng_; +}; + +TEST_F(StreamSequencerBufferRandomIOTest, RandomWriteAndReadv) { + // Set kMaxReadSize larger than kBlockSizeBytes to test both small and large + // read. + const size_t kMaxReadSize = kBlockSizeBytes * 2; + // kNumReads is larger than 1 to test how multiple read destinations work. + const size_t kNumReads = 2; + // Since write and read operation have equal possibility to be called. Bytes + // to be written into and read out of should roughly the same. + const size_t kMaxWriteSize = kNumReads * kMaxReadSize; + size_t iterations = 0; + + CreateSourceAndShuffle(kMaxWriteSize); + + while ((!shuffled_buf_.empty() || total_bytes_read_ < bytes_to_buffer_) && + iterations <= 2 * bytes_to_buffer_) { + uint8 next_action = + shuffled_buf_.empty() ? uint8{1} : rng_.RandUint64() % 2; + DVLOG(1) << "iteration: " << iterations; + switch (next_action) { + case 0: { // write + WriteNextChunkToBuffer(); + ASSERT_TRUE(helper_->CheckBufferInvariants()); + break; + } + case 1: { // readv + std::unique_ptr<char[][kMaxReadSize]> read_buf{ + new char[kNumReads][kMaxReadSize]}; + iovec dest_iov[kNumReads]; + size_t num_to_read = 0; + for (size_t i = 0; i < kNumReads; ++i) { + dest_iov[i].iov_base = + reinterpret_cast<void*>(const_cast<char*>(read_buf[i])); + dest_iov[i].iov_len = rng_.RandUint64() % kMaxReadSize; + num_to_read += dest_iov[i].iov_len; + } + size_t actually_read = buffer_->Readv(dest_iov, kNumReads); + ASSERT_LE(actually_read, num_to_read); + DVLOG(1) << " read from offset: " << total_bytes_read_ + << " size: " << num_to_read + << " actual read: " << actually_read; + for (size_t i = 0; i < actually_read; ++i) { + char ch = (i + total_bytes_read_) % 256; + ASSERT_EQ(ch, GetCharFromIOVecs(i, dest_iov, kNumReads)) + << " at iteration " << iterations; + } + total_bytes_read_ += actually_read; + ASSERT_EQ(total_bytes_read_, buffer_->BytesConsumed()); + ASSERT_TRUE(helper_->CheckBufferInvariants()); + break; + } + } + ++iterations; + ASSERT_LE(total_bytes_read_, total_bytes_written_); + } + EXPECT_LT(iterations, bytes_to_buffer_) << "runaway test"; + EXPECT_LE(bytes_to_buffer_, total_bytes_read_) << "iterations: " + << iterations; + EXPECT_LE(bytes_to_buffer_, total_bytes_written_); +} + +TEST_F(StreamSequencerBufferRandomIOTest, RandomWriteAndConsumeInPlace) { + // The value 4 is chosen such that the max write size is no larger than the + // maximum buffer capacity. + const size_t kMaxNumReads = 4; + // Adjust write amount be roughly equal to that GetReadableRegions() can get. + const size_t kMaxWriteSize = kMaxNumReads * kBlockSizeBytes; + ASSERT_LE(kMaxWriteSize, max_capacity_bytes_); + size_t iterations = 0; + + CreateSourceAndShuffle(kMaxWriteSize); + + while ((!shuffled_buf_.empty() || total_bytes_read_ < bytes_to_buffer_) && + iterations <= 2 * bytes_to_buffer_) { + uint8 next_action = + shuffled_buf_.empty() ? uint8{1} : rng_.RandUint64() % 2; + DVLOG(1) << "iteration: " << iterations; + switch (next_action) { + case 0: { // write + WriteNextChunkToBuffer(); + ASSERT_TRUE(helper_->CheckBufferInvariants()); + break; + } + case 1: { // GetReadableRegions and then MarkConsumed + size_t num_read = rng_.RandUint64() % kMaxNumReads + 1; + iovec dest_iov[kMaxNumReads]; + ASSERT_TRUE(helper_->CheckBufferInvariants()); + size_t actually_num_read = + buffer_->GetReadableRegions(dest_iov, num_read); + ASSERT_LE(actually_num_read, num_read); + size_t avail_bytes = 0; + for (size_t i = 0; i < actually_num_read; ++i) { + avail_bytes += dest_iov[i].iov_len; + } + // process random number of bytes (check the value of each byte). + size_t bytes_to_process = rng_.RandUint64() % (avail_bytes + 1); + size_t bytes_processed = 0; + for (size_t i = 0; i < actually_num_read; ++i) { + size_t bytes_in_block = min<size_t>( + bytes_to_process - bytes_processed, dest_iov[i].iov_len); + if (bytes_in_block == 0) { + break; + } + for (size_t j = 0; j < bytes_in_block; ++j) { + ASSERT_LE(bytes_processed, bytes_to_process); + char char_expected = + (buffer_->BytesConsumed() + bytes_processed) % 256; + ASSERT_EQ(char_expected, + reinterpret_cast<const char*>(dest_iov[i].iov_base)[j]) + << " at iteration " << iterations; + ++bytes_processed; + } + } + + buffer_->MarkConsumed(bytes_processed); + + DVLOG(1) << "iteration " << iterations << ": try to get " << num_read + << " readable regions, actually get " << actually_num_read + << " from offset: " << total_bytes_read_ + << "\nprocesse bytes: " << bytes_processed; + total_bytes_read_ += bytes_processed; + ASSERT_EQ(total_bytes_read_, buffer_->BytesConsumed()); + ASSERT_TRUE(helper_->CheckBufferInvariants()); + break; + } + } + ++iterations; + ASSERT_LE(total_bytes_read_, total_bytes_written_); + } + EXPECT_LT(iterations, bytes_to_buffer_) << "runaway test"; + EXPECT_LE(bytes_to_buffer_, total_bytes_read_) << "iterations: " + << iterations; + EXPECT_LE(bytes_to_buffer_, total_bytes_written_); +} + +} // anonymous namespace + +} // namespace test + +} // namespace net
diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc index 84c1c9f7..6d8dae9 100644 --- a/net/quic/test_tools/crypto_test_utils.cc +++ b/net/quic/test_tools/crypto_test_utils.cc
@@ -171,7 +171,7 @@ // static int CryptoTestUtils::HandshakeWithFakeServer( - MockHelper* helper, + MockConnectionHelper* helper, PacketSavingConnection* client_conn, QuicCryptoClientStream* client) { PacketSavingConnection* server_conn = new PacketSavingConnection( @@ -199,7 +199,7 @@ // static int CryptoTestUtils::HandshakeWithFakeClient( - MockHelper* helper, + MockConnectionHelper* helper, PacketSavingConnection* server_conn, QuicCryptoServerStream* server, const QuicServerId& server_id,
diff --git a/net/quic/test_tools/crypto_test_utils.h b/net/quic/test_tools/crypto_test_utils.h index c0a7d9e..3104bca 100644 --- a/net/quic/test_tools/crypto_test_utils.h +++ b/net/quic/test_tools/crypto_test_utils.h
@@ -69,12 +69,12 @@ }; // returns: the number of client hellos that the client sent. - static int HandshakeWithFakeServer(MockHelper* helper, + static int HandshakeWithFakeServer(MockConnectionHelper* helper, PacketSavingConnection* client_conn, QuicCryptoClientStream* client); // returns: the number of client hellos that the client sent. - static int HandshakeWithFakeClient(MockHelper* helper, + static int HandshakeWithFakeClient(MockConnectionHelper* helper, PacketSavingConnection* server_conn, QuicCryptoServerStream* server, const QuicServerId& server_id,
diff --git a/net/quic/test_tools/crypto_test_utils_chromium.cc b/net/quic/test_tools/crypto_test_utils_chromium.cc index ffa1788..8ff3c97 100644 --- a/net/quic/test_tools/crypto_test_utils_chromium.cc +++ b/net/quic/test_tools/crypto_test_utils_chromium.cc
@@ -50,6 +50,7 @@ const char kLeafCert[] = "leaf"; const char kIntermediateCert[] = "intermediate"; const char kSignature[] = "signature"; +const char kSCT[] = "CryptoServerTests"; class FakeProofSource : public ProofSource { public: @@ -65,9 +66,11 @@ const std::string& server_config, bool ecdsa_ok, const std::vector<std::string>** out_certs, - std::string* out_signature) override { + std::string* out_signature, + std::string* out_leaf_cert_sct) override { *out_certs = &certs_; *out_signature = kSignature; + *out_leaf_cert_sct = kSCT; return true; } @@ -117,7 +120,8 @@ base::FilePath certs_dir = GetTestCertsDirectory(); CHECK(source->Initialize( certs_dir.AppendASCII("quic_test.example.com.crt"), - certs_dir.AppendASCII("quic_test.example.com.key.pkcs8"))); + certs_dir.AppendASCII("quic_test.example.com.key.pkcs8"), + certs_dir.AppendASCII("quic_test.example.com.key.sct"))); return source; }
diff --git a/net/quic/test_tools/quic_connection_peer.cc b/net/quic/test_tools/quic_connection_peer.cc index 5bd6370..15653ce 100644 --- a/net/quic/test_tools/quic_connection_peer.cc +++ b/net/quic/test_tools/quic_connection_peer.cc
@@ -73,6 +73,12 @@ } // static +QuicSentEntropyManager* QuicConnectionPeer::GetSentEntropyManager( + QuicConnection* connection) { + return &connection->sent_entropy_manager_; +} + +// static // TODO(ianswett): Create a GetSentEntropyHash which accepts an AckFrame. QuicPacketEntropyHash QuicConnectionPeer::GetSentEntropyHash( QuicConnection* connection, @@ -213,7 +219,11 @@ // static QuicEncryptedPacket* QuicConnectionPeer::GetConnectionClosePacket( QuicConnection* connection) { - return connection->connection_close_packet_.get(); + if (connection->termination_packets_ == nullptr || + connection->termination_packets_->empty()) { + return nullptr; + } + return (*connection->termination_packets_)[0]; } // static
diff --git a/net/quic/test_tools/quic_connection_peer.h b/net/quic/test_tools/quic_connection_peer.h index d7bfe444..ff29cf1 100644 --- a/net/quic/test_tools/quic_connection_peer.h +++ b/net/quic/test_tools/quic_connection_peer.h
@@ -25,6 +25,7 @@ class QuicPacketGenerator; class QuicPacketWriter; class QuicReceivedPacketManager; +class QuicSentEntropyManager; class QuicSentPacketManager; class SendAlgorithmInterface; @@ -55,6 +56,9 @@ static QuicTime::Delta GetNetworkTimeout(QuicConnection* connection); + static QuicSentEntropyManager* GetSentEntropyManager( + QuicConnection* connection); + static QuicPacketEntropyHash GetSentEntropyHash( QuicConnection* connection, QuicPacketNumber packet_number);
diff --git a/net/quic/test_tools/quic_packet_creator_peer.cc b/net/quic/test_tools/quic_packet_creator_peer.cc index b5c9414..0b9a1014 100644 --- a/net/quic/test_tools/quic_packet_creator_peer.cc +++ b/net/quic/test_tools/quic_packet_creator_peer.cc
@@ -52,5 +52,13 @@ creator->packet_number_ = s; } +// static +void QuicPacketCreatorPeer::FillPacketHeader(QuicPacketCreator* creator, + QuicFecGroupNumber fec_group, + bool fec_flag, + QuicPacketHeader* header) { + creator->FillPacketHeader(fec_group, fec_flag, header); +} + } // namespace test } // namespace net
diff --git a/net/quic/test_tools/quic_packet_creator_peer.h b/net/quic/test_tools/quic_packet_creator_peer.h index 83efcb2..305a20cd 100644 --- a/net/quic/test_tools/quic_packet_creator_peer.h +++ b/net/quic/test_tools/quic_packet_creator_peer.h
@@ -29,6 +29,10 @@ static QuicPacketNumberLength NextPacketNumberLength( QuicPacketCreator* creator); static void SetPacketNumber(QuicPacketCreator* creator, QuicPacketNumber s); + static void FillPacketHeader(QuicPacketCreator* creator, + QuicFecGroupNumber fec_group, + bool fec_flag, + QuicPacketHeader* header); private: DISALLOW_COPY_AND_ASSIGN(QuicPacketCreatorPeer);
diff --git a/net/quic/test_tools/quic_session_peer.cc b/net/quic/test_tools/quic_session_peer.cc index f757121..cbf0ab46 100644 --- a/net/quic/test_tools/quic_session_peer.cc +++ b/net/quic/test_tools/quic_session_peer.cc
@@ -42,10 +42,10 @@ } // static -ReliableQuicStream* QuicSessionPeer::GetIncomingDynamicStream( +ReliableQuicStream* QuicSessionPeer::GetOrCreateDynamicStream( QuicSession* session, QuicStreamId stream_id) { - return session->GetIncomingDynamicStream(stream_id); + return session->GetOrCreateDynamicStream(stream_id); } // static
diff --git a/net/quic/test_tools/quic_session_peer.h b/net/quic/test_tools/quic_session_peer.h index b1c0cd4a..5ff9da98 100644 --- a/net/quic/test_tools/quic_session_peer.h +++ b/net/quic/test_tools/quic_session_peer.h
@@ -29,7 +29,7 @@ static void SetMaxOpenStreams(QuicSession* session, uint32 max_streams); static QuicCryptoStream* GetCryptoStream(QuicSession* session); static QuicWriteBlockedList* GetWriteBlockedStreams(QuicSession* session); - static ReliableQuicStream* GetIncomingDynamicStream(QuicSession* session, + static ReliableQuicStream* GetOrCreateDynamicStream(QuicSession* session, QuicStreamId stream_id); static std::map<QuicStreamId, QuicStreamOffset>& GetLocallyClosedStreamsHighestOffset(QuicSession* session);
diff --git a/net/quic/test_tools/quic_test_packet_maker.cc b/net/quic/test_tools/quic_test_packet_maker.cc index e3f30fd..adecf9c 100644 --- a/net/quic/test_tools/quic_test_packet_maker.cc +++ b/net/quic/test_tools/quic_test_packet_maker.cc
@@ -92,10 +92,11 @@ scoped_ptr<QuicPacket> packet( BuildUnsizedDataPacket(&framer, header, frames)); char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> encrypted(framer.EncryptPayload( - ENCRYPTION_NONE, header.packet_number, *packet, buffer, kMaxPacketSize)); - EXPECT_TRUE(encrypted != nullptr); - return scoped_ptr<QuicEncryptedPacket>(encrypted->Clone()); + size_t encrypted_size = framer.EncryptPayload( + ENCRYPTION_NONE, header.packet_number, *packet, buffer, kMaxPacketSize); + EXPECT_NE(0u, encrypted_size); + QuicEncryptedPacket encrypted(buffer, encrypted_size, false); + return scoped_ptr<QuicEncryptedPacket>(encrypted.Clone()); } scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeConnectionClosePacket( @@ -149,10 +150,11 @@ scoped_ptr<QuicPacket> packet( BuildUnsizedDataPacket(&framer, header, frames)); char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> encrypted(framer.EncryptPayload( - ENCRYPTION_NONE, header.packet_number, *packet, buffer, kMaxPacketSize)); - EXPECT_TRUE(encrypted != nullptr); - return scoped_ptr<QuicEncryptedPacket>(encrypted->Clone()); + size_t encrypted_size = framer.EncryptPayload( + ENCRYPTION_NONE, header.packet_number, *packet, buffer, kMaxPacketSize); + EXPECT_NE(0u, encrypted_size); + QuicEncryptedPacket encrypted(buffer, encrypted_size, false); + return scoped_ptr<QuicEncryptedPacket>(encrypted.Clone()); } // Returns a newly created packet to send kData on stream 1. @@ -282,10 +284,11 @@ scoped_ptr<QuicPacket> packet( BuildUnsizedDataPacket(&framer, header, frames)); char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> encrypted(framer.EncryptPayload( - ENCRYPTION_NONE, header.packet_number, *packet, buffer, kMaxPacketSize)); - EXPECT_TRUE(encrypted != nullptr); - return scoped_ptr<QuicEncryptedPacket>(encrypted->Clone()); + size_t encrypted_size = framer.EncryptPayload( + ENCRYPTION_NONE, header.packet_number, *packet, buffer, kMaxPacketSize); + EXPECT_NE(0u, encrypted_size); + QuicEncryptedPacket encrypted(buffer, encrypted_size, false); + return scoped_ptr<QuicEncryptedPacket>(encrypted.Clone()); } void QuicTestPacketMaker::InitializeHeader(QuicPacketNumber packet_number,
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc index 44e2c83b..380a487a 100644 --- a/net/quic/test_tools/quic_test_utils.cc +++ b/net/quic/test_tools/quic_test_utils.cc
@@ -33,7 +33,7 @@ namespace test { namespace { -// No-op alarm implementation used by MockHelper. +// No-op alarm implementation used by MockConnectionHelper. class TestAlarm : public QuicAlarm { public: explicit TestAlarm(QuicAlarm::Delegate* delegate) @@ -204,23 +204,23 @@ MockConnectionVisitor::~MockConnectionVisitor() {} -MockHelper::MockHelper() {} +MockConnectionHelper::MockConnectionHelper() {} -MockHelper::~MockHelper() {} +MockConnectionHelper::~MockConnectionHelper() {} -const QuicClock* MockHelper::GetClock() const { +const QuicClock* MockConnectionHelper::GetClock() const { return &clock_; } -QuicRandom* MockHelper::GetRandomGenerator() { +QuicRandom* MockConnectionHelper::GetRandomGenerator() { return &random_generator_; } -QuicAlarm* MockHelper::CreateAlarm(QuicAlarm::Delegate* delegate) { +QuicAlarm* MockConnectionHelper::CreateAlarm(QuicAlarm::Delegate* delegate) { return new TestAlarm(delegate); } -void MockHelper::AdvanceTime(QuicTime::Delta delta) { +void MockConnectionHelper::AdvanceTime(QuicTime::Delta delta) { clock_.AdvanceTime(delta); } @@ -229,7 +229,8 @@ return new testing::NiceMock<MockPacketWriter>(); } -MockConnection::MockConnection(MockHelper* helper, Perspective perspective) +MockConnection::MockConnection(MockConnectionHelper* helper, + Perspective perspective) : MockConnection(kTestConnectionId, IPEndPoint(TestPeerIPAddress(), kTestPort), helper, @@ -237,7 +238,7 @@ QuicSupportedVersions()) {} MockConnection::MockConnection(IPEndPoint address, - MockHelper* helper, + MockConnectionHelper* helper, Perspective perspective) : MockConnection(kTestConnectionId, address, @@ -246,7 +247,7 @@ QuicSupportedVersions()) {} MockConnection::MockConnection(QuicConnectionId connection_id, - MockHelper* helper, + MockConnectionHelper* helper, Perspective perspective) : MockConnection(connection_id, IPEndPoint(TestPeerIPAddress(), kTestPort), @@ -254,7 +255,7 @@ perspective, QuicSupportedVersions()) {} -MockConnection::MockConnection(MockHelper* helper, +MockConnection::MockConnection(MockConnectionHelper* helper, Perspective perspective, const QuicVersionVector& supported_versions) : MockConnection(kTestConnectionId, @@ -265,7 +266,7 @@ MockConnection::MockConnection(QuicConnectionId connection_id, IPEndPoint address, - MockHelper* helper, + MockConnectionHelper* helper, Perspective perspective, const QuicVersionVector& supported_versions) : QuicConnection(connection_id, @@ -283,15 +284,15 @@ MockConnection::~MockConnection() {} void MockConnection::AdvanceTime(QuicTime::Delta delta) { - static_cast<MockHelper*>(helper())->AdvanceTime(delta); + static_cast<MockConnectionHelper*>(helper())->AdvanceTime(delta); } -PacketSavingConnection::PacketSavingConnection(MockHelper* helper, +PacketSavingConnection::PacketSavingConnection(MockConnectionHelper* helper, Perspective perspective) : MockConnection(helper, perspective) {} PacketSavingConnection::PacketSavingConnection( - MockHelper* helper, + MockConnectionHelper* helper, Perspective perspective, const QuicVersionVector& supported_versions) : MockConnection(helper, perspective, supported_versions) {} @@ -508,11 +509,11 @@ scoped_ptr<QuicPacket> packet( BuildUnsizedDataPacket(&framer, header, frames)); EXPECT_TRUE(packet != nullptr); - char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> encrypted(framer.EncryptPayload( - ENCRYPTION_NONE, packet_number, *packet, buffer, kMaxPacketSize)); - EXPECT_TRUE(encrypted != nullptr); - return encrypted->Clone(); + char* buffer = new char[kMaxPacketSize]; + size_t encrypted_length = framer.EncryptPayload( + ENCRYPTION_NONE, packet_number, *packet, buffer, kMaxPacketSize); + EXPECT_NE(0u, encrypted_length); + return new QuicEncryptedPacket(buffer, encrypted_length, true); } QuicEncryptedPacket* ConstructMisFramedEncryptedPacket( @@ -552,11 +553,11 @@ packet->mutable_data())[GetStartOfEncryptedData( connection_id_length, version_flag, packet_number_length)] = 0xFF; - char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> encrypted(framer.EncryptPayload( - ENCRYPTION_NONE, packet_number, *packet, buffer, kMaxPacketSize)); - EXPECT_TRUE(encrypted != nullptr); - return encrypted->Clone(); + char* buffer = new char[kMaxPacketSize]; + size_t encrypted_length = framer.EncryptPayload( + ENCRYPTION_NONE, packet_number, *packet, buffer, kMaxPacketSize); + EXPECT_NE(0u, encrypted_length); + return new QuicEncryptedPacket(buffer, encrypted_length, true); } void CompareCharArraysWithHexError( @@ -755,7 +756,7 @@ void CreateClientSessionForTest(QuicServerId server_id, bool supports_stateless_rejects, QuicTime::Delta connection_start_time, - MockHelper* helper, + MockConnectionHelper* helper, QuicCryptoClientConfig* crypto_client_config, PacketSavingConnection** client_connection, TestQuicSpdyClientSession** client_session) { @@ -778,7 +779,7 @@ void CreateServerSessionForTest(QuicServerId server_id, QuicTime::Delta connection_start_time, - MockHelper* helper, + MockConnectionHelper* helper, QuicCryptoServerConfig* server_crypto_config, PacketSavingConnection** server_connection, TestQuicSpdyServerSession** server_session) {
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h index 19cc5d6..d5fdec2 100644 --- a/net/quic/test_tools/quic_test_utils.h +++ b/net/quic/test_tools/quic_test_utils.h
@@ -294,10 +294,10 @@ DISALLOW_COPY_AND_ASSIGN(MockConnectionVisitor); }; -class MockHelper : public QuicConnectionHelperInterface { +class MockConnectionHelper : public QuicConnectionHelperInterface { public: - MockHelper(); - ~MockHelper() override; + MockConnectionHelper(); + ~MockConnectionHelper() override; const QuicClock* GetClock() const override; QuicRandom* GetRandomGenerator() override; QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override; @@ -307,7 +307,7 @@ MockClock clock_; MockRandom random_generator_; - DISALLOW_COPY_AND_ASSIGN(MockHelper); + DISALLOW_COPY_AND_ASSIGN(MockConnectionHelper); }; class NiceMockPacketWriterFactory : public QuicConnection::PacketWriterFactory { @@ -324,32 +324,33 @@ class MockConnection : public QuicConnection { public: // Uses a ConnectionId of 42 and 127.0.0.1:123. - MockConnection(MockHelper* helper, Perspective perspective); + MockConnection(MockConnectionHelper* helper, Perspective perspective); // Uses a ConnectionId of 42. MockConnection(IPEndPoint address, - MockHelper* helper, + MockConnectionHelper* helper, Perspective perspective); // Uses 127.0.0.1:123. MockConnection(QuicConnectionId connection_id, - MockHelper* helper, + MockConnectionHelper* helper, Perspective perspective); // Uses a ConnectionId of 42, and 127.0.0.1:123. - MockConnection(MockHelper* helper, + MockConnection(MockConnectionHelper* helper, Perspective perspective, const QuicVersionVector& supported_versions); MockConnection(QuicConnectionId connection_id, IPEndPoint address, - MockHelper* helper, + MockConnectionHelper* helper, Perspective perspective, const QuicVersionVector& supported_versions); ~MockConnection() override; - // If the constructor that uses a MockHelper has been used then this method + // If the constructor that uses a MockConnectionHelper has been used then + // this method // will advance the time of the MockClock. void AdvanceTime(QuicTime::Delta delta); @@ -404,9 +405,9 @@ class PacketSavingConnection : public MockConnection { public: - PacketSavingConnection(MockHelper* helper, Perspective perspective); + PacketSavingConnection(MockConnectionHelper* helper, Perspective perspective); - PacketSavingConnection(MockHelper* helper, + PacketSavingConnection(MockConnectionHelper* helper, Perspective perspective, const QuicVersionVector& supported_versions); @@ -448,6 +449,7 @@ QuicRstStreamErrorCode error, QuicStreamOffset bytes_written)); MOCK_METHOD0(IsCryptoHandshakeConfirmed, bool()); + MOCK_METHOD1(OnHeadersHeadOfLineBlocking, void(QuicTime::Delta delta)); using QuicSession::ActivateStream; @@ -730,7 +732,7 @@ // Needed for strike-register nonce verification. The client // connection_start_time should be synchronized witht the server // start time, otherwise nonce verification will fail. -// helper: Pointer to the MockHelper to use for the session. +// helper: Pointer to the MockConnectionHelper to use for the session. // crypto_client_config: Pointer to the crypto client config. // client_connection: Pointer reference for newly created // connection. This object will be owned by the @@ -740,7 +742,7 @@ void CreateClientSessionForTest(QuicServerId server_id, bool supports_stateless_rejects, QuicTime::Delta connection_start_time, - MockHelper* helper, + MockConnectionHelper* helper, QuicCryptoClientConfig* crypto_client_config, PacketSavingConnection** client_connection, TestQuicSpdyClientSession** client_session); @@ -752,7 +754,7 @@ // Needed for strike-register nonce verification. The server // connection_start_time should be synchronized witht the client // start time, otherwise nonce verification will fail. -// helper: Pointer to the MockHelper to use for the session. +// helper: Pointer to the MockConnectionHelper to use for the session. // crypto_server_config: Pointer to the crypto server config. // server_connection: Pointer reference for newly created // connection. This object will be owned by the @@ -761,7 +763,7 @@ // session. The new object will be owned by the caller. void CreateServerSessionForTest(QuicServerId server_id, QuicTime::Delta connection_start_time, - MockHelper* helper, + MockConnectionHelper* helper, QuicCryptoServerConfig* crypto_server_config, PacketSavingConnection** server_connection, TestQuicSpdyServerSession** server_session);
diff --git a/net/server/web_socket_encoder.cc b/net/server/web_socket_encoder.cc index b1b93ee..738f39d 100644 --- a/net/server/web_socket_encoder.cc +++ b/net/server/web_socket_encoder.cc
@@ -235,7 +235,7 @@ } // static -WebSocketEncoder* WebSocketEncoder::CreateClient( +scoped_ptr<WebSocketEncoder> WebSocketEncoder::CreateClient( const std::string& response_extensions) { // TODO(yhirano): Add a way to return an error. @@ -246,12 +246,12 @@ // 2) There is a malformed Sec-WebSocketExtensions header. // We should return a deflate-disabled encoder for the former case and // fail the connection for the latter case. - return new WebSocketEncoder(FOR_CLIENT, nullptr, nullptr); + return make_scoped_ptr(new WebSocketEncoder(FOR_CLIENT, nullptr, nullptr)); } if (parser.extensions().size() != 1) { // Only permessage-deflate extension is supported. // TODO (yhirano): Fail the connection. - return new WebSocketEncoder(FOR_CLIENT, nullptr, nullptr); + return make_scoped_ptr(new WebSocketEncoder(FOR_CLIENT, nullptr, nullptr)); } const auto& extension = parser.extensions()[0]; WebSocketDeflateParameters params; @@ -259,7 +259,7 @@ if (!params.Initialize(extension, &failure_message) || !params.IsValidAsResponse(&failure_message)) { // TODO (yhirano): Fail the connection. - return new WebSocketEncoder(FOR_CLIENT, nullptr, nullptr); + return make_scoped_ptr(new WebSocketEncoder(FOR_CLIENT, nullptr, nullptr)); } auto deflater = make_scoped_ptr( @@ -269,10 +269,11 @@ if (!deflater->Initialize(params.PermissiveClientMaxWindowBits()) || !inflater->Initialize(params.PermissiveServerMaxWindowBits())) { // TODO (yhirano): Fail the connection. - return new WebSocketEncoder(FOR_CLIENT, nullptr, nullptr); + return make_scoped_ptr(new WebSocketEncoder(FOR_CLIENT, nullptr, nullptr)); } - return new WebSocketEncoder(FOR_CLIENT, deflater.Pass(), inflater.Pass()); + return make_scoped_ptr( + new WebSocketEncoder(FOR_CLIENT, deflater.Pass(), inflater.Pass())); } WebSocketEncoder::WebSocketEncoder(Type type,
diff --git a/net/server/web_socket_encoder.h b/net/server/web_socket_encoder.h index 1eb749f..097df0e 100644 --- a/net/server/web_socket_encoder.h +++ b/net/server/web_socket_encoder.h
@@ -32,8 +32,8 @@ static scoped_ptr<WebSocketEncoder> CreateServer( const std::string& extensions, WebSocketDeflateParameters* params); - // TODO(yhirano): Return a scoped_ptr instead of a raw pointer. - static WebSocketEncoder* CreateClient(const std::string& response_extensions); + static scoped_ptr<WebSocketEncoder> CreateClient( + const std::string& response_extensions); WebSocket::ParseResult DecodeFrame(const base::StringPiece& frame, int* bytes_consumed,
diff --git a/net/server/web_socket_encoder_unittest.cc b/net/server/web_socket_encoder_unittest.cc index 9991bd7..b5284e77 100644 --- a/net/server/web_socket_encoder_unittest.cc +++ b/net/server/web_socket_encoder_unittest.cc
@@ -83,7 +83,7 @@ std::string response_extensions; server_ = WebSocketEncoder::CreateServer(); EXPECT_EQ(std::string(), response_extensions); - client_.reset(WebSocketEncoder::CreateClient("")); + client_ = WebSocketEncoder::CreateClient(""); } protected: @@ -103,14 +103,13 @@ EXPECT_TRUE(server_->deflate_enabled()); EXPECT_EQ("permessage-deflate; client_max_window_bits=15", params.AsExtension().ToString()); - client_.reset( - WebSocketEncoder::CreateClient(params.AsExtension().ToString())); + client_ = WebSocketEncoder::CreateClient(params.AsExtension().ToString()); } }; TEST_F(WebSocketEncoderTest, DeflateDisabledEncoder) { - scoped_ptr<WebSocketEncoder> server(WebSocketEncoder::CreateServer()); - scoped_ptr<WebSocketEncoder> client(WebSocketEncoder::CreateClient("")); + scoped_ptr<WebSocketEncoder> server = WebSocketEncoder::CreateServer(); + scoped_ptr<WebSocketEncoder> client = WebSocketEncoder::CreateClient(""); ASSERT_TRUE(server); ASSERT_TRUE(client);
diff --git a/net/spdy/buffered_spdy_framer.cc b/net/spdy/buffered_spdy_framer.cc index fdd2653..c5c33d5c 100644 --- a/net/spdy/buffered_spdy_framer.cc +++ b/net/spdy/buffered_spdy_framer.cc
@@ -202,6 +202,16 @@ visitor_->OnStreamPadding(stream_id, len); } +SpdyHeadersHandlerInterface* BufferedSpdyFramer::OnHeaderFrameStart( + SpdyStreamId stream_id) { + return visitor_->OnHeaderFrameStart(stream_id); +} + +void BufferedSpdyFramer::OnHeaderFrameEnd(SpdyStreamId stream_id, + bool end_headers) { + visitor_->OnHeaderFrameEnd(stream_id, end_headers); +} + void BufferedSpdyFramer::OnSettings(bool clear_persisted) { visitor_->OnSettings(clear_persisted); }
diff --git a/net/spdy/buffered_spdy_framer.h b/net/spdy/buffered_spdy_framer.h index 46cda47..0576f416 100644 --- a/net/spdy/buffered_spdy_framer.h +++ b/net/spdy/buffered_spdy_framer.h
@@ -77,6 +77,20 @@ // |len| The number of padding octets. virtual void OnStreamPadding(SpdyStreamId stream_id, size_t len) = 0; + // Called just before processing the payload of a frame containing header + // data. Should return an implementation of SpdyHeadersHandlerInterface that + // will receive headers for stream |stream_id|. The caller will not take + // ownership of the headers handler. The same instance should be returned + // for all header frames comprising a logical header block (i.e. until + // OnHeaderFrameEnd() is called with end_headers == true). + virtual SpdyHeadersHandlerInterface* OnHeaderFrameStart( + SpdyStreamId stream_id) = 0; + + // Called after processing the payload of a frame containing header data. + // |end_headers| is true if there will not be any subsequent CONTINUATION + // frames. + virtual void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) = 0; + // Called when a SETTINGS frame is received. // |clear_persisted| True if the respective flag is set on the SETTINGS frame. virtual void OnSettings(bool clear_persisted) = 0; @@ -166,6 +180,9 @@ size_t len, bool fin) override; void OnStreamPadding(SpdyStreamId stream_id, size_t len) override; + SpdyHeadersHandlerInterface* OnHeaderFrameStart( + SpdyStreamId stream_id) override; + void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) override; void OnSettings(bool clear_persisted) override; void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override; void OnSettingsAck() override;
diff --git a/net/spdy/buffered_spdy_framer_unittest.cc b/net/spdy/buffered_spdy_framer_unittest.cc index 852247eb..8510db7 100644 --- a/net/spdy/buffered_spdy_framer_unittest.cc +++ b/net/spdy/buffered_spdy_framer_unittest.cc
@@ -88,6 +88,16 @@ LOG(FATAL) << "Unexpected OnStreamPadding call."; } + SpdyHeadersHandlerInterface* OnHeaderFrameStart( + SpdyStreamId stream_id) override { + LOG(FATAL) << "Unexpected OnHeaderFrameStart call."; + return nullptr; + } + + void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) override { + LOG(FATAL) << "Unexpected OnHeaderFrameEnd call."; + } + void OnSettings(bool clear_persisted) override {} void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
diff --git a/net/spdy/mock_spdy_framer_visitor.h b/net/spdy/mock_spdy_framer_visitor.h index 83eacc5..2c08392 100644 --- a/net/spdy/mock_spdy_framer_visitor.h +++ b/net/spdy/mock_spdy_framer_visitor.h
@@ -26,6 +26,9 @@ size_t len, bool fin)); MOCK_METHOD2(OnStreamPadding, void(SpdyStreamId stream_id, size_t len)); + MOCK_METHOD1(OnHeaderFrameStart, + SpdyHeadersHandlerInterface*(SpdyStreamId stream_id)); + MOCK_METHOD2(OnHeaderFrameEnd, void(SpdyStreamId stream_id, bool end)); MOCK_METHOD3(OnControlFrameHeaderData, bool(SpdyStreamId stream_id, const char* header_data, size_t len));
diff --git a/net/spdy/spdy_framer.h b/net/spdy/spdy_framer.h index 3b345094..976a364 100644 --- a/net/spdy/spdy_framer.h +++ b/net/spdy/spdy_framer.h
@@ -125,6 +125,20 @@ // |len| The number of padding octets. virtual void OnStreamPadding(SpdyStreamId stream_id, size_t len) = 0; + // Called just before processing the payload of a frame containing header + // data. Should return an implementation of SpdyHeadersHandlerInterface that + // will receive headers for stream |stream_id|. The caller will not take + // ownership of the headers handler. The same instance should be returned + // for all header frames comprising a logical header block (i.e. until + // OnHeaderFrameEnd() is called with end_headers == true). + virtual SpdyHeadersHandlerInterface* OnHeaderFrameStart( + SpdyStreamId stream_id) = 0; + + // Called after processing the payload of a frame containing header data. + // |end_headers| is true if there will not be any subsequent CONTINUATION + // frames. + virtual void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) = 0; + // Called when a chunk of header data is available. This is called // after OnSynStream, OnSynReply, OnHeaders(), or OnPushPromise. // |stream_id| The stream receiving the header data.
diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc index 749d975..70a1122 100644 --- a/net/spdy/spdy_framer_test.cc +++ b/net/spdy/spdy_framer_test.cc
@@ -99,6 +99,16 @@ LOG(FATAL); } + SpdyHeadersHandlerInterface* OnHeaderFrameStart( + SpdyStreamId stream_id) override { + LOG(FATAL); + return nullptr; + } + + void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) override { + LOG(FATAL); + } + bool OnControlFrameHeaderData(SpdyStreamId stream_id, const char* header_data, size_t len) override { @@ -319,6 +329,16 @@ LOG(INFO) << "OnStreamPadding(" << stream_id << ", " << len << ")\n"; } + SpdyHeadersHandlerInterface* OnHeaderFrameStart( + SpdyStreamId stream_id) override { + LOG(FATAL); + return nullptr; + } + + void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) override { + LOG(FATAL); + } + bool OnControlFrameHeaderData(SpdyStreamId stream_id, const char* header_data, size_t len) override {
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index 13f0d86..80e24c6 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc
@@ -2120,6 +2120,16 @@ it->second.stream->OnPaddingConsumed(len); } +SpdyHeadersHandlerInterface* SpdySession::OnHeaderFrameStart( + SpdyStreamId stream_id) { + LOG(FATAL); + return nullptr; +} + +void SpdySession::OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) { + LOG(FATAL); +} + void SpdySession::OnSettings(bool clear_persisted) { CHECK(in_io_loop_);
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index 3d0c857..3ad5d27 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h
@@ -831,6 +831,9 @@ size_t len, bool fin) override; void OnStreamPadding(SpdyStreamId stream_id, size_t len) override; + SpdyHeadersHandlerInterface* OnHeaderFrameStart( + SpdyStreamId stream_id) override; + void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) override; void OnSettings(bool clear_persisted) override; void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override; void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override;
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc index 4cc450e..d442a47 100644 --- a/net/spdy/spdy_test_util_common.cc +++ b/net/spdy/spdy_test_util_common.cc
@@ -248,6 +248,11 @@ size_t len, bool fin) override {} void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {} + SpdyHeadersHandlerInterface* OnHeaderFrameStart( + SpdyStreamId stream_id) override { + return nullptr; + } + void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) override {} void OnSettings(bool clear_persisted) override {} void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {} void OnPing(SpdyPingId unique_id, bool is_ack) override {}
diff --git a/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServer.java b/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServer.java index 2eab2798..841a3e5 100644 --- a/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServer.java +++ b/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServer.java
@@ -16,7 +16,7 @@ * EmbeddedTestServer s = new EmbeddedTestServer(); * s.initializeNative(); * s.serveFilesFromDirectory("/path/to/my/directory"); - * if (!s.initializeAndWaitUntilReady()) { + * if (!s.start()) { * throw new SomeKindOfException("Unable to initialize EmbeddedTestServer."); * } * @@ -54,15 +54,26 @@ nativeServeFilesFromDirectory(mNativeEmbeddedTestServer, directoryPath); } - /** Initialize the server. + // TODO(svaldez): Remove once all consumers have switched to start(). + /** Wrapper for start() + * + * start() should be used instead of this. + * + * @return Whether the server was successfully initialized. + */ + public boolean initializeAndWaitUntilReady() { + return start(); + } + + /** Starts the server. * * Note that this should be called after handlers are set up, including any relevant calls * serveFilesFromDirectory. * * @return Whether the server was successfully initialized. */ - public boolean initializeAndWaitUntilReady() { - return nativeInitializeAndWaitUntilReady(mNativeEmbeddedTestServer); + public boolean start() { + return nativeStart(mNativeEmbeddedTestServer); } /** Get the full URL for the given relative URL. @@ -103,7 +114,7 @@ private native void nativeInit(); private native void nativeDestroy(long nativeEmbeddedTestServerAndroid); - private native boolean nativeInitializeAndWaitUntilReady(long nativeEmbeddedTestServerAndroid); + private native boolean nativeStart(long nativeEmbeddedTestServerAndroid); private native boolean nativeShutdownAndWaitUntilComplete(long nativeEmbeddedTestServerAndroid); private native String nativeGetURL(long nativeEmbeddedTestServerAndroid, String relativeUrl); private native void nativeServeFilesFromDirectory(
diff --git a/net/test/embedded_test_server/android/embedded_test_server_android.cc b/net/test/embedded_test_server/android/embedded_test_server_android.cc index 9ba3886..86ef5bd 100644 --- a/net/test/embedded_test_server/android/embedded_test_server_android.cc +++ b/net/test/embedded_test_server/android/embedded_test_server_android.cc
@@ -25,9 +25,8 @@ Java_EmbeddedTestServer_clearNativePtr(env, weak_java_server_.get(env).obj()); } -jboolean EmbeddedTestServerAndroid::InitializeAndWaitUntilReady(JNIEnv* env, - jobject jobj) { - return test_server_.InitializeAndWaitUntilReady(); +jboolean EmbeddedTestServerAndroid::Start(JNIEnv* env, jobject jobj) { + return test_server_.Start(); } jboolean EmbeddedTestServerAndroid::ShutdownAndWaitUntilComplete(JNIEnv* env,
diff --git a/net/test/embedded_test_server/android/embedded_test_server_android.h b/net/test/embedded_test_server/android/embedded_test_server_android.h index fb03e37a..1c5002f5 100644 --- a/net/test/embedded_test_server/android/embedded_test_server_android.h +++ b/net/test/embedded_test_server/android/embedded_test_server_android.h
@@ -24,7 +24,7 @@ void Destroy(JNIEnv* env, jobject obj); - jboolean InitializeAndWaitUntilReady(JNIEnv* env, jobject jobj); + jboolean Start(JNIEnv* env, jobject jobj); jboolean ShutdownAndWaitUntilComplete(JNIEnv* env, jobject jobj);
diff --git a/net/tools/flip_server/spdy_interface.cc b/net/tools/flip_server/spdy_interface.cc index fb5d290..d21b500 100644 --- a/net/tools/flip_server/spdy_interface.cc +++ b/net/tools/flip_server/spdy_interface.cc
@@ -244,6 +244,18 @@ << ", [" << len << "])"; } +SpdyHeadersHandlerInterface* SpdySM::OnHeaderFrameStart( + SpdyStreamId stream_id) { + LOG(FATAL) << ACCEPTOR_CLIENT_IDENT + << "SpdySM::OnHeaderFrameStart() not implemented."; + return nullptr; +} + +void SpdySM::OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) { + LOG(FATAL) << ACCEPTOR_CLIENT_IDENT + << "SpdySM::OnHeaderFrameEnd() not implemented."; +} + void SpdySM::OnSynStream(SpdyStreamId stream_id, SpdyStreamId associated_stream_id, SpdyPriority priority,
diff --git a/net/tools/flip_server/spdy_interface.h b/net/tools/flip_server/spdy_interface.h index 45d1885e1..e9918a83 100644 --- a/net/tools/flip_server/spdy_interface.h +++ b/net/tools/flip_server/spdy_interface.h
@@ -109,6 +109,20 @@ // |len| The number of padding octets. void OnStreamPadding(SpdyStreamId stream_id, size_t len) override; + // Called just before processing the payload of a frame containing header + // data. Should return an implementation of SpdyHeadersHandlerInterface that + // will receive headers for stream |stream_id|. The caller will not take + // ownership of the headers handler. The same instance should be returned + // for all header frames comprising a logical header block (i.e. until + // OnHeaderFrameEnd() is called with end_headers == true). + SpdyHeadersHandlerInterface* OnHeaderFrameStart( + SpdyStreamId stream_id) override; + + // Called after processing the payload of a frame containing header data. + // |end_headers| is true if there will not be any subsequent CONTINUATION + // frames. + void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) override; + // Called when a SETTINGS frame is received. // |clear_persisted| True if the respective flag is set on the SETTINGS frame. void OnSettings(bool clear_persisted) override {}
diff --git a/net/tools/flip_server/spdy_interface_test.cc b/net/tools/flip_server/spdy_interface_test.cc index d47a8725..1732426 100644 --- a/net/tools/flip_server/spdy_interface_test.cc +++ b/net/tools/flip_server/spdy_interface_test.cc
@@ -67,6 +67,10 @@ size_t, bool)); MOCK_METHOD2(OnStreamPadding, void(SpdyStreamId, size_t)); + MOCK_METHOD1(OnHeaderFrameStart, + SpdyHeadersHandlerInterface*(SpdyStreamId stream_id)); + MOCK_METHOD2(OnHeaderFrameEnd, + void(SpdyStreamId stream_id, bool end_headers)); MOCK_METHOD1(OnSettings, void(bool clear_persisted)); MOCK_METHOD3(OnSetting, void(SpdySettingsIds, uint8, uint32)); MOCK_METHOD2(OnPing, void(SpdyPingId unique_id, bool is_ack));
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc index b99cf1e..0d82d6d 100644 --- a/net/tools/quic/end_to_end_test.cc +++ b/net/tools/quic/end_to_end_test.cc
@@ -211,18 +211,12 @@ class ServerDelegate : public PacketDroppingTestWriter::Delegate { public: - ServerDelegate(TestWriterFactory* writer_factory, - QuicDispatcher* dispatcher) - : writer_factory_(writer_factory), - dispatcher_(dispatcher) {} + explicit ServerDelegate(QuicDispatcher* dispatcher) + : dispatcher_(dispatcher) {} ~ServerDelegate() override {} - void OnPacketSent(WriteResult result) override { - writer_factory_->OnPacketSent(result); - } void OnCanWrite() override { dispatcher_->OnCanWrite(); } private: - TestWriterFactory* writer_factory_; QuicDispatcher* dispatcher_; }; @@ -230,7 +224,6 @@ public: explicit ClientDelegate(QuicClient* client) : client_(client) {} ~ClientDelegate() override {} - void OnPacketSent(WriteResult /*result*/) override {} void OnCanWrite() override { EpollEvent event(EPOLLOUT, false); client_->OnEvent(client_->fd(), &event); @@ -400,19 +393,11 @@ packet_writer_factory); QuicDispatcherPeer::UseWriter(dispatcher, server_writer_); - if (GetParam().server_uses_stateless_rejects_if_peer_supported) { - // Enable stateless rejects and force the server to always send - // them. - FLAGS_enable_quic_stateless_reject_support = true; - FLAGS_quic_session_map_threshold_for_stateless_rejects = 0; - } else { - FLAGS_enable_quic_stateless_reject_support = false; - FLAGS_quic_session_map_threshold_for_stateless_rejects = -1; - } + FLAGS_enable_quic_stateless_reject_support = + GetParam().server_uses_stateless_rejects_if_peer_supported; - server_writer_->Initialize( - QuicDispatcherPeer::GetHelper(dispatcher), - new ServerDelegate(packet_writer_factory, dispatcher)); + server_writer_->Initialize(QuicDispatcherPeer::GetHelper(dispatcher), + new ServerDelegate(dispatcher)); if (stream_factory_ != nullptr) { static_cast<QuicTestServer*>(server_thread_->server()) ->SetSpdyStreamFactory(stream_factory_); @@ -474,7 +459,11 @@ // EXPECT_EQ(0u, client_stats.packets_lost); // } EXPECT_EQ(0u, client_stats.packets_discarded); - EXPECT_EQ(0u, client_stats.packets_dropped); + // When doing 0-RTT with stateless rejects, the encrypted requests cause + // a retranmission of the SREJ packets which are dropped by the client. + if (!BothSidesSupportStatelessRejects()) { + EXPECT_EQ(0u, client_stats.packets_dropped); + } EXPECT_EQ(client_stats.packets_received, client_stats.packets_processed); const int num_expected_stateless_rejects = @@ -926,22 +915,9 @@ TEST_P(EndToEndTest, StatelessRejectWithPacketLoss) { // In this test, we intentionally drop the first packet from the // server, which corresponds with the initial REJ/SREJ response from - // the server. The REJ case will succeed, due to redundancy in the - // stateful handshake. The SREJ will fail, because there is - // (currently) no way to recover from a loss of the first SREJ, and - // all remaining state for the first handshake is black-holed on the - // time-wait list. - // TODO(jokulik): Once redundant SREJ support is added, this test - // should succeed. + // the server. server_writer_->set_fake_drop_first_n_packets(1); - // If this test will involve version negotiation then the version - // negotiation packet will be dropped, not the SREJ, and since the - // version negotiation packet will be retransmitted the test will - // succeed. - const bool will_succeed = - !BothSidesSupportStatelessRejects() || - negotiated_version_ != client_supported_versions_.front(); - ASSERT_EQ(will_succeed, Initialize()); + ASSERT_TRUE(Initialize()); } TEST_P(EndToEndTest, SetInitialReceivedConnectionOptions) { @@ -1073,7 +1049,8 @@ client_->SendCustomSynchronousRequest(request); // EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error()); - EXPECT_EQ(QUIC_PACKET_FOR_NONEXISTENT_STREAM, client_->connection_error()); + EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error()); + EXPECT_EQ(QUIC_INVALID_STREAM_ID, client_->connection_error()); } // TODO(rch): this test seems to cause net_unittests timeouts :| @@ -1721,7 +1698,7 @@ EXPECT_EQ(200u, client_->response_headers()->parsed_response_code()); // Send another request to flush out any pending ACKs on the server. - client_->SendSynchronousRequest(request_string); + client_->SendSynchronousRequest("/bar"); // Pause the server to avoid races. server_thread_->Pause();
diff --git a/net/tools/quic/quic_client_session.cc b/net/tools/quic/quic_client_session.cc index 1ee8322..edba8eda 100644 --- a/net/tools/quic/quic_client_session.cc +++ b/net/tools/quic/quic_client_session.cc
@@ -20,17 +20,18 @@ const QuicServerId& server_id, QuicCryptoClientConfig* crypto_config) : QuicClientSessionBase(connection, config), - crypto_stream_(new QuicCryptoClientStream( - server_id, - this, - new ProofVerifyContextChromium(0, BoundNetLog()), - crypto_config)), - respect_goaway_(true) { -} + server_id_(server_id), + crypto_config_(crypto_config), + respect_goaway_(true) {} QuicClientSession::~QuicClientSession() { } +void QuicClientSession::Initialize() { + crypto_stream_.reset(CreateQuicCryptoStream()); + QuicClientSessionBase::Initialize(); +} + void QuicClientSession::OnProofValid( const QuicCryptoClientConfig::CachedState& /*cached*/) {} @@ -61,7 +62,7 @@ return new QuicSpdyClientStream(GetNextOutgoingStreamId(), this); } -QuicCryptoClientStream* QuicClientSession::GetCryptoStream() { +QuicCryptoClientStreamBase* QuicClientSession::GetCryptoStream() { return crypto_stream_.get(); } @@ -80,5 +81,12 @@ return nullptr; } +QuicCryptoClientStreamBase* QuicClientSession::CreateQuicCryptoStream() { + return new QuicCryptoClientStream( + server_id_, this, new ProofVerifyContextChromium(0, BoundNetLog()), + crypto_config_); +} + } // namespace tools + } // namespace net
diff --git a/net/tools/quic/quic_client_session.h b/net/tools/quic/quic_client_session.h index 2f180d73..e04d1439 100644 --- a/net/tools/quic/quic_client_session.h +++ b/net/tools/quic/quic_client_session.h
@@ -30,10 +30,12 @@ const QuicServerId& server_id, QuicCryptoClientConfig* crypto_config); ~QuicClientSession() override; + // Set up the QuicClientSession. Must be called prior to use. + void Initialize() override; // QuicSession methods: QuicSpdyClientStream* CreateOutgoingDynamicStream() override; - QuicCryptoClientStream* GetCryptoStream() override; + QuicCryptoClientStreamBase* GetCryptoStream() override; // QuicClientSessionBase methods: void OnProofValid(const QuicCryptoClientConfig::CachedState& cached) override; @@ -56,14 +58,22 @@ // QuicSession methods: QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override; + // Create the crypto stream. Called by Initialize() + virtual QuicCryptoClientStreamBase* CreateQuicCryptoStream(); + // Unlike CreateOutgoingDynamicStream, which applies a bunch of sanity checks, // this simply returns a new QuicSpdyClientStream. This may be used by // subclasses which want to use a subclass of QuicSpdyClientStream for streams // but wish to use the sanity checks in CreateOutgoingDynamicStream. virtual QuicSpdyClientStream* CreateClientStream(); + const QuicServerId& server_id() { return server_id_; } + QuicCryptoClientConfig* crypto_config() { return crypto_config_; } + private: - scoped_ptr<QuicCryptoClientStream> crypto_stream_; + scoped_ptr<QuicCryptoClientStreamBase> crypto_stream_; + QuicServerId server_id_; + QuicCryptoClientConfig* crypto_config_; // If this is set to false, the client will ignore server GOAWAYs and allow // the creation of streams regardless of the high chance they will fail.
diff --git a/net/tools/quic/quic_client_session_test.cc b/net/tools/quic/quic_client_session_test.cc index 541f290..7ae923bf 100644 --- a/net/tools/quic/quic_client_session_test.cc +++ b/net/tools/quic/quic_client_session_test.cc
@@ -20,7 +20,7 @@ using net::test::CryptoTestUtils; using net::test::DefaultQuicConfig; using net::test::MockConnection; -using net::test::MockHelper; +using net::test::MockConnectionHelper; using net::test::PacketSavingConnection; using net::test::QuicSpdySessionPeer; using net::test::SupportedVersions; @@ -60,12 +60,13 @@ void CompleteCryptoHandshake() { session_->CryptoConnect(); - CryptoTestUtils::HandshakeWithFakeServer(&helper_, connection_, - session_->GetCryptoStream()); + QuicCryptoClientStream* stream = + static_cast<QuicCryptoClientStream*>(session_->GetCryptoStream()); + CryptoTestUtils::HandshakeWithFakeServer(&helper_, connection_, stream); } QuicCryptoClientConfig crypto_config_; - MockHelper helper_; + MockConnectionHelper helper_; PacketSavingConnection* connection_; scoped_ptr<QuicClientSession> session_; };
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc index 47d47fff..bb4bd88 100644 --- a/net/tools/quic/quic_dispatcher.cc +++ b/net/tools/quic/quic_dispatcher.cc
@@ -21,12 +21,6 @@ using std::make_pair; using base::StringPiece; -// The threshold size for the session map, over which the dispatcher will start -// sending stateless rejects (SREJ), rather than stateful rejects (REJ) to -// clients who support them. If -1, stateless rejects will not be sent. If 0, -// the server will only send stateless rejects to clients who support them. -int32 FLAGS_quic_session_map_threshold_for_stateless_rejects = -1; - namespace { // An alarm that informs the QuicDispatcher to delete old sessions. @@ -209,7 +203,7 @@ current_packet_ = &packet; // ProcessPacket will cause the packet to be dispatched in // OnUnauthenticatedPublicHeader, or sent to the time wait list manager - // in OnAuthenticatedHeader. + // in OnUnauthenticatedHeader. framer_.ProcessPacket(packet); // TODO(rjshade): Return a status describing if/why a packet was dropped, // and log somehow. Maybe expose as a varz. @@ -359,13 +353,15 @@ void QuicDispatcher::CleanUpSession(SessionMap::iterator it, bool should_close_statelessly) { QuicConnection* connection = it->second->connection(); - QuicEncryptedPacket* connection_close_packet = - connection->ReleaseConnectionClosePacket(); + write_blocked_list_.erase(connection); - DCHECK(!should_close_statelessly || !connection_close_packet); + if (should_close_statelessly) { + DCHECK(connection->termination_packets() != nullptr && + !connection->termination_packets()->empty()); + } time_wait_list_manager_->AddConnectionIdToTimeWait( it->first, connection->version(), should_close_statelessly, - connection_close_packet); + connection->termination_packets()); session_map_.erase(it); } @@ -460,12 +456,6 @@ QuicServerSession* session = new QuicServerSession(config_, connection, this, crypto_config_); session->Initialize(); - if (FLAGS_quic_session_map_threshold_for_stateless_rejects != -1 && - session_map_.size() >= - static_cast<size_t>( - FLAGS_quic_session_map_threshold_for_stateless_rejects)) { - session->set_use_stateless_rejects_if_peer_supported(true); - } return session; }
diff --git a/net/tools/quic/quic_dispatcher.h b/net/tools/quic/quic_dispatcher.h index 624dcf9..49a6d6d2 100644 --- a/net/tools/quic/quic_dispatcher.h +++ b/net/tools/quic/quic_dispatcher.h
@@ -33,8 +33,6 @@ class QuicDispatcherPeer; } // namespace test -extern int32 FLAGS_quic_session_map_threshold_for_stateless_rejects; - class ProcessPacketInterface { public: virtual ~ProcessPacketInterface() {}
diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc index b54ee290..efe6acca0c 100644 --- a/net/tools/quic/quic_dispatcher_test.cc +++ b/net/tools/quic/quic_dispatcher_test.cc
@@ -31,7 +31,7 @@ using net::test::ConstructEncryptedPacket; using net::test::CryptoTestUtils; using net::test::MockConnection; -using net::test::MockHelper; +using net::test::MockConnectionHelper; using net::test::ValueRestore; using net::test::TestWriterFactory; using std::string; @@ -98,7 +98,7 @@ class MockServerConnection : public MockConnection { public: MockServerConnection(QuicConnectionId connection_id, - MockHelper* helper, + MockConnectionHelper* helper, QuicDispatcher* dispatcher) : MockConnection(connection_id, helper, Perspective::IS_SERVER), dispatcher_(dispatcher) {} @@ -116,7 +116,7 @@ const QuicConfig& config, QuicConnectionId connection_id, const IPEndPoint& client_address, - MockHelper* helper, + MockConnectionHelper* helper, const QuicCryptoServerConfig* crypto_config, TestQuicSpdyServerSession** session) { MockServerConnection* connection = @@ -203,7 +203,7 @@ EpollServer eps_; QuicEpollConnectionHelper helper_; - MockHelper mock_helper_; + MockConnectionHelper mock_helper_; QuicConfig config_; QuicCryptoServerConfig crypto_config_; IPEndPoint server_address_; @@ -328,12 +328,9 @@ struct StatelessRejectTestParams { StatelessRejectTestParams(bool enable_stateless_rejects_via_flag, - bool use_stateless_rejects_if_peer_supported, bool client_supports_statelesss_rejects, bool crypto_handshake_successful) : enable_stateless_rejects_via_flag(enable_stateless_rejects_via_flag), - use_stateless_rejects_if_peer_supported( - use_stateless_rejects_if_peer_supported), client_supports_statelesss_rejects(client_supports_statelesss_rejects), crypto_handshake_successful(crypto_handshake_successful) {} @@ -341,8 +338,6 @@ const StatelessRejectTestParams& p) { os << " enable_stateless_rejects_via_flag: " << p.enable_stateless_rejects_via_flag << std::endl; - os << "{ use_stateless_rejects_if_peer_supported: " - << p.use_stateless_rejects_if_peer_supported << std::endl; os << "{ client_supports_statelesss_rejects: " << p.client_supports_statelesss_rejects << std::endl; os << " crypto_handshake_successful: " << p.crypto_handshake_successful @@ -351,12 +346,8 @@ } // This only enables the stateless reject feature via the feature-flag. - // It does not force the crypto server to emit stateless rejects. + // This should be a no-op if the peer does not support them. bool enable_stateless_rejects_via_flag; - // If true, this forces the server to send a stateless reject when rejecting - // messages. This should be a no-op if enable_stateless_rejects_via_flag is - // false or the peer does not support them. - bool use_stateless_rejects_if_peer_supported; // Whether or not the client supports stateless rejects. bool client_supports_statelesss_rejects; // Should the initial crypto handshake succeed or not. @@ -367,14 +358,11 @@ vector<StatelessRejectTestParams> GetStatelessRejectTestParams() { vector<StatelessRejectTestParams> params; for (bool enable_stateless_rejects_via_flag : {true, false}) { - for (bool use_stateless_rejects_if_peer_supported : {true, false}) { - for (bool client_supports_statelesss_rejects : {true, false}) { - for (bool crypto_handshake_successful : {true, false}) { - params.push_back(StatelessRejectTestParams( - enable_stateless_rejects_via_flag, - use_stateless_rejects_if_peer_supported, - client_supports_statelesss_rejects, crypto_handshake_successful)); - } + for (bool client_supports_statelesss_rejects : {true, false}) { + for (bool crypto_handshake_successful : {true, false}) { + params.push_back(StatelessRejectTestParams( + enable_stateless_rejects_via_flag, + client_supports_statelesss_rejects, crypto_handshake_successful)); } } } @@ -404,7 +392,6 @@ // a stateless reject, depending upon the parameters of the test. bool ExpectStatelessReject() { return GetParam().enable_stateless_rejects_via_flag && - GetParam().use_stateless_rejects_if_peer_supported && !GetParam().crypto_handshake_successful && GetParam().client_supports_statelesss_rejects; } @@ -419,8 +406,6 @@ crypto_stream1_ = new MockQuicCryptoServerStream(crypto_config_, session1_); session1_->SetCryptoStream(crypto_stream1_); - crypto_stream1_->set_use_stateless_rejects_if_peer_supported( - GetParam().use_stateless_rejects_if_peer_supported); crypto_stream1_->set_handshake_confirmed_for_testing( GetParam().crypto_handshake_successful); crypto_stream1_->set_peer_supports_stateless_rejects( @@ -624,7 +609,7 @@ } protected: - MockHelper helper_; + MockConnectionHelper helper_; BlockingWriter* writer_; QuicDispatcher::WriteBlockedList* blocked_list_; };
diff --git a/net/tools/quic/quic_epoll_clock.cc b/net/tools/quic/quic_epoll_clock.cc index 450afb8..62cb6bd 100644 --- a/net/tools/quic/quic_epoll_clock.cc +++ b/net/tools/quic/quic_epoll_clock.cc
@@ -25,5 +25,10 @@ QuicTime::Delta::FromMicroseconds(epoll_server_->NowInUsec())); } +QuicWallTime QuicEpollClock::WallNow() const { + return QuicWallTime::FromUNIXMicroseconds( + epoll_server_->ApproximateNowInUsec()); +} + } // namespace tools } // namespace net
diff --git a/net/tools/quic/quic_epoll_clock.h b/net/tools/quic/quic_epoll_clock.h index c5a1390..b5eafc8 100644 --- a/net/tools/quic/quic_epoll_clock.h +++ b/net/tools/quic/quic_epoll_clock.h
@@ -27,9 +27,13 @@ QuicTime ApproximateNow() const override; // Returns the current time as a QuicTime object. - // Note: this use significant resources please use only if needed. + // Note: this uses significant resources, please use only if needed. QuicTime Now() const override; + // Returns the current time as a QuicWallTime object. + // Note: this uses significant resources, please use only if needed. + QuicWallTime WallNow() const override; + protected: EpollServer* epoll_server_;
diff --git a/net/tools/quic/quic_epoll_clock_test.cc b/net/tools/quic/quic_epoll_clock_test.cc index 1ed1d15..6fe7c0e 100644 --- a/net/tools/quic/quic_epoll_clock_test.cc +++ b/net/tools/quic/quic_epoll_clock_test.cc
@@ -18,10 +18,18 @@ epoll_server.set_now_in_usec(1000000); EXPECT_EQ(1000000, clock.ApproximateNow().Subtract(QuicTime::Zero()).ToMicroseconds()); + EXPECT_EQ(1u, clock.WallNow().ToUNIXSeconds()); + EXPECT_EQ(1000000u, clock.WallNow().ToUNIXMicroseconds()); epoll_server.AdvanceBy(5); EXPECT_EQ(1000005, clock.ApproximateNow().Subtract(QuicTime::Zero()).ToMicroseconds()); + EXPECT_EQ(1u, clock.WallNow().ToUNIXSeconds()); + EXPECT_EQ(1000005u, clock.WallNow().ToUNIXMicroseconds()); + + epoll_server.AdvanceBy(10 * 1000000); + EXPECT_EQ(11u, clock.WallNow().ToUNIXSeconds()); + EXPECT_EQ(11000005u, clock.WallNow().ToUNIXMicroseconds()); } TEST(QuicEpollClockTest, NowInUsec) { @@ -37,21 +45,6 @@ clock.Now().Subtract(QuicTime::Zero()).ToMicroseconds()); } -TEST(QuicEpollClockTest, WallNow) { - MockEpollServer epoll_server; - QuicEpollClock clock(&epoll_server); - - base::Time start = base::Time::Now(); - QuicWallTime now = clock.WallNow(); - base::Time end = base::Time::Now(); - - // If end > start, then we can check now is between start and end. - if (end > start) { - EXPECT_LE(static_cast<uint64>(start.ToTimeT()), now.ToUNIXSeconds()); - EXPECT_LE(now.ToUNIXSeconds(), static_cast<uint64>(end.ToTimeT())); - } -} - } // namespace test } // namespace tools } // namespace net
diff --git a/net/tools/quic/quic_server_bin.cc b/net/tools/quic/quic_server_bin.cc index 0102a81..7678eeb 100644 --- a/net/tools/quic/quic_server_bin.cc +++ b/net/tools/quic/quic_server_bin.cc
@@ -25,7 +25,7 @@ net::ProofSource* CreateProofSource(const base::FilePath& cert_path, const base::FilePath& key_path) { net::ProofSourceChromium* proof_source = new net::ProofSourceChromium(); - CHECK(proof_source->Initialize(cert_path, key_path)); + CHECK(proof_source->Initialize(cert_path, key_path, base::FilePath())); return proof_source; }
diff --git a/net/tools/quic/quic_server_session.h b/net/tools/quic/quic_server_session.h index 144912d..654d1ce8 100644 --- a/net/tools/quic/quic_server_session.h +++ b/net/tools/quic/quic_server_session.h
@@ -95,13 +95,6 @@ serving_region_ = serving_region; } - void set_use_stateless_rejects_if_peer_supported( - bool use_stateless_rejects_if_peer_supported) { - DCHECK(GetCryptoStream() != nullptr); - GetCryptoStream()->set_use_stateless_rejects_if_peer_supported( - use_stateless_rejects_if_peer_supported); - } - protected: // QuicSession methods: QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override;
diff --git a/net/tools/quic/quic_server_session_test.cc b/net/tools/quic/quic_server_session_test.cc index a8aa4347..2b1b961 100644 --- a/net/tools/quic/quic_server_session_test.cc +++ b/net/tools/quic/quic_server_session_test.cc
@@ -29,7 +29,7 @@ using __gnu_cxx::vector; using net::test::CryptoTestUtils; using net::test::MockConnection; -using net::test::MockHelper; +using net::test::MockConnectionHelper; using net::test::QuicConfigPeer; using net::test::QuicConnectionPeer; using net::test::QuicSpdyStreamPeer; @@ -54,9 +54,9 @@ class QuicServerSessionPeer { public: - static ReliableQuicStream* GetIncomingDynamicStream(QuicServerSession* s, + static ReliableQuicStream* GetOrCreateDynamicStream(QuicServerSession* s, QuicStreamId id) { - return s->GetIncomingDynamicStream(id); + return s->GetOrCreateDynamicStream(id); } static void SetCryptoStream(QuicServerSession* s, QuicCryptoServerStream* crypto_stream) { @@ -98,7 +98,7 @@ } StrictMock<MockQuicServerSessionVisitor> owner_; - MockHelper helper_; + MockConnectionHelper helper_; StrictMock<MockConnection>* connection_; QuicConfig config_; QuicCryptoServerConfig crypto_config_; @@ -134,7 +134,8 @@ EXPECT_EQ(1u, session_->GetNumOpenStreams()); // Send a reset (and expect the peer to send a RST in response). - QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_STREAM_NO_ERROR, 0); + QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, + 0); EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0)); visitor_->OnRstStream(rst1); @@ -150,7 +151,8 @@ TEST_P(QuicServerSessionTest, NeverOpenStreamDueToReset) { // Send a reset (and expect the peer to send a RST in response). - QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_STREAM_NO_ERROR, 0); + QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, + 0); EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0)); visitor_->OnRstStream(rst1); @@ -176,7 +178,7 @@ EXPECT_EQ(2u, session_->GetNumOpenStreams()); // Send a reset (and expect the peer to send a RST in response). - QuicRstStreamFrame rst(kClientDataStreamId1, QUIC_STREAM_NO_ERROR, 0); + QuicRstStreamFrame rst(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, 0); EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0)); visitor_->OnRstStream(rst); @@ -211,14 +213,14 @@ QuicStreamId stream_id = kClientDataStreamId1; // Open the max configured number of streams, should be no problem. for (size_t i = 0; i < kMaxStreamsForTest; ++i) { - EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDynamicStream(session_.get(), + EXPECT_TRUE(QuicServerSessionPeer::GetOrCreateDynamicStream(session_.get(), stream_id)); stream_id += 2; } // Open more streams: server should accept slightly more than the limit. for (size_t i = 0; i < kMaxStreamsMinimumIncrement; ++i) { - EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDynamicStream(session_.get(), + EXPECT_TRUE(QuicServerSessionPeer::GetOrCreateDynamicStream(session_.get(), stream_id)); stream_id += 2; } @@ -233,7 +235,7 @@ EXPECT_CALL(*connection_, SendRstStream(stream_id, QUIC_REFUSED_STREAM, 0)); } // Even if the connection remains open, the stream creation should fail. - EXPECT_FALSE(QuicServerSessionPeer::GetIncomingDynamicStream(session_.get(), + EXPECT_FALSE(QuicServerSessionPeer::GetOrCreateDynamicStream(session_.get(), stream_id)); } @@ -253,7 +255,7 @@ EXPECT_LE(10 * kMaxStreamsForTest, kAvailableStreamLimit); EXPECT_EQ(0u, session_->GetNumOpenStreams()); - EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDynamicStream( + EXPECT_TRUE(QuicServerSessionPeer::GetOrCreateDynamicStream( session_.get(), kClientDataStreamId1)); // Establish available streams up to the server's limit. @@ -261,7 +263,7 @@ FLAGS_allow_many_available_streams ? kClientDataStreamId1 + (kAvailableStreamLimit)*2 + 2 : kClientDataStreamId1 + (session_->get_max_open_streams() - 1) * 2; - EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDynamicStream( + EXPECT_TRUE(QuicServerSessionPeer::GetOrCreateDynamicStream( session_.get(), kLimitingStreamId)); // A further available stream will result in connection close. @@ -273,7 +275,7 @@ } // This forces stream kLimitingStreamId + 2 to become available, which // violates the quota. - EXPECT_FALSE(QuicServerSessionPeer::GetIncomingDynamicStream( + EXPECT_FALSE(QuicServerSessionPeer::GetOrCreateDynamicStream( session_.get(), kLimitingStreamId + 4)); } @@ -281,14 +283,14 @@ // Incoming streams on the server session must be odd. EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_STREAM_ID)); EXPECT_EQ(nullptr, - QuicServerSessionPeer::GetIncomingDynamicStream(session_.get(), 4)); + QuicServerSessionPeer::GetOrCreateDynamicStream(session_.get(), 4)); } TEST_P(QuicServerSessionTest, GetStreamDisconnected) { // Don't create new streams if the connection is disconnected. QuicConnectionPeer::CloseConnection(connection_); EXPECT_DFATAL( - QuicServerSessionPeer::GetIncomingDynamicStream(session_.get(), 5), + QuicServerSessionPeer::GetOrCreateDynamicStream(session_.get(), 5), "ShouldCreateIncomingDynamicStream called when disconnected"); } @@ -305,7 +307,7 @@ // optionally protected. EXPECT_EQ(FEC_PROTECT_ALWAYS, QuicSpdySessionPeer::GetHeadersStream( session_.get())->fec_policy()); - ReliableQuicStream* stream = QuicServerSessionPeer::GetIncomingDynamicStream( + ReliableQuicStream* stream = QuicServerSessionPeer::GetOrCreateDynamicStream( session_.get(), kClientDataStreamId1); ASSERT_TRUE(stream); EXPECT_EQ(FEC_PROTECT_OPTIONAL, stream->fec_policy());
diff --git a/net/tools/quic/quic_simple_server_bin.cc b/net/tools/quic/quic_simple_server_bin.cc index ef435533..e6dc5187f 100644 --- a/net/tools/quic/quic_simple_server_bin.cc +++ b/net/tools/quic/quic_simple_server_bin.cc
@@ -25,7 +25,7 @@ net::ProofSource* CreateProofSource(const base::FilePath& cert_path, const base::FilePath& key_path) { net::ProofSourceChromium* proof_source = new net::ProofSourceChromium(); - CHECK(proof_source->Initialize(cert_path, key_path)); + CHECK(proof_source->Initialize(cert_path, key_path, base::FilePath())); return proof_source; }
diff --git a/net/tools/quic/quic_simple_server_test.cc b/net/tools/quic/quic_simple_server_test.cc index c401c40..dea0a72d 100644 --- a/net/tools/quic/quic_simple_server_test.cc +++ b/net/tools/quic/quic_simple_server_test.cc
@@ -28,7 +28,7 @@ dispatcher_(config_, &crypto_config_, new tools::QuicDispatcher::DefaultPacketWriterFactory(), - new net::test::MockHelper) { + new net::test::MockConnectionHelper) { dispatcher_.InitializeWithWriter(nullptr); }
diff --git a/net/tools/quic/quic_spdy_client_stream_test.cc b/net/tools/quic/quic_spdy_client_stream_test.cc index 087cfe7..af7bbd3 100644 --- a/net/tools/quic/quic_spdy_client_stream_test.cc +++ b/net/tools/quic/quic_spdy_client_stream_test.cc
@@ -17,7 +17,7 @@ using net::test::CryptoTestUtils; using net::test::DefaultQuicConfig; using net::test::MockConnection; -using net::test::MockHelper; +using net::test::MockConnectionHelper; using net::test::SupportedVersions; using net::test::kClientDataStreamId1; using net::test::kInitialSessionFlowControlWindowForTest; @@ -60,7 +60,7 @@ stream_.reset(new QuicSpdyClientStream(kClientDataStreamId1, &session_)); } - MockHelper helper_; + MockConnectionHelper helper_; StrictMock<MockConnection>* connection_; QuicCryptoClientConfig crypto_config_; QuicClientSession session_;
diff --git a/net/tools/quic/quic_spdy_server_stream_test.cc b/net/tools/quic/quic_spdy_server_stream_test.cc index 0ba92ad..dedb272 100644 --- a/net/tools/quic/quic_spdy_server_stream_test.cc +++ b/net/tools/quic/quic_spdy_server_stream_test.cc
@@ -22,7 +22,7 @@ using base::StringPiece; using net::test::MockConnection; -using net::test::MockHelper; +using net::test::MockConnectionHelper; using net::test::MockQuicSpdySession; using net::test::ReliableQuicStreamPeer; using net::test::SupportedVersions; @@ -126,7 +126,7 @@ } SpdyHeaderBlock response_headers_; - MockHelper helper_; + MockConnectionHelper helper_; StrictMock<MockConnection>* connection_; StrictMock<MockQuicSpdySession> session_; QuicSpdyServerStreamPeer* stream_; // Owned by session_.
diff --git a/net/tools/quic/quic_time_wait_list_manager.cc b/net/tools/quic/quic_time_wait_list_manager.cc index 8c2b46a..c9405a5 100644 --- a/net/tools/quic/quic_time_wait_list_manager.cc +++ b/net/tools/quic/quic_time_wait_list_manager.cc
@@ -97,7 +97,7 @@ for (ConnectionIdMap::iterator it = connection_id_map_.begin(); it != connection_id_map_.end(); ++it) { - delete it->second.close_packet; + STLDeleteElements(&it->second.termination_packets); } } @@ -105,23 +105,28 @@ QuicConnectionId connection_id, QuicVersion version, bool connection_rejected_statelessly, - QuicEncryptedPacket* close_packet) { - DCHECK(!connection_rejected_statelessly || !close_packet) - << "Connections that were rejected statelessly should not " - << "have a close packet. connection_id = " << connection_id; + std::vector<QuicEncryptedPacket*>* termination_packets) { + if (connection_rejected_statelessly) { + DCHECK(termination_packets != nullptr && !termination_packets->empty()) + << "Connections that were rejected statelessly must " + << "have a close packet. connection_id = " << connection_id; + } int num_packets = 0; ConnectionIdMap::iterator it = connection_id_map_.find(connection_id); const bool new_connection_id = it == connection_id_map_.end(); if (!new_connection_id) { // Replace record if it is reinserted. num_packets = it->second.num_packets; - delete it->second.close_packet; + STLDeleteElements(&it->second.termination_packets); connection_id_map_.erase(it); } TrimTimeWaitListIfNeeded(); DCHECK_LT(num_connections(), static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections)); ConnectionIdData data(num_packets, version, clock_->ApproximateNow(), - close_packet, connection_rejected_statelessly); + connection_rejected_statelessly); + if (termination_packets != nullptr) { + data.termination_packets.swap(*termination_packets); + } connection_id_map_.insert(std::make_pair(connection_id, data)); if (new_connection_id) { visitor_->OnConnectionAddedToTimeWaitList(connection_id); @@ -171,17 +176,17 @@ return; } - if (connection_data->close_packet) { - QueuedPacket* queued_packet = new QueuedPacket( - server_address, client_address, connection_data->close_packet->Clone()); - // Takes ownership of the packet. - SendOrQueuePacket(queued_packet); - return; - } - - if (connection_data->connection_rejected_statelessly) { - DVLOG(3) << "Time wait list not sending response for connection " - << connection_id << " due to previous stateless reject."; + if (!connection_data->termination_packets.empty()) { + if (connection_data->connection_rejected_statelessly) { + DVLOG(3) << "Time wait list sending previous stateless reject response " + << "for connection " << connection_id; + } + for (QuicEncryptedPacket* packet : connection_data->termination_packets) { + QueuedPacket* queued_packet = + new QueuedPacket(server_address, client_address, packet->Clone()); + // Takes ownership of the packet. + SendOrQueuePacket(queued_packet); + } return; } @@ -290,7 +295,7 @@ } // This connection_id has lived its age, retire it now. const QuicConnectionId connection_id = it->first; - delete it->second.close_packet; + STLDeleteElements(&it->second.termination_packets); connection_id_map_.erase(it); visitor_->OnConnectionRemovedFromTimeWaitList(connection_id); return true; @@ -316,5 +321,17 @@ } } +QuicTimeWaitListManager::ConnectionIdData::ConnectionIdData( + int num_packets_, + QuicVersion version_, + QuicTime time_added_, + bool connection_rejected_statelessly) + : num_packets(num_packets_), + version(version_), + time_added(time_added_), + connection_rejected_statelessly(connection_rejected_statelessly) {} + +QuicTimeWaitListManager::ConnectionIdData::~ConnectionIdData() {} + } // namespace tools } // namespace net
diff --git a/net/tools/quic/quic_time_wait_list_manager.h b/net/tools/quic/quic_time_wait_list_manager.h index 092f116..e36d8662 100644 --- a/net/tools/quic/quic_time_wait_list_manager.h +++ b/net/tools/quic/quic_time_wait_list_manager.h
@@ -48,23 +48,18 @@ ~QuicTimeWaitListManager() override; // Adds the given connection_id to time wait state for time_wait_period_. - // Henceforth, any packet bearing this connection_id should not be processed - // while the connection_id remains in this list. If a non-nullptr - // |close_packet| is provided, the TimeWaitListManager takes ownership of it - // and sends it again when packets are received for added connection_ids. If - // nullptr, a public reset packet is sent with the specified |version|. - // DCHECKs that connection_id is not already on the list. "virtual" to - // override in tests. If "connection_rejected_statelessly" is true, it means - // that the connection was closed due to a stateless reject, and no close - // packet is expected. Any packets that are received for connection_id will - // be black-holed. - // TODO(jokulik): In the future, we plan send (redundant) SREJ packets back to - // the client in response to stray data-packets that arrive after the first - // SREJ. This requires some new plumbing, so we black-hole for now. - virtual void AddConnectionIdToTimeWait(QuicConnectionId connection_id, - QuicVersion version, - bool connection_rejected_statelessly, - QuicEncryptedPacket* close_packet); + // If |termination_packets| are provided, copies of these packets will be sent + // when a packet with this connection ID is processed. If no termination + // packets are provided, then a PUBLIC_RESET will be sent with the specified + // |version|. Any termination packets will be move from |termination_packets| + // and will become owned by the manager. If |connection_rejected_statelessly| + // is true, it means that the connection was closed due to a stateless reject, + // and termination packets are expected. + virtual void AddConnectionIdToTimeWait( + QuicConnectionId connection_id, + QuicVersion version, + bool connection_rejected_statelessly, + std::vector<QuicEncryptedPacket*>* termination_packets); // Returns true if the connection_id is in time wait state, false otherwise. // Packets received for this connection_id should not lead to creation of new @@ -151,17 +146,15 @@ ConnectionIdData(int num_packets_, QuicVersion version_, QuicTime time_added_, - QuicEncryptedPacket* close_packet, - bool connection_rejected_statelessly) - : num_packets(num_packets_), - version(version_), - time_added(time_added_), - close_packet(close_packet), - connection_rejected_statelessly(connection_rejected_statelessly) {} + bool connection_rejected_statelessly); + + ~ConnectionIdData(); + int num_packets; QuicVersion version; QuicTime time_added; - QuicEncryptedPacket* close_packet; + // These packets may contain CONNECTION_CLOSE frames, or SREJ messages. + std::vector<QuicEncryptedPacket*> termination_packets; bool connection_rejected_statelessly; };
diff --git a/net/tools/quic/quic_time_wait_list_manager_test.cc b/net/tools/quic/quic_time_wait_list_manager_test.cc index f78fbcbc..0e925cb 100644 --- a/net/tools/quic/quic_time_wait_list_manager_test.cc +++ b/net/tools/quic/quic_time_wait_list_manager_test.cc
@@ -97,9 +97,6 @@ QuicTimeWaitListManagerTest() : helper_(&epoll_server_), time_wait_list_manager_(&writer_, &visitor_, &helper_), - framer_(QuicSupportedVersions(), - QuicTime::Zero(), - Perspective::IS_SERVER), connection_id_(45), client_address_(net::test::TestPeerIPAddress(), kTestPort), writer_is_blocked_(false) {} @@ -119,17 +116,19 @@ } void AddStatelessConnectionId(QuicConnectionId connection_id) { + std::vector<QuicEncryptedPacket*> termination_packets; + termination_packets.push_back(new QuicEncryptedPacket(nullptr, 0, false)); time_wait_list_manager_.AddConnectionIdToTimeWait( connection_id, QuicVersionMax(), - /*connection_rejected_statelessly=*/true, nullptr); + /*connection_rejected_statelessly=*/true, &termination_packets); } void AddConnectionId(QuicConnectionId connection_id, QuicVersion version, bool connection_rejected_statelessly, - QuicEncryptedPacket* packet) { + std::vector<QuicEncryptedPacket*>* packets) { time_wait_list_manager_.AddConnectionIdToTimeWait( - connection_id, version, connection_rejected_statelessly, packet); + connection_id, version, connection_rejected_statelessly, packets); } bool IsConnectionIdInTimeWait(QuicConnectionId connection_id) { @@ -144,33 +143,10 @@ } QuicEncryptedPacket* ConstructEncryptedPacket( - EncryptionLevel level, QuicConnectionId connection_id, QuicPacketNumber packet_number) { - QuicPacketHeader header; - header.public_header.connection_id = connection_id; - header.public_header.connection_id_length = PACKET_8BYTE_CONNECTION_ID; - header.public_header.version_flag = false; - header.public_header.reset_flag = false; - header.public_header.packet_number_length = PACKET_6BYTE_PACKET_NUMBER; - header.packet_number = packet_number; - header.entropy_flag = false; - header.entropy_hash = 0; - header.fec_flag = false; - header.is_in_fec_group = NOT_IN_FEC_GROUP; - header.fec_group = 0; - QuicStreamFrame stream_frame(1, false, 0, StringPiece("data")); - QuicFrame frame(&stream_frame); - QuicFrames frames; - frames.push_back(frame); - scoped_ptr<QuicPacket> packet( - BuildUnsizedDataPacket(&framer_, header, frames)); - EXPECT_TRUE(packet != nullptr); - char buffer[kMaxPacketSize]; - scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPayload( - ENCRYPTION_NONE, packet_number, *packet, buffer, kMaxPacketSize)); - EXPECT_TRUE(encrypted != nullptr); - return encrypted->Clone(); + return net::test::ConstructEncryptedPacket(connection_id, false, false, + packet_number, "data"); } NiceMock<MockFakeTimeEpollServer> epoll_server_; @@ -178,7 +154,6 @@ StrictMock<MockPacketWriter> writer_; StrictMock<MockQuicServerSessionVisitor> visitor_; QuicTimeWaitListManager time_wait_list_manager_; - QuicFramer framer_; QuicConnectionId connection_id_; IPEndPoint server_address_; IPEndPoint client_address_; @@ -246,10 +221,12 @@ TEST_F(QuicTimeWaitListManagerTest, SendConnectionClose) { const size_t kConnectionCloseLength = 100; EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); + std::vector<QuicEncryptedPacket*> termination_packets; + termination_packets.push_back(new QuicEncryptedPacket( + new char[kConnectionCloseLength], kConnectionCloseLength, true)); AddConnectionId(connection_id_, QuicVersionMax(), /*connection_rejected_statelessly=*/false, - new QuicEncryptedPacket(new char[kConnectionCloseLength], - kConnectionCloseLength, true)); + &termination_packets); const int kRandomSequenceNumber = 1; EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength, server_address_.address(), @@ -259,6 +236,26 @@ ProcessPacket(connection_id_, kRandomSequenceNumber); } +TEST_F(QuicTimeWaitListManagerTest, SendTwoConnectionCloses) { + const size_t kConnectionCloseLength = 100; + EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); + std::vector<QuicEncryptedPacket*> termination_packets; + termination_packets.push_back(new QuicEncryptedPacket( + new char[kConnectionCloseLength], kConnectionCloseLength, true)); + termination_packets.push_back(new QuicEncryptedPacket( + new char[kConnectionCloseLength], kConnectionCloseLength, true)); + AddConnectionId(connection_id_, QuicVersionMax(), + /*connection_rejected_statelessly=*/false, + &termination_packets); + const int kRandomSequenceNumber = 1; + EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength, + server_address_.address(), client_address_)) + .Times(2) + .WillRepeatedly(Return(WriteResult(WRITE_STATUS_OK, 1))); + + ProcessPacket(connection_id_, kRandomSequenceNumber); +} + TEST_F(QuicTimeWaitListManagerTest, SendPublicReset) { EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); AddConnectionId(connection_id_); @@ -298,6 +295,11 @@ EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); AddStatelessConnectionId(connection_id_); const int kRandomSequenceNumber = 1; + + EXPECT_CALL(writer_, + WritePacket(_, _, server_address_.address(), client_address_)) + .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1))); + ProcessPacket(connection_id_, kRandomSequenceNumber); } @@ -359,7 +361,7 @@ AddConnectionId(connection_id); QuicPacketNumber packet_number = 234; scoped_ptr<QuicEncryptedPacket> packet( - ConstructEncryptedPacket(ENCRYPTION_NONE, connection_id, packet_number)); + ConstructEncryptedPacket(connection_id, packet_number)); // Let first write through. EXPECT_CALL(writer_, WritePacket(_, _, server_address_.address(), client_address_)) @@ -384,8 +386,8 @@ EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(other_connection_id)); AddConnectionId(other_connection_id); QuicPacketNumber other_packet_number = 23423; - scoped_ptr<QuicEncryptedPacket> other_packet(ConstructEncryptedPacket( - ENCRYPTION_NONE, other_connection_id, other_packet_number)); + scoped_ptr<QuicEncryptedPacket> other_packet( + ConstructEncryptedPacket(other_connection_id, other_packet_number)); EXPECT_CALL(writer_, WritePacket(_, _, _, _)) .Times(0); EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_)); @@ -439,10 +441,12 @@ AddConnectionId(connection_id_); EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_)); const size_t kConnectionCloseLength = 100; + std::vector<QuicEncryptedPacket*> termination_packets; + termination_packets.push_back(new QuicEncryptedPacket( + new char[kConnectionCloseLength], kConnectionCloseLength, true)); AddConnectionId(connection_id_, QuicVersionMax(), /*connection_rejected_statelessly=*/false, - new QuicEncryptedPacket(new char[kConnectionCloseLength], - kConnectionCloseLength, true)); + &termination_packets); EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_)); EXPECT_EQ(1u, time_wait_list_manager_.num_connections());
diff --git a/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h b/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h index 56b2880..116fd7e 100644 --- a/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h +++ b/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h
@@ -25,15 +25,16 @@ void(QuicConnectionId connection_id, QuicVersion version, bool connection_rejected_statelessly, - QuicEncryptedPacket* close_packet)); + std::vector<QuicEncryptedPacket*>* termination_packets)); void QuicTimeWaitListManager_AddConnectionIdToTimeWait( QuicConnectionId connection_id, QuicVersion version, bool connection_rejected_statelessly, - QuicEncryptedPacket* close_packet) { + std::vector<QuicEncryptedPacket*>* termination_packets) { QuicTimeWaitListManager::AddConnectionIdToTimeWait( - connection_id, version, connection_rejected_statelessly, close_packet); + connection_id, version, connection_rejected_statelessly, + termination_packets); } MOCK_METHOD5(ProcessPacket,
diff --git a/net/tools/quic/test_tools/packet_dropping_test_writer.h b/net/tools/quic/test_tools/packet_dropping_test_writer.h index 0082f8e..9a95bd85 100644 --- a/net/tools/quic/test_tools/packet_dropping_test_writer.h +++ b/net/tools/quic/test_tools/packet_dropping_test_writer.h
@@ -30,7 +30,6 @@ class Delegate { public: virtual ~Delegate() {} - virtual void OnPacketSent(WriteResult result) = 0; virtual void OnCanWrite() = 0; };
diff --git a/net/url_request/url_fetcher_impl_unittest.cc b/net/url_request/url_fetcher_impl_unittest.cc index 37e69024..f9eda54a 100644 --- a/net/url_request/url_fetcher_impl_unittest.cc +++ b/net/url_request/url_fetcher_impl_unittest.cc
@@ -11,6 +11,7 @@ #include <string> #include "base/bind.h" +#include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/location.h" @@ -33,7 +34,7 @@ #include "net/base/upload_file_element_reader.h" #include "net/dns/mock_host_resolver.h" #include "net/http/http_response_headers.h" -#include "net/test/spawned_test_server/spawned_test_server.h" +#include "net/test/embedded_test_server/embedded_test_server.h" #include "net/url_request/url_fetcher_delegate.h" #include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_test_util.h" @@ -56,11 +57,11 @@ // TODO(akalin): Move all the test data to somewhere under net/. const base::FilePath::CharType kDocRoot[] = FILE_PATH_LITERAL("net/data/url_fetcher_impl_unittest"); -const char kTestServerFilePrefix[] = "files/"; +const char kTestServerFilePrefix[] = "/"; // Test server path and response body for the default URL used by many of the // tests. -const char kDefaultResponsePath[] = "defaultresponse"; +const char kDefaultResponsePath[] = "/defaultresponse"; const char kDefaultResponseBody[] = "Default response given for path: /defaultresponse"; @@ -386,8 +387,11 @@ EXPECT_EQ(requested_out_path, out_path); } + base::FilePath server_root; + PathService::Get(base::DIR_SOURCE_ROOT, &server_root); + EXPECT_TRUE(base::ContentsEqual( - test_server_->GetDocumentRoot().AppendASCII(file_to_fetch), out_path)); + server_root.Append(kDocRoot).AppendASCII(file_to_fetch), out_path)); // Delete the delegate and run the message loop to give the fetcher's // destructor a chance to delete the file. @@ -413,7 +417,7 @@ // URL that will hang when lookups reach the host resolver. hanging_url_ = GURL(base::StringPrintf( - "http://example.com:%d/%s", test_server_->host_port_pair().port(), + "http://example.com:%d%s", test_server_->host_port_pair().port(), kDefaultResponsePath)); ASSERT_TRUE(hanging_url_.is_valid()); @@ -432,16 +436,15 @@ // Initializes |test_server_| without starting it. Allows subclasses to use // their own server configuration. virtual void SetUpServer() { - test_server_.reset(new SpawnedTestServer(SpawnedTestServer::TYPE_HTTP, - SpawnedTestServer::kLocalhost, - base::FilePath(kDocRoot))); + test_server_.reset(new EmbeddedTestServer); + test_server_->AddDefaultHandlers(base::FilePath(kDocRoot)); } // Network thread for cross-thread tests. Most threads just use the main // thread for network activity. scoped_ptr<base::Thread> network_thread_; - scoped_ptr<SpawnedTestServer> test_server_; + scoped_ptr<EmbeddedTestServer> test_server_; GURL hanging_url_; size_t num_upload_streams_created_; @@ -456,10 +459,10 @@ // URLFetcherTest: void SetUpServer() override { - SpawnedTestServer::SSLOptions ssl_options( - SpawnedTestServer::SSLOptions::CERT_EXPIRED); - test_server_.reset(new SpawnedTestServer( - SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath(kDocRoot))); + test_server_.reset( + new EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS)); + test_server_->SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED); + test_server_->ServeFilesFromSourceDirectory("net/data/ssl"); } }; @@ -660,7 +663,7 @@ const char kUploadData[] = "bobsyeruncle"; WaitingURLFetcherDelegate delegate; - delegate.CreateFetcher(test_server_->GetURL("echo"), URLFetcher::POST, + delegate.CreateFetcher(test_server_->GetURL("/echo"), URLFetcher::POST, CreateSameThreadContextGetter()); delegate.fetcher()->SetUploadData("application/x-www-form-urlencoded", kUploadData); @@ -677,7 +680,7 @@ const char kUploadData[] = ""; WaitingURLFetcherDelegate delegate; - delegate.CreateFetcher(test_server_->GetURL("echo"), URLFetcher::POST, + delegate.CreateFetcher(test_server_->GetURL("/echo"), URLFetcher::POST, CreateSameThreadContextGetter()); delegate.fetcher()->SetUploadData("application/x-www-form-urlencoded", kUploadData); @@ -694,7 +697,7 @@ base::FilePath upload_path = GetUploadFileTestPath(); WaitingURLFetcherDelegate delegate; - delegate.CreateFetcher(test_server_->GetURL("echo"), URLFetcher::POST, + delegate.CreateFetcher(test_server_->GetURL("/echo"), URLFetcher::POST, CreateSameThreadContextGetter()); delegate.fetcher()->SetUploadFilePath("application/x-www-form-urlencoded", upload_path, 0, kuint64max, @@ -717,7 +720,7 @@ base::FilePath upload_path = GetUploadFileTestPath(); WaitingURLFetcherDelegate delegate; - delegate.CreateFetcher(test_server_->GetURL("echo"), URLFetcher::POST, + delegate.CreateFetcher(test_server_->GetURL("/echo"), URLFetcher::POST, CreateSameThreadContextGetter()); delegate.fetcher()->SetUploadFilePath("application/x-www-form-urlencoded", upload_path, kRangeStart, kRangeLength, @@ -736,7 +739,7 @@ TEST_F(URLFetcherTest, PostWithUploadStreamFactory) { WaitingURLFetcherDelegate delegate; - delegate.CreateFetcher(test_server_->GetURL("echo"), URLFetcher::POST, + delegate.CreateFetcher(test_server_->GetURL("/echo"), URLFetcher::POST, CreateSameThreadContextGetter()); delegate.fetcher()->SetUploadStreamFactory( "text/plain", @@ -753,7 +756,7 @@ TEST_F(URLFetcherTest, PostWithUploadStreamFactoryAndRetries) { WaitingURLFetcherDelegate delegate; - delegate.CreateFetcher(test_server_->GetURL("echo?status=500"), + delegate.CreateFetcher(test_server_->GetURL("/echo?status=500"), URLFetcher::POST, CreateSameThreadContextGetter()); delegate.fetcher()->SetAutomaticallyRetryOn5xx(true); delegate.fetcher()->SetMaxRetriesOn5xx(1); @@ -815,7 +818,7 @@ TEST_F(URLFetcherTest, UploadProgress) { CheckUploadProgressDelegate delegate; - delegate.CreateFetcher(test_server_->GetURL("echo"), URLFetcher::POST, + delegate.CreateFetcher(test_server_->GetURL("/echo"), URLFetcher::POST, CreateSameThreadContextGetter()); // Use a chunked upload so that the upload can be paused after uploading data. // Since upload progress uses a timer, the delegate may not receive any @@ -869,9 +872,12 @@ const char kFileToFetch[] = "animate1.gif"; std::string file_contents; + + base::FilePath server_root; + PathService::Get(base::DIR_SOURCE_ROOT, &server_root); + ASSERT_TRUE(base::ReadFileToString( - test_server_->GetDocumentRoot().AppendASCII(kFileToFetch), - &file_contents)); + server_root.Append(kDocRoot).AppendASCII(kFileToFetch), &file_contents)); CheckDownloadProgressDelegate delegate(file_contents.size()); delegate.CreateFetcher( @@ -905,7 +911,7 @@ // callback. TEST_F(URLFetcherTest, CancelInUploadProgressCallback) { CancelOnUploadProgressDelegate delegate; - delegate.CreateFetcher(test_server_->GetURL("echo"), URLFetcher::POST, + delegate.CreateFetcher(test_server_->GetURL("/echo"), URLFetcher::POST, CreateSameThreadContextGetter()); delegate.fetcher()->SetChunkedUpload("application/x-www-form-urlencoded"); delegate.fetcher()->Start(); @@ -960,7 +966,7 @@ TEST_F(URLFetcherTest, Headers) { WaitingURLFetcherDelegate delegate; delegate.CreateFetcher( - test_server_->GetURL("set-header?cache-control: private"), + test_server_->GetURL("/set-header?cache-control: private"), URLFetcher::GET, CreateSameThreadContextGetter()); delegate.StartFetcherAndWait(); @@ -991,7 +997,7 @@ WaitingURLFetcherDelegate delegate; delegate.CreateFetcher( - test_server_->GetURL(std::string("server-redirect?") + kRedirectTarget), + test_server_->GetURL(std::string("/server-redirect?") + kRedirectTarget), URLFetcher::GET, CreateSameThreadContextGetter()); delegate.fetcher()->SetStopOnRedirect(true); delegate.StartFetcherAndWait(); @@ -1035,7 +1041,7 @@ TEST_F(URLFetcherTest, ThrottleOn5xxRetries) { base::Time start_time = Time::Now(); - GURL url(test_server_->GetURL("files/server-unavailable.html")); + GURL url(test_server_->GetURL("/server-unavailable.html")); scoped_refptr<FetcherTestURLRequestContextGetter> context_getter( CreateSameThreadContextGetter()); @@ -1072,7 +1078,7 @@ // Tests overload protection, when responses passed through. TEST_F(URLFetcherTest, ProtectTestPassedThrough) { base::Time start_time = Time::Now(); - GURL url(test_server_->GetURL("files/server-unavailable.html")); + GURL url(test_server_->GetURL("/server-unavailable.html")); scoped_refptr<FetcherTestURLRequestContextGetter> context_getter( CreateSameThreadContextGetter()); @@ -1241,7 +1247,7 @@ scoped_refptr<URLRequestContextGetter> context_getter( CreateSameThreadContextGetter()); ReuseFetcherDelegate delegate(context_getter); - delegate.CreateFetcher(test_server_->GetURL("echoheader?test"), + delegate.CreateFetcher(test_server_->GetURL("/echoheader?test"), URLFetcher::GET, context_getter); delegate.fetcher()->SetExtraRequestHeaders("test: request1"); delegate.StartFetcherAndWait();
diff --git a/net/url_request/url_request_context_builder_unittest.cc b/net/url_request/url_request_context_builder_unittest.cc index e37b51e..8c280d35 100644 --- a/net/url_request/url_request_context_builder_unittest.cc +++ b/net/url_request/url_request_context_builder_unittest.cc
@@ -9,7 +9,7 @@ #include "net/base/request_priority.h" #include "net/http/http_auth_handler.h" #include "net/http/http_auth_handler_factory.h" -#include "net/test/spawned_test_server/spawned_test_server.h" +#include "net/test/embedded_test_server/embedded_test_server.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_test_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -47,18 +47,16 @@ class URLRequestContextBuilderTest : public PlatformTest { protected: - URLRequestContextBuilderTest() - : test_server_(SpawnedTestServer::TYPE_HTTP, - SpawnedTestServer::kLocalhost, - base::FilePath( - FILE_PATH_LITERAL("net/data/url_request_unittest"))) { + URLRequestContextBuilderTest() { + test_server_.AddDefaultHandlers( + base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); #if defined(OS_LINUX) || defined(OS_ANDROID) builder_.set_proxy_config_service(make_scoped_ptr( new ProxyConfigServiceFixed(ProxyConfig::CreateDirect()))); #endif // defined(OS_LINUX) || defined(OS_ANDROID) } - SpawnedTestServer test_server_; + EmbeddedTestServer test_server_; URLRequestContextBuilder builder_; }; @@ -68,7 +66,7 @@ scoped_ptr<URLRequestContext> context(builder_.Build()); TestDelegate delegate; scoped_ptr<URLRequest> request(context->CreateRequest( - test_server_.GetURL("echoheader?Foo"), DEFAULT_PRIORITY, &delegate)); + test_server_.GetURL("/echoheader?Foo"), DEFAULT_PRIORITY, &delegate)); request->set_method("GET"); request->SetExtraRequestHeaderByName("Foo", "Bar", false); request->Start(); @@ -83,7 +81,7 @@ scoped_ptr<URLRequestContext> context(builder_.Build()); TestDelegate delegate; scoped_ptr<URLRequest> request( - context->CreateRequest(test_server_.GetURL("echoheader?User-Agent"), + context->CreateRequest(test_server_.GetURL("/echoheader?User-Agent"), DEFAULT_PRIORITY, &delegate)); request->set_method("GET"); request->Start();
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 925a4d0..943ee6e 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -77,6 +77,7 @@ #include "net/socket/ssl_client_socket.h" #include "net/ssl/ssl_cipher_suite_names.h" #include "net/ssl/ssl_connection_status_flags.h" +#include "net/ssl/ssl_server_config.h" #include "net/test/cert_test_util.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" @@ -225,7 +226,6 @@ } #endif -#if !defined(OS_IOS) void TestLoadTimingCacheHitNoNetwork( const LoadTimingInfo& load_timing_info) { EXPECT_FALSE(load_timing_info.socket_reused); @@ -318,6 +318,7 @@ EXPECT_EQ("keep-alive", sent_value); } +#if !defined(OS_IOS) bool FingerprintsEqual(const HashValueVector& a, const HashValueVector& b) { size_t size = a.size(); @@ -2193,40 +2194,17 @@ EXPECT_EQ(MAXIMUM_PRIORITY, job->priority()); } -// TODO(droger): Support SpawnedTestServer on iOS (see http://crbug.com/148666). -#if !defined(OS_IOS) namespace { // Less verbose way of running a simple testserver for the tests below. -class LocalHttpTestServer : public SpawnedTestServer { +class LocalHttpTestServer : public EmbeddedTestServer { public: - explicit LocalHttpTestServer(const base::FilePath& document_root) - : SpawnedTestServer(SpawnedTestServer::TYPE_HTTP, - SpawnedTestServer::kLocalhost, - document_root) {} - LocalHttpTestServer() - : SpawnedTestServer(SpawnedTestServer::TYPE_HTTP, - SpawnedTestServer::kLocalhost, - base::FilePath()) {} -}; - -scoped_ptr<net::test_server::HttpResponse> HandleSetCookieRequest( - const test_server::HttpRequest& request) { - scoped_ptr<test_server::BasicHttpResponse> http_response( - new test_server::BasicHttpResponse()); - if (request.relative_url.find("/set-cookie?") != 0) { - http_response->set_code(net::HTTP_NOT_FOUND); - http_response->set_content("hello"); - return http_response.Pass(); + explicit LocalHttpTestServer(const base::FilePath& document_root) { + AddDefaultHandlers(document_root); } - http_response->set_code(net::HTTP_OK); - http_response->set_content("hello"); - http_response->set_content_type("text/plain"); - http_response->AddCustomHeader( - "Set-Cookie", - request.relative_url.substr(request.relative_url.find("?") + 1)); - return http_response.Pass(); -} + + LocalHttpTestServer() { AddDefaultHandlers(base::FilePath()); } +}; } // namespace @@ -2246,7 +2224,7 @@ context.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(context.CreateRequest( - test_server.GetURL("set-cookie?CookieToNotSend=1"), DEFAULT_PRIORITY, + test_server.GetURL("/set-cookie?CookieToNotSend=1"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2261,7 +2239,7 @@ context.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(context.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2282,7 +2260,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("set-cookie?CookieToNotSend=1"), DEFAULT_PRIORITY, + test_server.GetURL("/set-cookie?CookieToNotSend=1"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2296,7 +2274,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2312,7 +2290,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->SetLoadFlags(LOAD_DO_NOT_SEND_COOKIES); req->Start(); base::RunLoop().Run(); @@ -2336,7 +2314,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("set-cookie?CookieToNotUpdate=2"), DEFAULT_PRIORITY, + test_server.GetURL("/set-cookie?CookieToNotUpdate=2"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2352,7 +2330,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"), + test_server.GetURL("/set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"), DEFAULT_PRIORITY, &d)); req->SetLoadFlags(LOAD_DO_NOT_SAVE_COOKIES); req->Start(); @@ -2371,7 +2349,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2396,7 +2374,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("set-cookie?CookieToNotSend=1"), DEFAULT_PRIORITY, + test_server.GetURL("/set-cookie?CookieToNotSend=1"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2411,7 +2389,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2429,7 +2407,7 @@ TestDelegate d; network_delegate.set_cookie_options(TestNetworkDelegate::NO_GET_COOKIES); scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2451,7 +2429,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("set-cookie?CookieToNotUpdate=2"), DEFAULT_PRIORITY, + test_server.GetURL("/set-cookie?CookieToNotUpdate=2"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2467,7 +2445,7 @@ TestDelegate d; network_delegate.set_cookie_options(TestNetworkDelegate::NO_SET_COOKIE); scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"), + test_server.GetURL("/set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"), DEFAULT_PRIORITY, &d)); req->Start(); @@ -2483,7 +2461,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2507,7 +2485,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("set-cookie"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/set-cookie"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2527,7 +2505,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("set-cookie?CookieToNotSend=1"), DEFAULT_PRIORITY, + test_server.GetURL("/set-cookie?CookieToNotSend=1"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2542,7 +2520,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2560,7 +2538,7 @@ TestDelegate d; network_delegate.set_cookie_options(TestNetworkDelegate::NO_GET_COOKIES); scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2582,7 +2560,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("set-cookie?CookieToNotUpdate=2"), DEFAULT_PRIORITY, + test_server.GetURL("/set-cookie?CookieToNotUpdate=2"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2598,7 +2576,7 @@ TestDelegate d; network_delegate.set_cookie_options(TestNetworkDelegate::NO_SET_COOKIE); scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"), + test_server.GetURL("/set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"), DEFAULT_PRIORITY, &d)); req->Start(); @@ -2614,7 +2592,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2642,7 +2620,7 @@ TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( test_server.GetURL( - "set-cookie?FirstPartyCookieToSet=1;First-Party-Only"), + "/set-cookie?FirstPartyCookieToSet=1;First-Party-Only"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2658,8 +2636,8 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); - req->set_first_party_for_cookies(test_server.GetURL("")); + test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + req->set_first_party_for_cookies(test_server.GetURL("/")); req->Start(); base::RunLoop().Run(); @@ -2676,7 +2654,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->set_first_party_for_cookies(GURL("http://third-party.test/")); req->Start(); base::RunLoop().Run(); @@ -2702,7 +2680,7 @@ TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( test_server.GetURL( - "set-cookie?FirstPartyCookieToSet=1;First-Party-Only"), + "/set-cookie?FirstPartyCookieToSet=1;First-Party-Only"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2718,8 +2696,8 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); - req->set_first_party_for_cookies(test_server.GetURL("")); + test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + req->set_first_party_for_cookies(test_server.GetURL("/")); req->Start(); base::RunLoop().Run(); @@ -2736,7 +2714,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->set_first_party_for_cookies(GURL("http://third-party.test/")); req->Start(); base::RunLoop().Run(); @@ -2750,13 +2728,14 @@ // Tests that $Secure- cookies can't be set on non-secure origins. TEST_F(URLRequestTest, SecureCookiePrefixOnNonsecureOrigin) { - test_server::EmbeddedTestServer test_server; - test_server.RegisterRequestHandler(base::Bind(&HandleSetCookieRequest)); - ASSERT_TRUE(test_server.InitializeAndWaitUntilReady()); - SpawnedTestServer test_server_https( - SpawnedTestServer::TYPE_HTTPS, SpawnedTestServer::kLocalhost, + EmbeddedTestServer http_server; + http_server.AddDefaultHandlers( base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); - ASSERT_TRUE(test_server_https.Start()); + EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS); + https_server.AddDefaultHandlers( + base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + ASSERT_TRUE(http_server.Start()); + ASSERT_TRUE(https_server.Start()); TestExperimentalFeaturesNetworkDelegate network_delegate; TestURLRequestContext context(true); @@ -2768,7 +2747,7 @@ { TestDelegate d; scoped_ptr<URLRequest> req(context.CreateRequest( - test_server.GetURL("/set-cookie?$Secure-nonsecure-origin=1;Secure"), + http_server.GetURL("/set-cookie?$Secure-nonsecure-origin=1;Secure"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2780,7 +2759,7 @@ { TestDelegate d; scoped_ptr<URLRequest> req(context.CreateRequest( - test_server_https.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + https_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2792,10 +2771,10 @@ } TEST_F(URLRequestTest, SecureCookiePrefixNonexperimental) { - SpawnedTestServer test_server( - SpawnedTestServer::TYPE_HTTPS, SpawnedTestServer::kLocalhost, + EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS); + https_server.AddDefaultHandlers( base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); - ASSERT_TRUE(test_server.Start()); + ASSERT_TRUE(https_server.Start()); TestNetworkDelegate network_delegate; TestURLRequestContext context(true); @@ -2809,7 +2788,7 @@ { TestDelegate d; scoped_ptr<URLRequest> req(context.CreateRequest( - test_server.GetURL("set-cookie?$Secure-nonsecure-not-experimental=1"), + https_server.GetURL("/set-cookie?$Secure-nonsecure-not-experimental=1"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2821,8 +2800,8 @@ { TestDelegate d; scoped_ptr<URLRequest> req(context.CreateRequest( - test_server.GetURL( - "set-cookie?$Secure-secure-not-experimental=1;Secure"), + https_server.GetURL( + "/set-cookie?$Secure-secure-not-experimental=1;Secure"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2835,7 +2814,7 @@ { TestDelegate d; scoped_ptr<URLRequest> req(context.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + https_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2850,10 +2829,10 @@ } TEST_F(URLRequestTest, SecureCookiePrefixExperimentalNonsecure) { - SpawnedTestServer test_server( - SpawnedTestServer::TYPE_HTTPS, SpawnedTestServer::kLocalhost, + EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS); + https_server.AddDefaultHandlers( base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); - ASSERT_TRUE(test_server.Start()); + ASSERT_TRUE(https_server.Start()); TestExperimentalFeaturesNetworkDelegate network_delegate; TestURLRequestContext context(true); @@ -2864,8 +2843,9 @@ // enabled. { TestDelegate d; - scoped_ptr<URLRequest> req(context.CreateRequest( - test_server.GetURL("set-cookie?$Secure-foo=1"), DEFAULT_PRIORITY, &d)); + scoped_ptr<URLRequest> req( + context.CreateRequest(https_server.GetURL("/set-cookie?$Secure-foo=1"), + DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); EXPECT_EQ(0, network_delegate.blocked_get_cookies_count()); @@ -2876,7 +2856,7 @@ { TestDelegate d; scoped_ptr<URLRequest> req(context.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + https_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -2887,10 +2867,10 @@ } TEST_F(URLRequestTest, SecureCookiePrefixExperimentalSecure) { - SpawnedTestServer test_server( - SpawnedTestServer::TYPE_HTTPS, SpawnedTestServer::kLocalhost, + EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS); + https_server.AddDefaultHandlers( base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); - ASSERT_TRUE(test_server.Start()); + ASSERT_TRUE(https_server.Start()); TestExperimentalFeaturesNetworkDelegate network_delegate; TestURLRequestContext context(true); @@ -2902,8 +2882,8 @@ { TestDelegate d; scoped_ptr<URLRequest> req(context.CreateRequest( - test_server.GetURL("set-cookie?$Secure-bar=1;Secure"), DEFAULT_PRIORITY, - &d)); + https_server.GetURL("/set-cookie?$Secure-bar=1;Secure"), + DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); EXPECT_EQ(0, network_delegate.blocked_get_cookies_count()); @@ -2914,7 +2894,7 @@ { TestDelegate d; scoped_ptr<URLRequest> req(context.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + https_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -3009,7 +2989,7 @@ TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( test_server.GetURL( - "set-cookie?StillGood=1;expires=Mon,18-Apr-1977,22:50:13,GMT"), + "/set-cookie?StillGood=1;expires=Mon,18-Apr-1977,22:50:13,GMT"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -3020,7 +3000,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -3033,7 +3013,7 @@ TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( test_server.GetURL( - "set-cookie?StillGood=1;expires=Mon,18-Apr-1977,22:50:13,GMT"), + "/set-cookie?StillGood=1;expires=Mon,18-Apr-1977,22:50:13,GMT"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -3044,7 +3024,7 @@ default_context_.set_network_delegate(&network_delegate); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("echoheader?Cookie"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -3064,7 +3044,7 @@ { TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("echoheader?Referer"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d)); req->SetReferrer("http://foo.com/"); HttpRequestHeaders headers; @@ -3082,7 +3062,7 @@ { TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server.GetURL("echoheader?Referer"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d)); HttpRequestHeaders headers; headers.SetHeader(HttpRequestHeaders::kReferer, "http://bar.com/"); @@ -3208,7 +3188,7 @@ for (int i = 0; i < kIterations; ++i) { TestDelegate d; scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL("echo"), DEFAULT_PRIORITY, &d)); + test_server_.GetURL("/echo"), DEFAULT_PRIORITY, &d)); r->set_method(method.c_str()); r->set_upload(CreateSimpleUploadData(uploadBytes)); @@ -3255,7 +3235,7 @@ bool DoManyCookiesRequest(int num_cookies) { TestDelegate d; scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL("set-many-cookies?" + + test_server_.GetURL("/set-many-cookies?" + base::IntToString(num_cookies)), DEFAULT_PRIORITY, &d)); @@ -3266,35 +3246,50 @@ bool is_success = r->status().is_success(); - if (!is_success) { + if (!is_success) EXPECT_TRUE(r->status().error() == ERR_RESPONSE_HEADERS_TOO_BIG); - // The test server appears to be unable to handle subsequent requests - // after this error is triggered. Force it to restart. - EXPECT_TRUE(test_server_.Stop()); - EXPECT_TRUE(test_server_.Start()); - } return is_success; } - LocalHttpTestServer* test_server() { - return &test_server_; - } + LocalHttpTestServer* http_test_server() { return &test_server_; } - protected: + private: LocalHttpTestServer test_server_; }; -// In this unit test, we're using the HTTPTestServer as a proxy server and +namespace { + +scoped_ptr<test_server::HttpResponse> HandleRedirectConnect( + const test_server::HttpRequest& request) { + if (request.headers.find("Host") == request.headers.end() || + request.headers.at("Host") != "www.redirect.com" || + request.method != test_server::METHOD_CONNECT) { + return nullptr; + } + + scoped_ptr<test_server::BasicHttpResponse> http_response( + new test_server::BasicHttpResponse); + http_response->set_code(HTTP_FOUND); + http_response->AddCustomHeader("Location", + "http://www.destination.com/foo.js"); + return http_response.Pass(); +} + +} // namespace + +// In this unit test, we're using the EmbeddedTestServer as a proxy server and // issuing a CONNECT request with the magic host name "www.redirect.com". -// The HTTPTestServer will return a 302 response, which we should not +// The EmbeddedTestServer will return a 302 response, which we should not // follow. TEST_F(URLRequestTestHTTP, ProxyTunnelRedirectTest) { - ASSERT_TRUE(test_server_.Start()); + http_test_server()->RegisterRequestHandler( + base::Bind(&HandleRedirectConnect)); + ASSERT_TRUE(http_test_server()->Start()); TestNetworkDelegate network_delegate; // Must outlive URLRequest. TestURLRequestContextWithProxy context( - test_server_.host_port_pair().ToString(), &network_delegate); + http_test_server()->host_port_pair().ToString(), &network_delegate); TestDelegate d; { @@ -3318,11 +3313,11 @@ // This is the same as the previous test, but checks that the network delegate // registers the error. TEST_F(URLRequestTestHTTP, NetworkDelegateTunnelConnectionFailed) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestNetworkDelegate network_delegate; // Must outlive URLRequest. TestURLRequestContextWithProxy context( - test_server_.host_port_pair().ToString(), &network_delegate); + http_test_server()->host_port_pair().ToString(), &network_delegate); TestDelegate d; { @@ -3355,7 +3350,7 @@ }; static const size_t blocking_stages_length = arraysize(blocking_stages); - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; BlockingNetworkDelegate network_delegate( @@ -3371,7 +3366,7 @@ { scoped_ptr<URLRequest> r(context.CreateRequest( - test_server_.GetURL("empty.html"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d)); r->Start(); for (size_t i = 0; i < blocking_stages_length; ++i) { @@ -3391,7 +3386,7 @@ // Tests that the network delegate can block and cancel a request. TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequest) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; BlockingNetworkDelegate network_delegate( @@ -3400,11 +3395,11 @@ network_delegate.set_retval(ERR_EMPTY_RESPONSE); TestURLRequestContextWithProxy context( - test_server_.host_port_pair().ToString(), &network_delegate); + http_test_server()->host_port_pair().ToString(), &network_delegate); { scoped_ptr<URLRequest> r(context.CreateRequest( - test_server_.GetURL(std::string()), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); @@ -3454,66 +3449,66 @@ // The following 3 tests check that the network delegate can cancel a request // synchronously in various stages of the request. TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestSynchronously1) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); NetworkDelegateCancelRequest(BlockingNetworkDelegate::SYNCHRONOUS, BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST, - test_server_.GetURL(std::string())); + http_test_server()->GetURL("/")); } TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestSynchronously2) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); NetworkDelegateCancelRequest(BlockingNetworkDelegate::SYNCHRONOUS, BlockingNetworkDelegate::ON_BEFORE_SEND_HEADERS, - test_server_.GetURL(std::string())); + http_test_server()->GetURL("/")); } TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestSynchronously3) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); NetworkDelegateCancelRequest(BlockingNetworkDelegate::SYNCHRONOUS, BlockingNetworkDelegate::ON_HEADERS_RECEIVED, - test_server_.GetURL(std::string())); + http_test_server()->GetURL("/")); } // The following 3 tests check that the network delegate can cancel a request // asynchronously in various stages of the request. TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestAsynchronously1) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); NetworkDelegateCancelRequest(BlockingNetworkDelegate::AUTO_CALLBACK, BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST, - test_server_.GetURL(std::string())); + http_test_server()->GetURL("/")); } TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestAsynchronously2) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); NetworkDelegateCancelRequest(BlockingNetworkDelegate::AUTO_CALLBACK, BlockingNetworkDelegate::ON_BEFORE_SEND_HEADERS, - test_server_.GetURL(std::string())); + http_test_server()->GetURL("/")); } TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestAsynchronously3) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); NetworkDelegateCancelRequest(BlockingNetworkDelegate::AUTO_CALLBACK, BlockingNetworkDelegate::ON_HEADERS_RECEIVED, - test_server_.GetURL(std::string())); + http_test_server()->GetURL("/")); } // Tests that the network delegate can block and redirect a request to a new // URL. TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequest) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; BlockingNetworkDelegate network_delegate( BlockingNetworkDelegate::AUTO_CALLBACK); network_delegate.set_block_on(BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST); - GURL redirect_url(test_server_.GetURL("simple.html")); + GURL redirect_url(http_test_server()->GetURL("/simple.html")); network_delegate.set_redirect_url(redirect_url); TestURLRequestContextWithProxy context( - test_server_.host_port_pair().ToString(), &network_delegate); + http_test_server()->host_port_pair().ToString(), &network_delegate); { - GURL original_url(test_server_.GetURL("empty.html")); + GURL original_url(http_test_server()->GetURL("/defaultresponse")); scoped_ptr<URLRequest> r( context.CreateRequest(original_url, DEFAULT_PRIORITY, &d)); @@ -3535,12 +3530,11 @@ r->FollowDeferredRedirect(); base::RunLoop().Run(); EXPECT_EQ(URLRequestStatus::SUCCESS, r->status().status()); - EXPECT_TRUE(r->proxy_server().Equals(test_server_.host_port_pair())); + EXPECT_TRUE(r->proxy_server().Equals(http_test_server()->host_port_pair())); EXPECT_EQ( 1, network_delegate.observed_before_proxy_headers_sent_callbacks()); - EXPECT_TRUE( - network_delegate.last_observed_proxy().Equals( - test_server_.host_port_pair())); + EXPECT_TRUE(network_delegate.last_observed_proxy().Equals( + http_test_server()->host_port_pair())); EXPECT_EQ(0, r->status().error()); EXPECT_EQ(redirect_url, r->url()); @@ -3555,19 +3549,19 @@ // Tests that the network delegate can block and redirect a request to a new // URL by setting a redirect_url and returning in OnBeforeURLRequest directly. TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequestSynchronously) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; BlockingNetworkDelegate network_delegate( BlockingNetworkDelegate::SYNCHRONOUS); - GURL redirect_url(test_server_.GetURL("simple.html")); + GURL redirect_url(http_test_server()->GetURL("/simple.html")); network_delegate.set_redirect_url(redirect_url); TestURLRequestContextWithProxy context( - test_server_.host_port_pair().ToString(), &network_delegate); + http_test_server()->host_port_pair().ToString(), &network_delegate); { - GURL original_url(test_server_.GetURL("empty.html")); + GURL original_url(http_test_server()->GetURL("/defaultresponse")); scoped_ptr<URLRequest> r( context.CreateRequest(original_url, DEFAULT_PRIORITY, &d)); @@ -3590,12 +3584,11 @@ base::RunLoop().Run(); EXPECT_EQ(URLRequestStatus::SUCCESS, r->status().status()); - EXPECT_TRUE(r->proxy_server().Equals(test_server_.host_port_pair())); + EXPECT_TRUE(r->proxy_server().Equals(http_test_server()->host_port_pair())); EXPECT_EQ( 1, network_delegate.observed_before_proxy_headers_sent_callbacks()); - EXPECT_TRUE( - network_delegate.last_observed_proxy().Equals( - test_server_.host_port_pair())); + EXPECT_TRUE(network_delegate.last_observed_proxy().Equals( + http_test_server()->host_port_pair())); EXPECT_EQ(0, r->status().error()); EXPECT_EQ(redirect_url, r->url()); EXPECT_EQ(original_url, r->original_url()); @@ -3608,7 +3601,7 @@ // Tests that redirects caused by the network delegate preserve POST data. TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequestPost) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); const char kData[] = "hello world"; @@ -3616,7 +3609,7 @@ BlockingNetworkDelegate network_delegate( BlockingNetworkDelegate::AUTO_CALLBACK); network_delegate.set_block_on(BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST); - GURL redirect_url(test_server_.GetURL("echo")); + GURL redirect_url(http_test_server()->GetURL("/echo")); network_delegate.set_redirect_url(redirect_url); TestURLRequestContext context(true); @@ -3624,7 +3617,7 @@ context.Init(); { - GURL original_url(test_server_.GetURL("empty.html")); + GURL original_url(http_test_server()->GetURL("/defaultresponse")); scoped_ptr<URLRequest> r( context.CreateRequest(original_url, DEFAULT_PRIORITY, &d)); r->set_method("POST"); @@ -3668,20 +3661,20 @@ // Tests that the network delegate can block and redirect a request to a new // URL during OnHeadersReceived. TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequestOnHeadersReceived) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; BlockingNetworkDelegate network_delegate( BlockingNetworkDelegate::AUTO_CALLBACK); network_delegate.set_block_on(BlockingNetworkDelegate::ON_HEADERS_RECEIVED); - GURL redirect_url(test_server_.GetURL("simple.html")); + GURL redirect_url(http_test_server()->GetURL("/simple.html")); network_delegate.set_redirect_on_headers_received_url(redirect_url); TestURLRequestContextWithProxy context( - test_server_.host_port_pair().ToString(), &network_delegate); + http_test_server()->host_port_pair().ToString(), &network_delegate); { - GURL original_url(test_server_.GetURL("empty.html")); + GURL original_url(http_test_server()->GetURL("/defaultresponse")); scoped_ptr<URLRequest> r( context.CreateRequest(original_url, DEFAULT_PRIORITY, &d)); @@ -3689,12 +3682,11 @@ base::RunLoop().Run(); EXPECT_EQ(URLRequestStatus::SUCCESS, r->status().status()); - EXPECT_TRUE(r->proxy_server().Equals(test_server_.host_port_pair())); + EXPECT_TRUE(r->proxy_server().Equals(http_test_server()->host_port_pair())); EXPECT_EQ( 2, network_delegate.observed_before_proxy_headers_sent_callbacks()); - EXPECT_TRUE( - network_delegate.last_observed_proxy().Equals( - test_server_.host_port_pair())); + EXPECT_TRUE(network_delegate.last_observed_proxy().Equals( + http_test_server()->host_port_pair())); EXPECT_EQ(OK, r->status().error()); EXPECT_EQ(redirect_url, r->url()); @@ -3711,7 +3703,7 @@ // handle the challenge, and is passing the buck along to the // URLRequest::Delegate. TEST_F(URLRequestTestHTTP, NetworkDelegateOnAuthRequiredSyncNoAction) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; BlockingNetworkDelegate network_delegate( @@ -3724,7 +3716,7 @@ d.set_credentials(AuthCredentials(kUser, kSecret)); { - GURL url(test_server_.GetURL("auth-basic")); + GURL url(http_test_server()->GetURL("/auth-basic")); scoped_ptr<URLRequest> r(context.CreateRequest(url, DEFAULT_PRIORITY, &d)); r->Start(); @@ -3742,7 +3734,7 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateOnAuthRequiredSyncNoAction_GetFullRequestHeaders) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; BlockingNetworkDelegate network_delegate( @@ -3755,7 +3747,7 @@ d.set_credentials(AuthCredentials(kUser, kSecret)); { - GURL url(test_server_.GetURL("auth-basic")); + GURL url(http_test_server()->GetURL("/auth-basic")); scoped_ptr<URLRequest> r(context.CreateRequest(url, DEFAULT_PRIORITY, &d)); r->Start(); @@ -3780,7 +3772,7 @@ // Tests that the network delegate can synchronously complete OnAuthRequired // by setting credentials. TEST_F(URLRequestTestHTTP, NetworkDelegateOnAuthRequiredSyncSetAuth) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; BlockingNetworkDelegate network_delegate( @@ -3796,7 +3788,7 @@ context.Init(); { - GURL url(test_server_.GetURL("auth-basic")); + GURL url(http_test_server()->GetURL("/auth-basic")); scoped_ptr<URLRequest> r(context.CreateRequest(url, DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); @@ -3815,7 +3807,7 @@ // headers (for the first or second request) when called at the proper times. TEST_F(URLRequestTestHTTP, NetworkDelegateOnAuthRequiredSyncSetAuth_GetFullRequestHeaders) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; BlockingNetworkDelegate network_delegate( @@ -3831,7 +3823,7 @@ context.Init(); { - GURL url(test_server_.GetURL("auth-basic")); + GURL url(http_test_server()->GetURL("/auth-basic")); scoped_ptr<URLRequest> r(context.CreateRequest(url, DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); @@ -3855,7 +3847,7 @@ // Tests that the network delegate can synchronously complete OnAuthRequired // by cancelling authentication. TEST_F(URLRequestTestHTTP, NetworkDelegateOnAuthRequiredSyncCancel) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; BlockingNetworkDelegate network_delegate( @@ -3869,7 +3861,7 @@ context.Init(); { - GURL url(test_server_.GetURL("auth-basic")); + GURL url(http_test_server()->GetURL("/auth-basic")); scoped_ptr<URLRequest> r(context.CreateRequest(url, DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); @@ -3889,7 +3881,7 @@ // to handle the challenge, and is passing the buck along to the // URLRequest::Delegate. TEST_F(URLRequestTestHTTP, NetworkDelegateOnAuthRequiredAsyncNoAction) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; BlockingNetworkDelegate network_delegate( @@ -3903,7 +3895,7 @@ d.set_credentials(AuthCredentials(kUser, kSecret)); { - GURL url(test_server_.GetURL("auth-basic")); + GURL url(http_test_server()->GetURL("/auth-basic")); scoped_ptr<URLRequest> r(context.CreateRequest(url, DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); @@ -3921,7 +3913,7 @@ // Tests that the network delegate can asynchronously complete OnAuthRequired // by setting credentials. TEST_F(URLRequestTestHTTP, NetworkDelegateOnAuthRequiredAsyncSetAuth) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; BlockingNetworkDelegate network_delegate( @@ -3938,7 +3930,7 @@ context.Init(); { - GURL url(test_server_.GetURL("auth-basic")); + GURL url(http_test_server()->GetURL("/auth-basic")); scoped_ptr<URLRequest> r(context.CreateRequest(url, DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); @@ -3957,7 +3949,7 @@ // Tests that the network delegate can asynchronously complete OnAuthRequired // by cancelling authentication. TEST_F(URLRequestTestHTTP, NetworkDelegateOnAuthRequiredAsyncCancel) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; BlockingNetworkDelegate network_delegate( @@ -3971,7 +3963,7 @@ context.Init(); { - GURL url(test_server_.GetURL("auth-basic")); + GURL url(http_test_server()->GetURL("/auth-basic")); scoped_ptr<URLRequest> r(context.CreateRequest(url, DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); @@ -3990,7 +3982,7 @@ // waiting for the network delegate. // Part 1: Request is cancelled while waiting for OnBeforeURLRequest callback. TEST_F(URLRequestTestHTTP, NetworkDelegateCancelWhileWaiting1) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; BlockingNetworkDelegate network_delegate( @@ -4003,7 +3995,7 @@ { scoped_ptr<URLRequest> r(context.CreateRequest( - test_server_.GetURL(std::string()), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); @@ -4026,7 +4018,7 @@ // waiting for the network delegate. // Part 2: Request is cancelled while waiting for OnBeforeSendHeaders callback. TEST_F(URLRequestTestHTTP, NetworkDelegateCancelWhileWaiting2) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; BlockingNetworkDelegate network_delegate( @@ -4040,7 +4032,7 @@ { scoped_ptr<URLRequest> r(context.CreateRequest( - test_server_.GetURL(std::string()), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); @@ -4063,7 +4055,7 @@ // waiting for the network delegate. // Part 3: Request is cancelled while waiting for OnHeadersReceived callback. TEST_F(URLRequestTestHTTP, NetworkDelegateCancelWhileWaiting3) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; BlockingNetworkDelegate network_delegate( @@ -4076,7 +4068,7 @@ { scoped_ptr<URLRequest> r(context.CreateRequest( - test_server_.GetURL(std::string()), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); @@ -4099,7 +4091,7 @@ // waiting for the network delegate. // Part 4: Request is cancelled while waiting for OnAuthRequired callback. TEST_F(URLRequestTestHTTP, NetworkDelegateCancelWhileWaiting4) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; BlockingNetworkDelegate network_delegate( @@ -4112,7 +4104,7 @@ { scoped_ptr<URLRequest> r(context.CreateRequest( - test_server_.GetURL("auth-basic"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/auth-basic"), DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); @@ -4131,15 +4123,37 @@ EXPECT_EQ(1, network_delegate.destroyed_requests()); } -// In this unit test, we're using the HTTPTestServer as a proxy server and +namespace { + +scoped_ptr<test_server::HttpResponse> HandleServerAuthConnect( + const test_server::HttpRequest& request) { + if (request.headers.find("Host") == request.headers.end() || + request.headers.at("Host") != "www.server-auth.com" || + request.method != test_server::METHOD_CONNECT) { + return nullptr; + } + + scoped_ptr<test_server::BasicHttpResponse> http_response( + new test_server::BasicHttpResponse); + http_response->set_code(HTTP_UNAUTHORIZED); + http_response->AddCustomHeader("WWW-Authenticate", + "Basic realm=\"WallyWorld\""); + return http_response.Pass(); +} + +} // namespace + +// In this unit test, we're using the EmbeddedTestServer as a proxy server and // issuing a CONNECT request with the magic host name "www.server-auth.com". -// The HTTPTestServer will return a 401 response, which we should balk at. +// The EmbeddedTestServer will return a 401 response, which we should balk at. TEST_F(URLRequestTestHTTP, UnexpectedServerAuthTest) { - ASSERT_TRUE(test_server_.Start()); + http_test_server()->RegisterRequestHandler( + base::Bind(&HandleServerAuthConnect)); + ASSERT_TRUE(http_test_server()->Start()); TestNetworkDelegate network_delegate; // Must outlive URLRequest. TestURLRequestContextWithProxy context( - test_server_.host_port_pair().ToString(), &network_delegate); + http_test_server()->host_port_pair().ToString(), &network_delegate); TestDelegate d; { @@ -4159,12 +4173,12 @@ } TEST_F(URLRequestTestHTTP, GetTest_NoCache) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL(std::string()), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -4174,9 +4188,9 @@ EXPECT_EQ(1, d.response_started_count()); EXPECT_FALSE(d.received_data_before_response()); EXPECT_NE(0, d.bytes_received()); - EXPECT_EQ(test_server_.host_port_pair().host(), + EXPECT_EQ(http_test_server()->host_port_pair().host(), r->GetSocketAddress().host()); - EXPECT_EQ(test_server_.host_port_pair().port(), + EXPECT_EQ(http_test_server()->host_port_pair().port(), r->GetSocketAddress().port()); // TODO(eroman): Add back the NetLog tests... @@ -4195,7 +4209,7 @@ #define MAYBE_GetTest_ManyCookies GetTest_ManyCookies #endif // defined(OS_WIN) TEST_F(URLRequestTestHTTP, MAYBE_GetTest_ManyCookies) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); int lower_bound = 0; int upper_bound = 1; @@ -4226,12 +4240,12 @@ } TEST_F(URLRequestTestHTTP, GetTest) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL(std::string()), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -4241,19 +4255,19 @@ EXPECT_EQ(1, d.response_started_count()); EXPECT_FALSE(d.received_data_before_response()); EXPECT_NE(0, d.bytes_received()); - EXPECT_EQ(test_server_.host_port_pair().host(), + EXPECT_EQ(http_test_server()->host_port_pair().host(), r->GetSocketAddress().host()); - EXPECT_EQ(test_server_.host_port_pair().port(), + EXPECT_EQ(http_test_server()->host_port_pair().port(), r->GetSocketAddress().port()); } } TEST_F(URLRequestTestHTTP, GetTest_GetFullRequestHeaders) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { - GURL test_url(test_server_.GetURL(std::string())); + GURL test_url(http_test_server()->GetURL("/defaultresponse")); scoped_ptr<URLRequest> r( default_context_.CreateRequest(test_url, DEFAULT_PRIORITY, &d)); @@ -4268,9 +4282,9 @@ EXPECT_EQ(1, d.response_started_count()); EXPECT_FALSE(d.received_data_before_response()); EXPECT_NE(0, d.bytes_received()); - EXPECT_EQ(test_server_.host_port_pair().host(), + EXPECT_EQ(http_test_server()->host_port_pair().host(), r->GetSocketAddress().host()); - EXPECT_EQ(test_server_.host_port_pair().port(), + EXPECT_EQ(http_test_server()->host_port_pair().port(), r->GetSocketAddress().port()); EXPECT_TRUE(d.have_full_request_headers()); @@ -4279,12 +4293,12 @@ } TEST_F(URLRequestTestHTTP, GetTestLoadTiming) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL(std::string()), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -4298,15 +4312,21 @@ EXPECT_EQ(1, d.response_started_count()); EXPECT_FALSE(d.received_data_before_response()); EXPECT_NE(0, d.bytes_received()); - EXPECT_EQ(test_server_.host_port_pair().host(), + EXPECT_EQ(http_test_server()->host_port_pair().host(), r->GetSocketAddress().host()); - EXPECT_EQ(test_server_.host_port_pair().port(), + EXPECT_EQ(http_test_server()->host_port_pair().port(), r->GetSocketAddress().port()); } } +// TODO(svaldez): Update tests to use EmbeddedTestServer. +#if !defined(OS_IOS) TEST_F(URLRequestTestHTTP, GetZippedTest) { - ASSERT_TRUE(test_server_.Start()); + SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, + SpawnedTestServer::kLocalhost, + base::FilePath(kTestFilePath)); + + ASSERT_TRUE(test_server.Start()); // Parameter that specifies the Content-Length field in the response: // C - Compressed length. @@ -4325,9 +4345,8 @@ for (int i = 0; i < num_tests ; i++) { TestDelegate d; { - std::string test_file = - base::StringPrintf("compressedfiles/BullRunSpeech.txt?%c", - test_parameters[i]); + std::string test_file = base::StringPrintf( + "compressedfiles/BullRunSpeech.txt?%c", test_parameters[i]); TestNetworkDelegate network_delegate; // Must outlive URLRequest. TestURLRequestContext context(true); @@ -4335,7 +4354,7 @@ context.Init(); scoped_ptr<URLRequest> r(context.CreateRequest( - test_server_.GetURL(test_file), DEFAULT_PRIORITY, &d)); + test_server.GetURL(test_file), DEFAULT_PRIORITY, &d)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -4357,9 +4376,10 @@ } } } +#endif // !defined(OS_IOS) TEST_F(URLRequestTestHTTP, NetworkQualityEstimator) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); // Enable requests to local host to be used for network quality estimation. std::map<std::string, std::string> variation_params; NetworkQualityEstimator estimator(scoped_ptr<net::ExternalEstimateProvider>(), @@ -4372,10 +4392,10 @@ context.set_network_delegate(&network_delegate); context.Init(); - std::string url = "echo.html"; + std::string url = "/defaultresponse"; - scoped_ptr<URLRequest> r( - context.CreateRequest(test_server_.GetURL(url), DEFAULT_PRIORITY, &d)); + scoped_ptr<URLRequest> r(context.CreateRequest( + http_test_server()->GetURL(url), DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); @@ -4402,11 +4422,11 @@ } TEST_F(URLRequestTestHTTP, RedirectLoadTiming) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); - GURL destination_url = test_server_.GetURL(std::string()); + GURL destination_url = http_test_server()->GetURL("/"); GURL original_url = - test_server_.GetURL("server-redirect?" + destination_url.spec()); + http_test_server()->GetURL("/server-redirect?" + destination_url.spec()); TestDelegate d; scoped_ptr<URLRequest> req( default_context_.CreateRequest(original_url, DEFAULT_PRIORITY, &d)); @@ -4441,13 +4461,13 @@ } TEST_F(URLRequestTestHTTP, MultipleRedirectTest) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); - GURL destination_url = test_server_.GetURL(std::string()); + GURL destination_url = http_test_server()->GetURL("/"); GURL middle_redirect_url = - test_server_.GetURL("server-redirect?" + destination_url.spec()); - GURL original_url = test_server_.GetURL( - "server-redirect?" + middle_redirect_url.spec()); + http_test_server()->GetURL("/server-redirect?" + destination_url.spec()); + GURL original_url = http_test_server()->GetURL("/server-redirect?" + + middle_redirect_url.spec()); TestDelegate d; scoped_ptr<URLRequest> req( default_context_.CreateRequest(original_url, DEFAULT_PRIORITY, &d)); @@ -4768,7 +4788,7 @@ // Tests handling of delegate info before a request starts. TEST_F(URLRequestTestHTTP, DelegateInfoBeforeStart) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate request_delegate; TestURLRequestContext context(true); @@ -4778,7 +4798,7 @@ { scoped_ptr<URLRequest> r( - context.CreateRequest(test_server_.GetURL("empty.html"), + context.CreateRequest(http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &request_delegate)); LoadStateWithParam load_state = r->GetLoadState(); EXPECT_EQ(LOAD_STATE_IDLE, load_state.state); @@ -4814,7 +4834,7 @@ // Tests handling of delegate info from a network delegate. TEST_F(URLRequestTestHTTP, NetworkDelegateInfo) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate request_delegate; AsyncLoggingNetworkDelegate network_delegate; @@ -4825,7 +4845,7 @@ { scoped_ptr<URLRequest> r( - context.CreateRequest(test_server_.GetURL("simple.html"), + context.CreateRequest(http_test_server()->GetURL("/simple.html"), DEFAULT_PRIORITY, &request_delegate)); LoadStateWithParam load_state = r->GetLoadState(); EXPECT_EQ(LOAD_STATE_IDLE, load_state.state); @@ -4871,7 +4891,7 @@ // Tests handling of delegate info from a network delegate in the case of an // HTTP redirect. TEST_F(URLRequestTestHTTP, NetworkDelegateInfoRedirect) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate request_delegate; AsyncLoggingNetworkDelegate network_delegate; @@ -4882,8 +4902,8 @@ { scoped_ptr<URLRequest> r(context.CreateRequest( - test_server_.GetURL("server-redirect?simple.html"), DEFAULT_PRIORITY, - &request_delegate)); + http_test_server()->GetURL("/server-redirect?simple.html"), + DEFAULT_PRIORITY, &request_delegate)); LoadStateWithParam load_state = r->GetLoadState(); EXPECT_EQ(LOAD_STATE_IDLE, load_state.state); EXPECT_EQ(base::string16(), load_state.param); @@ -4953,7 +4973,7 @@ // Tests handling of delegate info from a network delegate in the case of HTTP // AUTH. TEST_F(URLRequestTestHTTP, NetworkDelegateInfoAuth) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate request_delegate; AsyncLoggingNetworkDelegate network_delegate; @@ -4964,7 +4984,7 @@ { scoped_ptr<URLRequest> r( - context.CreateRequest(test_server_.GetURL("auth-basic"), + context.CreateRequest(http_test_server()->GetURL("/auth-basic"), DEFAULT_PRIORITY, &request_delegate)); LoadStateWithParam load_state = r->GetLoadState(); EXPECT_EQ(LOAD_STATE_IDLE, load_state.state); @@ -5010,9 +5030,15 @@ entries, log_position + 1, NetLog::TYPE_DELEGATE_INFO)); } +// TODO(svaldez): Update tests to use EmbeddedTestServer. +#if !defined(OS_IOS) // Tests handling of delegate info from a URLRequest::Delegate. TEST_F(URLRequestTestHTTP, URLRequestDelegateInfo) { - ASSERT_TRUE(test_server_.Start()); + SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, + SpawnedTestServer::kLocalhost, + base::FilePath(kTestFilePath)); + + ASSERT_TRUE(test_server.Start()); AsyncLoggingUrlRequestDelegate request_delegate( AsyncLoggingUrlRequestDelegate::NO_CANCEL); @@ -5028,7 +5054,7 @@ // the possibility of multiple reads being combined in the unlikely event // that it occurs. scoped_ptr<URLRequest> r(context.CreateRequest( - test_server_.GetURL("chunked?waitBetweenChunks=20"), DEFAULT_PRIORITY, + test_server.GetURL("/chunked?waitBetweenChunks=20"), DEFAULT_PRIORITY, &request_delegate)); LoadStateWithParam load_state = r->GetLoadState(); r->Start(); @@ -5066,11 +5092,12 @@ EXPECT_FALSE(LogContainsEntryWithTypeAfter( entries, log_position + 1, NetLog::TYPE_URL_REQUEST_DELEGATE)); } +#endif // !defined(OS_IOS) // Tests handling of delegate info from a URLRequest::Delegate in the case of // an HTTP redirect. TEST_F(URLRequestTestHTTP, URLRequestDelegateInfoOnRedirect) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); AsyncLoggingUrlRequestDelegate request_delegate( AsyncLoggingUrlRequestDelegate::NO_CANCEL); @@ -5081,8 +5108,8 @@ { scoped_ptr<URLRequest> r(context.CreateRequest( - test_server_.GetURL("server-redirect?simple.html"), DEFAULT_PRIORITY, - &request_delegate)); + http_test_server()->GetURL("/server-redirect?simple.html"), + DEFAULT_PRIORITY, &request_delegate)); LoadStateWithParam load_state = r->GetLoadState(); r->Start(); base::RunLoop().Run(); @@ -5126,7 +5153,7 @@ // Tests handling of delegate info from a URLRequest::Delegate in the case of // an HTTP redirect, with cancellation at various points. TEST_F(URLRequestTestHTTP, URLRequestDelegateOnRedirectCancelled) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); const AsyncLoggingUrlRequestDelegate::CancelStage kCancelStages[] = { AsyncLoggingUrlRequestDelegate::CANCEL_ON_RECEIVED_REDIRECT, @@ -5145,8 +5172,8 @@ { scoped_ptr<URLRequest> r(context.CreateRequest( - test_server_.GetURL("server-redirect?simple.html"), DEFAULT_PRIORITY, - &request_delegate)); + http_test_server()->GetURL("/server-redirect?simple.html"), + DEFAULT_PRIORITY, &request_delegate)); LoadStateWithParam load_state = r->GetLoadState(); r->Start(); base::RunLoop().Run(); @@ -5205,12 +5232,12 @@ } // namespace TEST_F(URLRequestTestHTTP, RedirectWithAdditionalHeadersTest) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); - GURL destination_url = test_server_.GetURL( - "echoheader?" + std::string(kExtraHeader)); - GURL original_url = test_server_.GetURL( - "server-redirect?" + destination_url.spec()); + GURL destination_url = + http_test_server()->GetURL("/echoheader?" + std::string(kExtraHeader)); + GURL original_url = + http_test_server()->GetURL("/server-redirect?" + destination_url.spec()); RedirectWithAdditionalHeadersDelegate d; scoped_ptr<URLRequest> req( default_context_.CreateRequest(original_url, DEFAULT_PRIORITY, &d)); @@ -5242,12 +5269,12 @@ } // namespace TEST_F(URLRequestTestHTTP, RedirectWithHeaderRemovalTest) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); - GURL destination_url = test_server_.GetURL( - "echoheader?" + std::string(kExtraHeaderToRemove)); - GURL original_url = test_server_.GetURL( - "server-redirect?" + destination_url.spec()); + GURL destination_url = http_test_server()->GetURL( + "/echoheader?" + std::string(kExtraHeaderToRemove)); + GURL original_url = + http_test_server()->GetURL("/server-redirect?" + destination_url.spec()); RedirectWithHeaderRemovalDelegate d; scoped_ptr<URLRequest> req( default_context_.CreateRequest(original_url, DEFAULT_PRIORITY, &d)); @@ -5285,12 +5312,12 @@ } TEST_F(URLRequestTestHTTP, CancelTest2) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL(std::string()), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d)); d.set_cancel_in_response_started(true); @@ -5307,12 +5334,12 @@ } TEST_F(URLRequestTestHTTP, CancelTest3) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL(std::string()), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d)); d.set_cancel_in_received_data(true); @@ -5332,12 +5359,12 @@ } TEST_F(URLRequestTestHTTP, CancelTest4) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL(std::string()), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -5358,13 +5385,13 @@ } TEST_F(URLRequestTestHTTP, CancelTest5) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); // populate cache { TestDelegate d; scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL("cachetime"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/cachetime"), DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); EXPECT_EQ(URLRequestStatus::SUCCESS, r->status().status()); @@ -5374,7 +5401,7 @@ { TestDelegate d; scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL("cachetime"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/cachetime"), DEFAULT_PRIORITY, &d)); r->Start(); r->Cancel(); base::RunLoop().Run(); @@ -5387,22 +5414,22 @@ } TEST_F(URLRequestTestHTTP, PostTest) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); HTTPUploadDataOperationTest("POST"); } TEST_F(URLRequestTestHTTP, PutTest) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); HTTPUploadDataOperationTest("PUT"); } TEST_F(URLRequestTestHTTP, PostEmptyTest) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL("echo"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d)); r->set_method("POST"); r->Start(); @@ -5420,12 +5447,12 @@ } TEST_F(URLRequestTestHTTP, PostFileTest) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL("echo"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d)); r->set_method("POST"); base::FilePath dir; @@ -5469,12 +5496,12 @@ } TEST_F(URLRequestTestHTTP, PostUnreadableFileTest) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL("echo"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d)); r->set_method("POST"); ScopedVector<UploadElementReader> element_readers; @@ -5501,12 +5528,12 @@ } TEST_F(URLRequestTestHTTP, TestPostChunkedDataBeforeStart) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL("echo"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d)); r->EnableChunkedUpload(); r->set_method("POST"); AddChunksToUpload(r.get()); @@ -5520,12 +5547,12 @@ } TEST_F(URLRequestTestHTTP, TestPostChunkedDataJustAfterStart) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL("echo"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d)); r->EnableChunkedUpload(); r->set_method("POST"); r->Start(); @@ -5538,12 +5565,12 @@ } TEST_F(URLRequestTestHTTP, TestPostChunkedDataAfterStart) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL("echo"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d)); r->EnableChunkedUpload(); r->set_method("POST"); r->Start(); @@ -5558,11 +5585,11 @@ } TEST_F(URLRequestTestHTTP, ResponseHeadersTest) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("files/with-headers.html"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/with-headers.html"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -5586,20 +5613,21 @@ EXPECT_EQ("a, b", header); } +// TODO(svaldez): iOS tests are flaky with EmbeddedTestServer and transport +// security state. (see http://crbug.com/550977). +#if !defined(OS_IOS) TEST_F(URLRequestTestHTTP, ProcessSTS) { - SpawnedTestServer::SSLOptions ssl_options( - SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); - SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS, - ssl_options, - base::FilePath(kTestFilePath)); + EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_test_server.SetSSLConfig( + net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN); + https_test_server.ServeFilesFromSourceDirectory( + base::FilePath(kTestFilePath)); ASSERT_TRUE(https_test_server.Start()); - std::string test_server_hostname = https_test_server.GetURL("").host(); - + std::string test_server_hostname = https_test_server.GetURL("/").host(); TestDelegate d; scoped_ptr<URLRequest> request(default_context_.CreateRequest( - https_test_server.GetURL("files/hsts-headers.html"), DEFAULT_PRIORITY, - &d)); + https_test_server.GetURL("/hsts-headers.html"), DEFAULT_PRIORITY, &d)); request->Start(); base::RunLoop().Run(); @@ -5623,22 +5651,20 @@ } TEST_F(URLRequestTestHTTP, STSNotProcessedOnIP) { - SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS, - SpawnedTestServer::SSLOptions(), - base::FilePath(kTestFilePath)); + EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_test_server.ServeFilesFromSourceDirectory( + base::FilePath(kTestFilePath)); ASSERT_TRUE(https_test_server.Start()); // Make sure this test fails if the test server is changed to not // listen on an IP by default. - ASSERT_TRUE(https_test_server.GetURL("").HostIsIPAddress()); - std::string test_server_hostname = https_test_server.GetURL("").host(); + ASSERT_TRUE(https_test_server.GetURL("/").HostIsIPAddress()); + std::string test_server_hostname = https_test_server.GetURL("/").host(); TestDelegate d; scoped_ptr<URLRequest> request(default_context_.CreateRequest( - https_test_server.GetURL("files/hsts-headers.html"), DEFAULT_PRIORITY, - &d)); + https_test_server.GetURL("/hsts-headers.html"), DEFAULT_PRIORITY, &d)); request->Start(); base::RunLoop().Run(); - TransportSecurityState* security_state = default_context_.transport_security_state(); TransportSecurityState::STSState sts_state; @@ -5671,22 +5697,20 @@ // validity/expiration. TEST_F(URLRequestTestHTTP, MAYBE_ProcessPKP) { GURL report_uri(kHPKPReportUri); - SpawnedTestServer::SSLOptions ssl_options( - SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); - SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS, - ssl_options, - base::FilePath(kTestFilePath)); + EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_test_server.SetSSLConfig( + net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN); + https_test_server.ServeFilesFromSourceDirectory( + base::FilePath(kTestFilePath)); ASSERT_TRUE(https_test_server.Start()); - std::string test_server_hostname = https_test_server.GetURL("").host(); + std::string test_server_hostname = https_test_server.GetURL("/").host(); TestDelegate d; scoped_ptr<URLRequest> request(default_context_.CreateRequest( - https_test_server.GetURL("files/hpkp-headers.html"), DEFAULT_PRIORITY, - &d)); + https_test_server.GetURL("/hpkp-headers.html"), DEFAULT_PRIORITY, &d)); request->Start(); base::RunLoop().Run(); - TransportSecurityState* security_state = default_context_.transport_security_state(); TransportSecurityState::STSState sts_state; @@ -5707,15 +5731,14 @@ // Tests that reports get sent on HPKP violations when a report-uri is set. TEST_F(URLRequestTestHTTP, MAYBE_ProcessPKPAndSendReport) { GURL report_uri(kHPKPReportUri); - SpawnedTestServer::SSLOptions ssl_options( - SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); - SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS, - ssl_options, - base::FilePath(kTestFilePath)); - + EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_test_server.SetSSLConfig( + net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN); + https_test_server.ServeFilesFromSourceDirectory( + base::FilePath(kTestFilePath)); ASSERT_TRUE(https_test_server.Start()); - std::string test_server_hostname = https_test_server.GetURL("").host(); + std::string test_server_hostname = https_test_server.GetURL("/").host(); // Set up a pin for |test_server_hostname|. TransportSecurityState security_state; @@ -5764,7 +5787,7 @@ // Now send a request to trigger the violation. TestDelegate d; scoped_ptr<URLRequest> violating_request(context.CreateRequest( - https_test_server.GetURL("files/simple.html"), DEFAULT_PRIORITY, &d)); + https_test_server.GetURL("/simple.html"), DEFAULT_PRIORITY, &d)); violating_request->Start(); base::RunLoop().Run(); @@ -5786,15 +5809,14 @@ // Public-Key-Pins-Report-Only headers. TEST_F(URLRequestTestHTTP, MAYBE_ProcessPKPReportOnly) { GURL report_uri(kHPKPReportUri); - SpawnedTestServer::SSLOptions ssl_options( - SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); - SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS, - ssl_options, - base::FilePath(kTestFilePath)); - + EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_test_server.SetSSLConfig( + net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN); + https_test_server.ServeFilesFromSourceDirectory( + base::FilePath(kTestFilePath)); ASSERT_TRUE(https_test_server.Start()); - std::string test_server_hostname = https_test_server.GetURL("").host(); + std::string test_server_hostname = https_test_server.GetURL("/").host(); TransportSecurityState security_state; MockCertificateReportSender mock_report_sender; @@ -5827,7 +5849,7 @@ // Now send a request to trigger the violation. TestDelegate d; scoped_ptr<URLRequest> violating_request(context.CreateRequest( - https_test_server.GetURL("files/hpkp-headers-report-only.html"), + https_test_server.GetURL("/hpkp-headers-report-only.html"), DEFAULT_PRIORITY, &d)); violating_request->Start(); base::RunLoop().Run(); @@ -5850,15 +5872,14 @@ // Public-Key-Pins-Report-Only headers that don't have pin violations. TEST_F(URLRequestTestHTTP, MAYBE_ProcessPKPReportOnlyWithNoViolation) { GURL report_uri(kHPKPReportUri); - SpawnedTestServer::SSLOptions ssl_options( - SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); - SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS, - ssl_options, - base::FilePath(kTestFilePath)); - + EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_test_server.SetSSLConfig( + net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN); + https_test_server.ServeFilesFromSourceDirectory( + base::FilePath(kTestFilePath)); ASSERT_TRUE(https_test_server.Start()); - std::string test_server_hostname = https_test_server.GetURL("").host(); + std::string test_server_hostname = https_test_server.GetURL("/").host(); TransportSecurityState security_state; MockCertificateReportSender mock_report_sender; @@ -5876,7 +5897,7 @@ // Now send a request that does not trigger the violation. TestDelegate d; scoped_ptr<URLRequest> request(context.CreateRequest( - https_test_server.GetURL("files/hpkp-headers-report-only.html"), + https_test_server.GetURL("/hpkp-headers-report-only.html"), DEFAULT_PRIORITY, &d)); request->Start(); base::RunLoop().Run(); @@ -5887,19 +5908,18 @@ } TEST_F(URLRequestTestHTTP, PKPNotProcessedOnIP) { - SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS, - SpawnedTestServer::SSLOptions(), - base::FilePath(kTestFilePath)); + EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_test_server.ServeFilesFromSourceDirectory( + base::FilePath(kTestFilePath)); ASSERT_TRUE(https_test_server.Start()); // Make sure this test fails if the test server is changed to not // listen on an IP by default. - ASSERT_TRUE(https_test_server.GetURL("").HostIsIPAddress()); - std::string test_server_hostname = https_test_server.GetURL("").host(); + ASSERT_TRUE(https_test_server.GetURL("/").HostIsIPAddress()); + std::string test_server_hostname = https_test_server.GetURL("/").host(); TestDelegate d; scoped_ptr<URLRequest> request(default_context_.CreateRequest( - https_test_server.GetURL("files/hpkp-headers.html"), DEFAULT_PRIORITY, - &d)); + https_test_server.GetURL("/hpkp-headers.html"), DEFAULT_PRIORITY, &d)); request->Start(); base::RunLoop().Run(); @@ -5911,19 +5931,19 @@ } TEST_F(URLRequestTestHTTP, ProcessSTSOnce) { - SpawnedTestServer::SSLOptions ssl_options( - SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); - SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS, - ssl_options, - base::FilePath(kTestFilePath)); + EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_test_server.SetSSLConfig( + net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN); + https_test_server.ServeFilesFromSourceDirectory( + base::FilePath(kTestFilePath)); ASSERT_TRUE(https_test_server.Start()); - std::string test_server_hostname = https_test_server.GetURL("").host(); + std::string test_server_hostname = https_test_server.GetURL("/").host(); TestDelegate d; scoped_ptr<URLRequest> request(default_context_.CreateRequest( - https_test_server.GetURL("files/hsts-multiple-headers.html"), - DEFAULT_PRIORITY, &d)); + https_test_server.GetURL("/hsts-multiple-headers.html"), DEFAULT_PRIORITY, + &d)); request->Start(); base::RunLoop().Run(); @@ -5940,19 +5960,19 @@ } TEST_F(URLRequestTestHTTP, ProcessSTSAndPKP) { - SpawnedTestServer::SSLOptions ssl_options( - SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); - SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS, - ssl_options, - base::FilePath(kTestFilePath)); + EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_test_server.SetSSLConfig( + net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN); + https_test_server.ServeFilesFromSourceDirectory( + base::FilePath(kTestFilePath)); ASSERT_TRUE(https_test_server.Start()); - std::string test_server_hostname = https_test_server.GetURL("").host(); + std::string test_server_hostname = https_test_server.GetURL("/").host(); TestDelegate d; scoped_ptr<URLRequest> request(default_context_.CreateRequest( - https_test_server.GetURL("files/hsts-and-hpkp-headers.html"), - DEFAULT_PRIORITY, &d)); + https_test_server.GetURL("/hsts-and-hpkp-headers.html"), DEFAULT_PRIORITY, + &d)); request->Start(); base::RunLoop().Run(); @@ -5984,18 +6004,18 @@ // Tests that when multiple HPKP headers are present, asserting different // policies, that only the first such policy is processed. TEST_F(URLRequestTestHTTP, ProcessSTSAndPKP2) { - SpawnedTestServer::SSLOptions ssl_options( - SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); - SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS, - ssl_options, - base::FilePath(kTestFilePath)); + EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_test_server.SetSSLConfig( + net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN); + https_test_server.ServeFilesFromSourceDirectory( + base::FilePath(kTestFilePath)); ASSERT_TRUE(https_test_server.Start()); - std::string test_server_hostname = https_test_server.GetURL("").host(); + std::string test_server_hostname = https_test_server.GetURL("/").host(); TestDelegate d; scoped_ptr<URLRequest> request(default_context_.CreateRequest( - https_test_server.GetURL("files/hsts-and-hpkp-headers2.html"), + https_test_server.GetURL("/hsts-and-hpkp-headers2.html"), DEFAULT_PRIORITY, &d)); request->Start(); base::RunLoop().Run(); @@ -6021,12 +6041,14 @@ EXPECT_FALSE(pkp_state.include_subdomains); } +#endif // !defined(OS_IOS) + TEST_F(URLRequestTestHTTP, ContentTypeNormalizationTest) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("files/content-type-normalization.html"), + http_test_server()->GetURL("/content-type-normalization.html"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -6064,11 +6086,11 @@ } TEST_F(URLRequestTestHTTP, RestrictFileRedirects) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("files/redirect-to-file.html"), DEFAULT_PRIORITY, + http_test_server()->GetURL("/redirect-to-file.html"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -6079,11 +6101,11 @@ #endif // !defined(DISABLE_FILE_SUPPORT) TEST_F(URLRequestTestHTTP, RestrictDataRedirects) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("files/redirect-to-data.html"), DEFAULT_PRIORITY, + http_test_server()->GetURL("/redirect-to-data.html"), DEFAULT_PRIORITY, &d)); req->Start(); base::MessageLoop::current()->Run(); @@ -6093,11 +6115,11 @@ } TEST_F(URLRequestTestHTTP, RedirectToInvalidURL) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("files/redirect-to-invalid-url.html"), + http_test_server()->GetURL("/redirect-to-invalid-url.html"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -6108,9 +6130,9 @@ // Make sure redirects are cached, despite not reading their bodies. TEST_F(URLRequestTestHTTP, CacheRedirect) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); GURL redirect_url = - test_server_.GetURL("files/redirect302-to-echo-cacheable"); + http_test_server()->GetURL("/redirect302-to-echo-cacheable"); { TestDelegate d; @@ -6120,7 +6142,7 @@ base::RunLoop().Run(); EXPECT_EQ(URLRequestStatus::SUCCESS, req->status().status()); EXPECT_EQ(1, d.received_redirect_count()); - EXPECT_EQ(test_server_.GetURL("echo"), req->url()); + EXPECT_EQ(http_test_server()->GetURL("/echo"), req->url()); } { @@ -6140,20 +6162,20 @@ EXPECT_EQ(1, d.received_redirect_count()); EXPECT_EQ(1, d.response_started_count()); EXPECT_EQ(URLRequestStatus::SUCCESS, req->status().status()); - EXPECT_EQ(test_server_.GetURL("echo"), req->url()); + EXPECT_EQ(http_test_server()->GetURL("/echo"), req->url()); } } // Make sure a request isn't cached when a NetworkDelegate forces a redirect // when the headers are read, since the body won't have been read. TEST_F(URLRequestTestHTTP, NoCacheOnNetworkDelegateRedirect) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); // URL that is normally cached. - GURL initial_url = test_server_.GetURL("cachetime"); + GURL initial_url = http_test_server()->GetURL("/cachetime"); { // Set up the TestNetworkDelegate tp force a redirect. - GURL redirect_to_url = test_server_.GetURL("echo"); + GURL redirect_to_url = http_test_server()->GetURL("/echo"); default_network_delegate_.set_redirect_on_headers_received_url( redirect_to_url); @@ -6184,7 +6206,7 @@ // Tests that redirection to an unsafe URL is allowed when it has been marked as // safe. TEST_F(URLRequestTestHTTP, UnsafeRedirectToWhitelistedUnsafeURL) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); GURL unsafe_url("data:text/html,this-is-considered-an-unsafe-url"); default_network_delegate_.set_redirect_on_headers_received_url(unsafe_url); @@ -6193,7 +6215,7 @@ TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL("whatever"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/whatever"), DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); @@ -6210,7 +6232,7 @@ // Tests that a redirect to a different unsafe URL is blocked, even after adding // some other URL to the whitelist. TEST_F(URLRequestTestHTTP, UnsafeRedirectToDifferentUnsafeURL) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); GURL unsafe_url("data:text/html,something"); GURL different_unsafe_url("data:text/html,something-else"); @@ -6221,7 +6243,7 @@ TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL("whatever"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/whatever"), DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); @@ -6234,9 +6256,9 @@ // Redirects from an URL with fragment to an unsafe URL with fragment should // be allowed, and the reference fragment of the target URL should be preserved. TEST_F(URLRequestTestHTTP, UnsafeRedirectWithDifferentReferenceFragment) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); - GURL original_url(test_server_.GetURL("original#fragment1")); + GURL original_url(http_test_server()->GetURL("/original#fragment1")); GURL unsafe_url("data:,url-marked-safe-and-used-in-redirect#fragment2"); GURL expected_url("data:,url-marked-safe-and-used-in-redirect#fragment2"); @@ -6262,12 +6284,13 @@ // When a delegate has specified a safe redirect URL, but it does not match the // redirect target, then do not prevent the reference fragment from being added. TEST_F(URLRequestTestHTTP, RedirectWithReferenceFragmentAndUnrelatedUnsafeUrl) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); - GURL original_url(test_server_.GetURL("original#expected-fragment")); + GURL original_url(http_test_server()->GetURL("/original#expected-fragment")); GURL unsafe_url("data:text/html,this-url-does-not-match-redirect-url"); - GURL redirect_url(test_server_.GetURL("target")); - GURL expected_redirect_url(test_server_.GetURL("target#expected-fragment")); + GURL redirect_url(http_test_server()->GetURL("/target")); + GURL expected_redirect_url( + http_test_server()->GetURL("/target#expected-fragment")); default_network_delegate_.set_redirect_on_headers_received_url(redirect_url); default_network_delegate_.set_allowed_unsafe_redirect_url(unsafe_url); @@ -6292,9 +6315,10 @@ // URL should not be changed. In particular, the reference fragment should not // be modified. TEST_F(URLRequestTestHTTP, RedirectWithReferenceFragment) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); - GURL original_url(test_server_.GetURL("original#should-not-be-appended")); + GURL original_url( + http_test_server()->GetURL("/original#should-not-be-appended")); GURL redirect_url("data:text/html,expect-no-reference-fragment"); default_network_delegate_.set_redirect_on_headers_received_url(redirect_url); @@ -6319,10 +6343,11 @@ // When a URLRequestRedirectJob is created, the redirection must be followed and // the reference fragment of the target URL must not be modified. TEST_F(URLRequestTestHTTP, RedirectJobWithReferenceFragment) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); - GURL original_url(test_server_.GetURL("original#should-not-be-appended")); - GURL redirect_url(test_server_.GetURL("echo")); + GURL original_url( + http_test_server()->GetURL("/original#should-not-be-appended")); + GURL redirect_url(http_test_server()->GetURL("/echo")); TestDelegate d; scoped_ptr<URLRequest> r( @@ -6343,11 +6368,11 @@ } TEST_F(URLRequestTestHTTP, NoUserPassInReferrer) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("echoheader?Referer"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d)); req->SetReferrer("http://user:pass@foo.com/"); req->Start(); base::RunLoop().Run(); @@ -6356,11 +6381,11 @@ } TEST_F(URLRequestTestHTTP, NoFragmentInReferrer) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("echoheader?Referer"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d)); req->SetReferrer("http://foo.com/test#fragment"); req->Start(); base::RunLoop().Run(); @@ -6369,11 +6394,11 @@ } TEST_F(URLRequestTestHTTP, EmptyReferrerAfterValidReferrer) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("echoheader?Referer"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d)); req->SetReferrer("http://foo.com/test#fragment"); req->SetReferrer(""); req->Start(); @@ -6385,12 +6410,12 @@ // Defer network start and then resume, checking that the request was a success // and bytes were received. TEST_F(URLRequestTestHTTP, DeferredBeforeNetworkStart) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { d.set_quit_on_network_start(true); - GURL test_url(test_server_.GetURL("echo")); + GURL test_url(http_test_server()->GetURL("/echo")); scoped_ptr<URLRequest> req( default_context_.CreateRequest(test_url, DEFAULT_PRIORITY, &d)); @@ -6412,14 +6437,15 @@ // Check that OnBeforeNetworkStart is only called once even if there is a // redirect. TEST_F(URLRequestTestHTTP, BeforeNetworkStartCalledOnce) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { d.set_quit_on_redirect(true); d.set_quit_on_network_start(true); scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("server-redirect?echo"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/server-redirect?echo"), DEFAULT_PRIORITY, + &d)); req->Start(); base::RunLoop().Run(); @@ -6447,12 +6473,12 @@ // Cancel the request after learning that the request would use the network. TEST_F(URLRequestTestHTTP, CancelOnBeforeNetworkStart) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { d.set_quit_on_network_start(true); - GURL test_url(test_server_.GetURL("echo")); + GURL test_url(http_test_server()->GetURL("/echo")); scoped_ptr<URLRequest> req( default_context_.CreateRequest(test_url, DEFAULT_PRIORITY, &d)); @@ -6472,13 +6498,14 @@ } TEST_F(URLRequestTestHTTP, CancelRedirect) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { d.set_cancel_in_received_redirect(true); scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("files/redirect-test.html"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/redirect-test.html"), DEFAULT_PRIORITY, + &d)); req->Start(); base::RunLoop().Run(); @@ -6490,12 +6517,12 @@ } TEST_F(URLRequestTestHTTP, DeferredRedirect) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { d.set_quit_on_redirect(true); - GURL test_url(test_server_.GetURL("files/redirect-test.html")); + GURL test_url(http_test_server()->GetURL("/redirect-test.html")); scoped_ptr<URLRequest> req( default_context_.CreateRequest(test_url, DEFAULT_PRIORITY, &d)); @@ -6523,12 +6550,12 @@ } TEST_F(URLRequestTestHTTP, DeferredRedirect_GetFullRequestHeaders) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { d.set_quit_on_redirect(true); - GURL test_url(test_server_.GetURL("files/redirect-test.html")); + GURL test_url(http_test_server()->GetURL("/redirect-test.html")); scoped_ptr<URLRequest> req( default_context_.CreateRequest(test_url, DEFAULT_PRIORITY, &d)); @@ -6545,7 +6572,7 @@ req->FollowDeferredRedirect(); base::RunLoop().Run(); - GURL target_url(test_server_.GetURL("files/with-headers.html")); + GURL target_url(http_test_server()->GetURL("/with-headers.html")); EXPECT_EQ(1, d.response_started_count()); EXPECT_TRUE(d.have_full_request_headers()); CheckFullRequestHeaders(d.full_request_headers(), target_url); @@ -6564,13 +6591,14 @@ } TEST_F(URLRequestTestHTTP, CancelDeferredRedirect) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; { d.set_quit_on_redirect(true); scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("files/redirect-test.html"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/redirect-test.html"), DEFAULT_PRIORITY, + &d)); req->Start(); base::RunLoop().Run(); @@ -6587,13 +6615,14 @@ } TEST_F(URLRequestTestHTTP, VaryHeader) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); // Populate the cache. { TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("echoheadercache?foo"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echoheadercache?foo"), DEFAULT_PRIORITY, + &d)); HttpRequestHeaders headers; headers.SetHeader("foo", "1"); req->SetExtraRequestHeaders(headers); @@ -6609,7 +6638,8 @@ { TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("echoheadercache?foo"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echoheadercache?foo"), DEFAULT_PRIORITY, + &d)); HttpRequestHeaders headers; headers.SetHeader("foo", "1"); req->SetExtraRequestHeaders(headers); @@ -6627,7 +6657,8 @@ { TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("echoheadercache?foo"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echoheadercache?foo"), DEFAULT_PRIORITY, + &d)); HttpRequestHeaders headers; headers.SetHeader("foo", "2"); req->SetExtraRequestHeaders(headers); @@ -6643,7 +6674,7 @@ } TEST_F(URLRequestTestHTTP, BasicAuth) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); // populate the cache { @@ -6651,7 +6682,7 @@ d.set_credentials(AuthCredentials(kUser, kSecret)); scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL("auth-basic"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/auth-basic"), DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); @@ -6667,7 +6698,7 @@ d.set_credentials(AuthCredentials(kUser, kSecret)); scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL("auth-basic"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/auth-basic"), DEFAULT_PRIORITY, &d)); r->SetLoadFlags(LOAD_VALIDATE_CACHE); r->Start(); @@ -6683,10 +6714,10 @@ // Check that Set-Cookie headers in 401 responses are respected. // http://crbug.com/6450 TEST_F(URLRequestTestHTTP, BasicAuthWithCookies) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); GURL url_requiring_auth = - test_server_.GetURL("auth-basic?set-cookie-if-challenged"); + http_test_server()->GetURL("/auth-basic?set-cookie-if-challenged"); // Request a page that will give a 401 containing a Set-Cookie header. // Verify that when the transaction is restarted, it includes the new cookie. @@ -6743,7 +6774,7 @@ // Tests that load timing works as expected with auth and the cache. TEST_F(URLRequestTestHTTP, BasicAuthLoadTiming) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); // populate the cache { @@ -6751,7 +6782,7 @@ d.set_credentials(AuthCredentials(kUser, kSecret)); scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL("auth-basic"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/auth-basic"), DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); @@ -6783,7 +6814,7 @@ d.set_credentials(AuthCredentials(kUser, kSecret)); scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL("auth-basic"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/auth-basic"), DEFAULT_PRIORITY, &d)); r->SetLoadFlags(LOAD_VALIDATE_CACHE); r->Start(); @@ -6807,13 +6838,14 @@ // Content-Type header. // http://code.google.com/p/chromium/issues/detail?id=843 TEST_F(URLRequestTestHTTP, Post302RedirectGet) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); const char kData[] = "hello world"; TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("files/redirect-to-echoall"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/redirect-to-echoall"), DEFAULT_PRIORITY, + &d)); req->set_method("POST"); req->set_upload(CreateSimpleUploadData(kData)); @@ -6855,11 +6887,11 @@ // https://crbug.com/465517. TEST_F(URLRequestTestHTTP, Redirect301Tests) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); - const GURL url = test_server_.GetURL("files/redirect301-to-echo"); + const GURL url = http_test_server()->GetURL("/redirect301-to-echo"); const GURL https_redirect_url = - test_server_.GetURL("files/redirect301-to-https"); + http_test_server()->GetURL("/redirect301-to-https"); HTTPRedirectMethodTest(url, "POST", "GET", true); HTTPRedirectMethodTest(url, "PUT", "PUT", true); @@ -6873,11 +6905,11 @@ } TEST_F(URLRequestTestHTTP, Redirect302Tests) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); - const GURL url = test_server_.GetURL("files/redirect302-to-echo"); + const GURL url = http_test_server()->GetURL("/redirect302-to-echo"); const GURL https_redirect_url = - test_server_.GetURL("files/redirect302-to-https"); + http_test_server()->GetURL("/redirect302-to-https"); HTTPRedirectMethodTest(url, "POST", "GET", true); HTTPRedirectMethodTest(url, "PUT", "PUT", true); @@ -6891,11 +6923,11 @@ } TEST_F(URLRequestTestHTTP, Redirect303Tests) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); - const GURL url = test_server_.GetURL("files/redirect303-to-echo"); + const GURL url = http_test_server()->GetURL("/redirect303-to-echo"); const GURL https_redirect_url = - test_server_.GetURL("files/redirect303-to-https"); + http_test_server()->GetURL("/redirect303-to-https"); HTTPRedirectMethodTest(url, "POST", "GET", true); HTTPRedirectMethodTest(url, "PUT", "GET", true); @@ -6909,11 +6941,11 @@ } TEST_F(URLRequestTestHTTP, Redirect307Tests) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); - const GURL url = test_server_.GetURL("files/redirect307-to-echo"); + const GURL url = http_test_server()->GetURL("/redirect307-to-echo"); const GURL https_redirect_url = - test_server_.GetURL("files/redirect307-to-https"); + http_test_server()->GetURL("/redirect307-to-https"); HTTPRedirectMethodTest(url, "POST", "POST", true); HTTPRedirectMethodTest(url, "PUT", "PUT", true); @@ -6926,11 +6958,11 @@ } TEST_F(URLRequestTestHTTP, Redirect308Tests) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); - const GURL url = test_server_.GetURL("files/redirect308-to-echo"); + const GURL url = http_test_server()->GetURL("/redirect308-to-echo"); const GURL https_redirect_url = - test_server_.GetURL("files/redirect308-to-https"); + http_test_server()->GetURL("/redirect308-to-https"); HTTPRedirectMethodTest(url, "POST", "POST", true); HTTPRedirectMethodTest(url, "PUT", "PUT", true); @@ -6946,10 +6978,10 @@ // Certain legacy apis that pre-date the response code expect this behavior // (Like Google Drive). TEST_F(URLRequestTestHTTP, NoRedirectOn308WithoutLocationHeader) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; - const GURL url = test_server_.GetURL("files/308-without-location-header"); + const GURL url = http_test_server()->GetURL("/308-without-location-header"); scoped_ptr<URLRequest> request( default_context_.CreateRequest(url, DEFAULT_PRIORITY, &d)); @@ -6964,10 +6996,11 @@ } TEST_F(URLRequestTestHTTP, Redirect302PreserveReferenceFragment) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); - GURL original_url(test_server_.GetURL("files/redirect302-to-echo#fragment")); - GURL expected_url(test_server_.GetURL("echo#fragment")); + GURL original_url( + http_test_server()->GetURL("/redirect302-to-echo#fragment")); + GURL expected_url(http_test_server()->GetURL("/echo#fragment")); TestDelegate d; { @@ -6986,9 +7019,9 @@ } TEST_F(URLRequestTestHTTP, RedirectPreserveFirstPartyURL) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); - GURL url(test_server_.GetURL("files/redirect302-to-echo")); + GURL url(http_test_server()->GetURL("/redirect302-to-echo")); GURL first_party_url("http://example.com"); TestDelegate d; @@ -7008,11 +7041,11 @@ } TEST_F(URLRequestTestHTTP, RedirectUpdateFirstPartyURL) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); - GURL url(test_server_.GetURL("files/redirect302-to-echo")); + GURL url(http_test_server()->GetURL("/redirect302-to-echo")); GURL original_first_party_url("http://example.com"); - GURL expected_first_party_url(test_server_.GetURL("echo")); + GURL expected_first_party_url(http_test_server()->GetURL("/echo")); TestDelegate d; { @@ -7033,13 +7066,13 @@ } TEST_F(URLRequestTestHTTP, InterceptPost302RedirectGet) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); const char kData[] = "hello world"; TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("empty.html"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d)); req->set_method("POST"); req->set_upload(CreateSimpleUploadData(kData)); HttpRequestHeaders headers; @@ -7048,7 +7081,8 @@ req->SetExtraRequestHeaders(headers); URLRequestRedirectJob* job = new URLRequestRedirectJob( - req.get(), &default_network_delegate_, test_server_.GetURL("echo"), + req.get(), &default_network_delegate_, + http_test_server()->GetURL("/echo"), URLRequestRedirectJob::REDIRECT_302_FOUND, "Very Good Reason"); AddTestInterceptor()->set_main_intercept_job(job); @@ -7058,13 +7092,13 @@ } TEST_F(URLRequestTestHTTP, InterceptPost307RedirectPost) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); const char kData[] = "hello world"; TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("empty.html"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d)); req->set_method("POST"); req->set_upload(CreateSimpleUploadData(kData)); HttpRequestHeaders headers; @@ -7073,7 +7107,8 @@ req->SetExtraRequestHeaders(headers); URLRequestRedirectJob* job = new URLRequestRedirectJob( - req.get(), &default_network_delegate_, test_server_.GetURL("echo"), + req.get(), &default_network_delegate_, + http_test_server()->GetURL("/echo"), URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT, "Very Good Reason"); AddTestInterceptor()->set_main_intercept_job(job); @@ -7086,7 +7121,7 @@ // Check that default A-L header is sent. TEST_F(URLRequestTestHTTP, DefaultAcceptLanguage) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); StaticHttpUserAgentSettings settings("en", std::string()); TestNetworkDelegate network_delegate; // Must outlive URLRequests. @@ -7097,7 +7132,8 @@ TestDelegate d; scoped_ptr<URLRequest> req(context.CreateRequest( - test_server_.GetURL("echoheader?Accept-Language"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echoheader?Accept-Language"), + DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); EXPECT_EQ("en", d.data_received()); @@ -7105,7 +7141,7 @@ // Check that an empty A-L header is not sent. http://crbug.com/77365. TEST_F(URLRequestTestHTTP, EmptyAcceptLanguage) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); std::string empty_string; // Avoid most vexing parse on line below. StaticHttpUserAgentSettings settings(empty_string, empty_string); @@ -7119,7 +7155,8 @@ TestDelegate d; scoped_ptr<URLRequest> req(context.CreateRequest( - test_server_.GetURL("echoheader?Accept-Language"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echoheader?Accept-Language"), + DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); EXPECT_EQ("None", d.data_received()); @@ -7128,11 +7165,12 @@ // Check that if request overrides the A-L header, the default is not appended. // See http://crbug.com/20894 TEST_F(URLRequestTestHTTP, OverrideAcceptLanguage) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("echoheader?Accept-Language"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echoheader?Accept-Language"), + DEFAULT_PRIORITY, &d)); HttpRequestHeaders headers; headers.SetHeader(HttpRequestHeaders::kAcceptLanguage, "ru"); req->SetExtraRequestHeaders(headers); @@ -7143,11 +7181,12 @@ // Check that default A-E header is sent. TEST_F(URLRequestTestHTTP, DefaultAcceptEncoding) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("echoheader?Accept-Encoding"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echoheader?Accept-Encoding"), + DEFAULT_PRIORITY, &d)); HttpRequestHeaders headers; req->SetExtraRequestHeaders(headers); req->Start(); @@ -7158,11 +7197,12 @@ // Check that if request overrides the A-E header, the default is not appended. // See http://crbug.com/47381 TEST_F(URLRequestTestHTTP, OverrideAcceptEncoding) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("echoheader?Accept-Encoding"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echoheader?Accept-Encoding"), + DEFAULT_PRIORITY, &d)); HttpRequestHeaders headers; headers.SetHeader(HttpRequestHeaders::kAcceptEncoding, "identity"); req->SetExtraRequestHeaders(headers); @@ -7174,11 +7214,12 @@ // Check that setting the A-C header sends the proper header. TEST_F(URLRequestTestHTTP, SetAcceptCharset) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("echoheader?Accept-Charset"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echoheader?Accept-Charset"), + DEFAULT_PRIORITY, &d)); HttpRequestHeaders headers; headers.SetHeader(HttpRequestHeaders::kAcceptCharset, "koi-8r"); req->SetExtraRequestHeaders(headers); @@ -7189,11 +7230,12 @@ // Check that default User-Agent header is sent. TEST_F(URLRequestTestHTTP, DefaultUserAgent) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("echoheader?User-Agent"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echoheader?User-Agent"), DEFAULT_PRIORITY, + &d)); req->Start(); base::RunLoop().Run(); EXPECT_EQ(default_context_.http_user_agent_settings()->GetUserAgent(), @@ -7203,11 +7245,12 @@ // Check that if request overrides the User-Agent header, // the default is not appended. TEST_F(URLRequestTestHTTP, OverrideUserAgent) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("echoheader?User-Agent"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/echoheader?User-Agent"), DEFAULT_PRIORITY, + &d)); HttpRequestHeaders headers; headers.SetHeader(HttpRequestHeaders::kUserAgent, "Lynx (textmode)"); req->SetExtraRequestHeaders(headers); @@ -7220,7 +7263,7 @@ // User-Agent header to be sent but does not send the Accept-Language and // Accept-Charset headers. TEST_F(URLRequestTestHTTP, EmptyHttpUserAgentSettings) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestNetworkDelegate network_delegate; // Must outlive URLRequests. TestURLRequestContext context(true); @@ -7233,14 +7276,14 @@ struct { const char* request; const char* expected_response; - } tests[] = { { "echoheader?Accept-Language", "None" }, - { "echoheader?Accept-Charset", "None" }, - { "echoheader?User-Agent", "" } }; + } tests[] = {{"/echoheader?Accept-Language", "None"}, + {"/echoheader?Accept-Charset", "None"}, + {"/echoheader?User-Agent", ""}}; for (size_t i = 0; i < arraysize(tests); i++) { TestDelegate d; scoped_ptr<URLRequest> req(context.CreateRequest( - test_server_.GetURL(tests[i].request), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL(tests[i].request), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); EXPECT_EQ(tests[i].expected_response, d.data_received()) @@ -7251,17 +7294,17 @@ // Make sure that URLRequest passes on its priority updates to // newly-created jobs after the first one. TEST_F(URLRequestTestHTTP, SetSubsequentJobPriority) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("empty.html"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d)); EXPECT_EQ(DEFAULT_PRIORITY, req->priority()); - scoped_refptr<URLRequestRedirectJob> redirect_job = - new URLRequestRedirectJob( - req.get(), &default_network_delegate_, test_server_.GetURL("echo"), - URLRequestRedirectJob::REDIRECT_302_FOUND, "Very Good Reason"); + scoped_refptr<URLRequestRedirectJob> redirect_job = new URLRequestRedirectJob( + req.get(), &default_network_delegate_, + http_test_server()->GetURL("/echo"), + URLRequestRedirectJob::REDIRECT_302_FOUND, "Very Good Reason"); AddTestInterceptor()->set_main_intercept_job(redirect_job.get()); req->SetPriority(LOW); @@ -7369,10 +7412,10 @@ } TEST_F(URLRequestTestHTTP, NetworkAccessedSetOnNetworkRequest) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; - GURL test_url(test_server_.GetURL(std::string())); + GURL test_url(http_test_server()->GetURL("/")); scoped_ptr<URLRequest> req( default_context_.CreateRequest(test_url, DEFAULT_PRIORITY, &d)); @@ -7383,12 +7426,12 @@ } TEST_F(URLRequestTestHTTP, NetworkAccessedClearOnCachedResponse) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); // Populate the cache. TestDelegate d; scoped_ptr<URLRequest> req(default_context_.CreateRequest( - test_server_.GetURL("cachetime"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/cachetime"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -7396,7 +7439,7 @@ EXPECT_TRUE(req->response_info().network_accessed); EXPECT_FALSE(req->response_info().was_cached); - req = default_context_.CreateRequest(test_server_.GetURL("cachetime"), + req = default_context_.CreateRequest(http_test_server()->GetURL("/cachetime"), DEFAULT_PRIORITY, &d); req->Start(); base::RunLoop().Run(); @@ -7407,10 +7450,10 @@ } TEST_F(URLRequestTestHTTP, NetworkAccessedClearOnLoadOnlyFromCache) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; - GURL test_url(test_server_.GetURL(std::string())); + GURL test_url(http_test_server()->GetURL("/")); scoped_ptr<URLRequest> req( default_context_.CreateRequest(test_url, DEFAULT_PRIORITY, &d)); req->SetLoadFlags(LOAD_ONLY_FROM_CACHE); @@ -7449,11 +7492,11 @@ interceptor()->set_redirect_headers(MockURLRequestInterceptor::ok_headers()); interceptor()->set_redirect_data(MockURLRequestInterceptor::ok_data()); - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context().CreateRequest( - test_server()->GetURL("files/redirect-test.html"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/redirect-test.html"), DEFAULT_PRIORITY, &d)); req->Start(); base::RunLoop().Run(); @@ -7480,11 +7523,11 @@ interceptor()->set_final_data(MockURLRequestInterceptor::ok_data()); default_network_delegate()->set_can_be_intercepted_on_error(true); - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context().CreateRequest( - test_server()->GetURL("files/two-content-lengths.html"), DEFAULT_PRIORITY, + http_test_server()->GetURL("/two-content-lengths.html"), DEFAULT_PRIORITY, &d)); req->set_method("GET"); req->Start(); @@ -7513,11 +7556,11 @@ // Intercept with a real URLRequestHttpJob. interceptor()->set_use_url_request_http_job(true); - ASSERT_TRUE(test_server()->Start()); + ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; scoped_ptr<URLRequest> req(default_context().CreateRequest( - test_server()->GetURL("files/simple.html"), DEFAULT_PRIORITY, &d)); + http_test_server()->GetURL("/simple.html"), DEFAULT_PRIORITY, &d)); req->set_method("GET"); req->Start(); base::RunLoop().Run(); @@ -7541,29 +7584,35 @@ public: URLRequestTestReferrerPolicy() {} - void InstantiateSameOriginServers(SpawnedTestServer::Type origin_type) { - origin_server_.reset(new SpawnedTestServer( - origin_type, SpawnedTestServer::kLocalhost, - origin_type == SpawnedTestServer::TYPE_HTTPS - ? base::FilePath(FILE_PATH_LITERAL("net/data/ssl")) - : base::FilePath(kTestFilePath))); + void InstantiateSameOriginServers(net::EmbeddedTestServer::Type type) { + origin_server_.reset(new EmbeddedTestServer(type)); + if (type == net::EmbeddedTestServer::TYPE_HTTPS) { + origin_server_->AddDefaultHandlers( + base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + } else { + origin_server_->AddDefaultHandlers(base::FilePath(kTestFilePath)); + } ASSERT_TRUE(origin_server_->Start()); } - void InstantiateCrossOriginServers(SpawnedTestServer::Type origin_type, - SpawnedTestServer::Type destination_type) { - origin_server_.reset(new SpawnedTestServer( - origin_type, SpawnedTestServer::kLocalhost, - origin_type == SpawnedTestServer::TYPE_HTTPS - ? base::FilePath(FILE_PATH_LITERAL("net/data/ssl")) - : base::FilePath(kTestFilePath))); + void InstantiateCrossOriginServers(net::EmbeddedTestServer::Type origin_type, + net::EmbeddedTestServer::Type dest_type) { + origin_server_.reset(new EmbeddedTestServer(origin_type)); + if (origin_type == net::EmbeddedTestServer::TYPE_HTTPS) { + origin_server_->AddDefaultHandlers( + base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + } else { + origin_server_->AddDefaultHandlers(base::FilePath(kTestFilePath)); + } ASSERT_TRUE(origin_server_->Start()); - destination_server_.reset(new SpawnedTestServer( - destination_type, SpawnedTestServer::kLocalhost, - destination_type == SpawnedTestServer::TYPE_HTTPS - ? base::FilePath(FILE_PATH_LITERAL("net/data/ssl")) - : base::FilePath(kTestFilePath))); + destination_server_.reset(new EmbeddedTestServer(dest_type)); + if (dest_type == net::EmbeddedTestServer::TYPE_HTTPS) { + destination_server_->AddDefaultHandlers( + base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + } else { + destination_server_->AddDefaultHandlers(base::FilePath(kTestFilePath)); + } ASSERT_TRUE(destination_server_->Start()); } @@ -7574,10 +7623,10 @@ // if the origins are meant to be distinct. Otherwise, we'll use the // |origin_server_| for both endpoints. GURL destination_url = - destination_server_ ? destination_server_->GetURL("echoheader?Referer") - : origin_server_->GetURL("echoheader?Referer"); + destination_server_ ? destination_server_->GetURL("/echoheader?Referer") + : origin_server_->GetURL("/echoheader?Referer"); GURL origin_url = - origin_server_->GetURL("server-redirect?" + destination_url.spec()); + origin_server_->GetURL("/server-redirect?" + destination_url.spec()); TestDelegate d; scoped_ptr<URLRequest> req( @@ -7600,175 +7649,151 @@ EXPECT_EQ(expected.spec(), d.data_received()); } - SpawnedTestServer* origin_server() const { return origin_server_.get(); } + EmbeddedTestServer* origin_server() const { return origin_server_.get(); } private: - scoped_ptr<SpawnedTestServer> origin_server_; - scoped_ptr<SpawnedTestServer> destination_server_; + scoped_ptr<EmbeddedTestServer> origin_server_; + scoped_ptr<EmbeddedTestServer> destination_server_; }; TEST_F(URLRequestTestReferrerPolicy, HTTPToSameOriginHTTP) { - InstantiateSameOriginServers(SpawnedTestServer::TYPE_HTTP); + InstantiateSameOriginServers(net::EmbeddedTestServer::TYPE_HTTP); VerifyReferrerAfterRedirect( URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL("path/to/file.html")); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/path/to/file.html")); VerifyReferrerAfterRedirect( URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL("path/to/file.html")); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/path/to/file.html")); VerifyReferrerAfterRedirect( URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL("path/to/file.html")); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/path/to/file.html")); VerifyReferrerAfterRedirect(URLRequest::NEVER_CLEAR_REFERRER, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL("path/to/file.html")); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/path/to/file.html")); } -// Can't spin up more than one SpawnedTestServer on Android. -#if defined(OS_ANDROID) -#define MAYBE_HTTPToCrossOriginHTTP DISABLED_HTTPToCrosOriginHTTP -#else -#define MAYBE_HTTPToCrossOriginHTTP HTTPToCrossOriginHTTP -#endif -TEST_F(URLRequestTestReferrerPolicy, MAYBE_HTTPToCrossOriginHTTP) { - InstantiateCrossOriginServers(SpawnedTestServer::TYPE_HTTP, - SpawnedTestServer::TYPE_HTTP); +TEST_F(URLRequestTestReferrerPolicy, HTTPToCrossOriginHTTP) { + InstantiateCrossOriginServers(net::EmbeddedTestServer::TYPE_HTTP, + net::EmbeddedTestServer::TYPE_HTTP); VerifyReferrerAfterRedirect( URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL("path/to/file.html")); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/path/to/file.html")); VerifyReferrerAfterRedirect( URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL(std::string())); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/")); VerifyReferrerAfterRedirect( URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL(std::string())); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/")); VerifyReferrerAfterRedirect(URLRequest::NEVER_CLEAR_REFERRER, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL("path/to/file.html")); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/path/to/file.html")); } TEST_F(URLRequestTestReferrerPolicy, HTTPSToSameOriginHTTPS) { - InstantiateSameOriginServers(SpawnedTestServer::TYPE_HTTPS); + InstantiateSameOriginServers(net::EmbeddedTestServer::TYPE_HTTPS); VerifyReferrerAfterRedirect( URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL("path/to/file.html")); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/path/to/file.html")); VerifyReferrerAfterRedirect( URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL("path/to/file.html")); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/path/to/file.html")); VerifyReferrerAfterRedirect( URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL("path/to/file.html")); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/path/to/file.html")); VerifyReferrerAfterRedirect(URLRequest::NEVER_CLEAR_REFERRER, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL("path/to/file.html")); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/path/to/file.html")); } -// Can't spin up more than one SpawnedTestServer on Android. -#if defined(OS_ANDROID) -#define MAYBE_HTTPSToCrossOriginHTTPS DISABLED_HTTPSToCrosOriginHTTPS -#else -#define MAYBE_HTTPSToCrossOriginHTTPS HTTPSToCrossOriginHTTPS -#endif -TEST_F(URLRequestTestReferrerPolicy, MAYBE_HTTPSToCrossOriginHTTPS) { - InstantiateCrossOriginServers(SpawnedTestServer::TYPE_HTTPS, - SpawnedTestServer::TYPE_HTTPS); +TEST_F(URLRequestTestReferrerPolicy, HTTPSToCrossOriginHTTPS) { + InstantiateCrossOriginServers(net::EmbeddedTestServer::TYPE_HTTPS, + net::EmbeddedTestServer::TYPE_HTTPS); VerifyReferrerAfterRedirect( URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL("path/to/file.html")); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/path/to/file.html")); VerifyReferrerAfterRedirect( URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL(std::string())); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/")); VerifyReferrerAfterRedirect( URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL(std::string())); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/")); VerifyReferrerAfterRedirect(URLRequest::NEVER_CLEAR_REFERRER, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL("path/to/file.html")); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/path/to/file.html")); } -// Can't spin up more than one SpawnedTestServer on Android. -#if defined(OS_ANDROID) -#define MAYBE_HTTPToHTTPS DISABLED_HTTPToHTTPS -#else -#define MAYBE_HTTPToHTTPS HTTPToHTTPS -#endif -TEST_F(URLRequestTestReferrerPolicy, MAYBE_HTTPToHTTPS) { - InstantiateCrossOriginServers(SpawnedTestServer::TYPE_HTTP, - SpawnedTestServer::TYPE_HTTPS); +TEST_F(URLRequestTestReferrerPolicy, HTTPToHTTPS) { + InstantiateCrossOriginServers(net::EmbeddedTestServer::TYPE_HTTP, + net::EmbeddedTestServer::TYPE_HTTPS); VerifyReferrerAfterRedirect( URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL("path/to/file.html")); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/path/to/file.html")); VerifyReferrerAfterRedirect( URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL(std::string())); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/")); VerifyReferrerAfterRedirect( URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL(std::string())); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/")); VerifyReferrerAfterRedirect(URLRequest::NEVER_CLEAR_REFERRER, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL("path/to/file.html")); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/path/to/file.html")); } -// Can't spin up more than one SpawnedTestServer on Android. -#if defined(OS_ANDROID) -#define MAYBE_HTTPSToHTTP DISABLED_HTTPSToHTTP -#else -#define MAYBE_HTTPSToHTTP HTTPSToHTTP -#endif -TEST_F(URLRequestTestReferrerPolicy, MAYBE_HTTPSToHTTP) { - InstantiateCrossOriginServers(SpawnedTestServer::TYPE_HTTPS, - SpawnedTestServer::TYPE_HTTP); +TEST_F(URLRequestTestReferrerPolicy, HTTPSToHTTP) { + InstantiateCrossOriginServers(net::EmbeddedTestServer::TYPE_HTTPS, + net::EmbeddedTestServer::TYPE_HTTP); VerifyReferrerAfterRedirect( URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, - origin_server()->GetURL("path/to/file.html"), GURL()); + origin_server()->GetURL("/path/to/file.html"), GURL()); VerifyReferrerAfterRedirect( URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, - origin_server()->GetURL("path/to/file.html"), GURL()); + origin_server()->GetURL("/path/to/file.html"), GURL()); VerifyReferrerAfterRedirect( URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL(std::string())); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/")); VerifyReferrerAfterRedirect(URLRequest::NEVER_CLEAR_REFERRER, - origin_server()->GetURL("path/to/file.html"), - origin_server()->GetURL("path/to/file.html")); + origin_server()->GetURL("/path/to/file.html"), + origin_server()->GetURL("/path/to/file.html")); } class HTTPSRequestTest : public testing::Test { @@ -7785,16 +7810,15 @@ }; TEST_F(HTTPSRequestTest, HTTPSGetTest) { - SpawnedTestServer test_server( - SpawnedTestServer::TYPE_HTTPS, - SpawnedTestServer::kLocalhost, + EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS); + test_server.AddDefaultHandlers( base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); ASSERT_TRUE(test_server.Start()); TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server.GetURL(std::string()), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -7812,11 +7836,9 @@ } TEST_F(HTTPSRequestTest, HTTPSMismatchedTest) { - SpawnedTestServer::SSLOptions ssl_options( - SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME); - SpawnedTestServer test_server( - SpawnedTestServer::TYPE_HTTPS, - ssl_options, + EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS); + test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME); + test_server.AddDefaultHandlers( base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); ASSERT_TRUE(test_server.Start()); @@ -7826,7 +7848,7 @@ { d.set_allow_certificate_errors(err_allowed); scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server.GetURL(std::string()), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -7847,11 +7869,9 @@ } TEST_F(HTTPSRequestTest, HTTPSExpiredTest) { - SpawnedTestServer::SSLOptions ssl_options( - SpawnedTestServer::SSLOptions::CERT_EXPIRED); - SpawnedTestServer test_server( - SpawnedTestServer::TYPE_HTTPS, - ssl_options, + EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS); + test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED); + test_server.AddDefaultHandlers( base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); ASSERT_TRUE(test_server.Start()); @@ -7863,7 +7883,7 @@ { d.set_allow_certificate_errors(err_allowed); scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server.GetURL(std::string()), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -7883,16 +7903,16 @@ } } +// TODO(svaldez): iOS tests are flaky with EmbeddedTestServer and transport +// security state. (see http://crbug.com/550977). +#if !defined(OS_IOS) // This tests that a load of www.google.com with a certificate error sets // the |certificate_errors_are_fatal| flag correctly. This flag will cause // the interstitial to be fatal. TEST_F(HTTPSRequestTest, HTTPSPreloadedHSTSTest) { - SpawnedTestServer::SSLOptions ssl_options( - SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME); - SpawnedTestServer test_server( - SpawnedTestServer::TYPE_HTTPS, - ssl_options, - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS); + test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME); + test_server.ServeFilesFromSourceDirectory("net/data/ssl"); ASSERT_TRUE(test_server.Start()); // We require that the URL be www.google.com in order to pick up the @@ -7931,12 +7951,9 @@ TEST_F(HTTPSRequestTest, HTTPSErrorsNoClobberTSSTest) { // The actual problem -- CERT_MISMATCHED_NAME in this case -- doesn't // matter. It just has to be any error. - SpawnedTestServer::SSLOptions ssl_options( - SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME); - SpawnedTestServer test_server( - SpawnedTestServer::TYPE_HTTPS, - ssl_options, - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS); + test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME); + test_server.ServeFilesFromSourceDirectory("net/data/ssl"); ASSERT_TRUE(test_server.Start()); // We require that the URL be www.google.com in order to pick up the static @@ -8008,18 +8025,15 @@ TEST_F(HTTPSRequestTest, HSTSPreservesPosts) { static const char kData[] = "hello world"; - SpawnedTestServer::SSLOptions ssl_options( - SpawnedTestServer::SSLOptions::CERT_OK); - SpawnedTestServer test_server( - SpawnedTestServer::TYPE_HTTPS, - ssl_options, + EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS); + test_server.AddDefaultHandlers( base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); ASSERT_TRUE(test_server.Start()); // Per spec, TransportSecurityState expects a domain name, rather than an IP // address, so a MockHostResolver is needed to redirect www.somewhere.com to - // the SpawnedTestServer. By default, MockHostResolver maps all hosts + // the EmbeddedTestServer. By default, MockHostResolver maps all hosts // to 127.0.0.1. MockHostResolver host_resolver; @@ -8067,17 +8081,14 @@ TEST_F(HTTPSRequestTest, HSTSCrossOriginAddHeaders) { static const char kOriginHeaderValue[] = "http://www.example.com"; - SpawnedTestServer::SSLOptions ssl_options( - SpawnedTestServer::SSLOptions::CERT_OK); - SpawnedTestServer test_server( - SpawnedTestServer::TYPE_HTTPS, - ssl_options, - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS); + test_server.ServeFilesFromSourceDirectory("net/data/ssl"); ASSERT_TRUE(test_server.Start()); // Per spec, TransportSecurityState expects a domain name, rather than an IP // address, so a MockHostResolver is needed to redirect example.net to the - // SpawnedTestServer. MockHostResolver maps all hosts to 127.0.0.1 by default. + // EmbeddedTestServer. MockHostResolver maps all hosts to 127.0.0.1 by + // default. MockHostResolver host_resolver; TransportSecurityState transport_security_state; @@ -8177,18 +8188,18 @@ // - Getting a certificate request in an SSL renegotiation sending the // HTTP request. TEST_F(HTTPSRequestTest, ClientAuthTest) { - SpawnedTestServer::SSLOptions ssl_options; - ssl_options.request_client_certificate = true; - SpawnedTestServer test_server( - SpawnedTestServer::TYPE_HTTPS, - ssl_options, + EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS); + net::SSLServerConfig ssl_config; + ssl_config.require_client_cert = true; + test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config); + test_server.AddDefaultHandlers( base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); ASSERT_TRUE(test_server.Start()); SSLClientAuthTestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server.GetURL(std::string()), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -8393,15 +8404,13 @@ return; } - SpawnedTestServer test_server( - SpawnedTestServer::TYPE_HTTPS, - SpawnedTestServer::kLocalhost, - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS); + test_server.ServeFilesFromSourceDirectory("net/data/ssl"); ASSERT_TRUE(test_server.Start()); TestDelegate d; scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server.GetURL("client-cipher-list"), DEFAULT_PRIORITY, &d)); + test_server.GetURL("/client-cipher-list"), DEFAULT_PRIORITY, &d)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -8500,8 +8509,8 @@ base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); ASSERT_TRUE(test_server.Start()); - request_ = context_.CreateRequest(test_server.GetURL(std::string()), - DEFAULT_PRIORITY, &delegate_); + request_ = context_.CreateRequest(test_server.GetURL("/"), DEFAULT_PRIORITY, + &delegate_); request_->Start(); base::RunLoop().Run(); @@ -8656,7 +8665,7 @@ context.set_fallback_min_version(SSL_PROTOCOL_VERSION_TLS1_2); context.Init(); scoped_ptr<URLRequest> request(context.CreateRequest( - test_server.GetURL(std::string()), DEFAULT_PRIORITY, &delegate)); + test_server.GetURL("/"), DEFAULT_PRIORITY, &delegate)); request->Start(); base::RunLoop().Run(); @@ -8831,8 +8840,8 @@ TestDelegate d; d.set_allow_certificate_errors(true); - scoped_ptr<URLRequest> r(context_.CreateRequest( - test_server.GetURL(std::string()), DEFAULT_PRIORITY, &d)); + scoped_ptr<URLRequest> r( + context_.CreateRequest(test_server.GetURL("/"), DEFAULT_PRIORITY, &d)); r->Start(); base::RunLoop().Run(); @@ -9328,9 +9337,9 @@ public: URLRequestTestFTP() : ftp_transaction_factory_(&host_resolver_), - test_server_(SpawnedTestServer::TYPE_FTP, - SpawnedTestServer::kLocalhost, - base::FilePath(kTestFilePath)) { + ftp_test_server_(SpawnedTestServer::TYPE_FTP, + SpawnedTestServer::kLocalhost, + base::FilePath(kTestFilePath)) { // Can't use |default_context_|'s HostResolver to set up the // FTPTransactionFactory because it hasn't been created yet. default_context_.set_host_resolver(&host_resolver_); @@ -9358,7 +9367,7 @@ MockHostResolver host_resolver_; FtpNetworkLayer ftp_transaction_factory_; - SpawnedTestServer test_server_; + SpawnedTestServer ftp_test_server_; }; // Make sure an FTP request using an unsafe ports fails. @@ -9381,12 +9390,12 @@ } TEST_F(URLRequestTestFTP, FTPDirectoryListing) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(ftp_test_server_.Start()); TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL("/"), DEFAULT_PRIORITY, &d)); + ftp_test_server_.GetURL("/"), DEFAULT_PRIORITY, &d)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -9396,20 +9405,20 @@ EXPECT_EQ(1, d.response_started_count()); EXPECT_FALSE(d.received_data_before_response()); EXPECT_LT(0, d.bytes_received()); - EXPECT_EQ(test_server_.host_port_pair().host(), + EXPECT_EQ(ftp_test_server_.host_port_pair().host(), r->GetSocketAddress().host()); - EXPECT_EQ(test_server_.host_port_pair().port(), + EXPECT_EQ(ftp_test_server_.host_port_pair().port(), r->GetSocketAddress().port()); } } TEST_F(URLRequestTestFTP, FTPGetTestAnonymous) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(ftp_test_server_.Start()); TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL(kFtpTestFile), DEFAULT_PRIORITY, &d)); + ftp_test_server_.GetURL(kFtpTestFile), DEFAULT_PRIORITY, &d)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -9419,22 +9428,22 @@ EXPECT_EQ(1, d.response_started_count()); EXPECT_FALSE(d.received_data_before_response()); EXPECT_EQ(GetTestFileContents(), d.data_received()); - EXPECT_EQ(test_server_.host_port_pair().host(), + EXPECT_EQ(ftp_test_server_.host_port_pair().host(), r->GetSocketAddress().host()); - EXPECT_EQ(test_server_.host_port_pair().port(), + EXPECT_EQ(ftp_test_server_.host_port_pair().port(), r->GetSocketAddress().port()); } } TEST_F(URLRequestTestFTP, FTPGetTest) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(ftp_test_server_.Start()); TestDelegate d; { - scoped_ptr<URLRequest> r( - default_context_.CreateRequest(test_server_.GetURLWithUserAndPassword( - kFtpTestFile, "chrome", "chrome"), - DEFAULT_PRIORITY, &d)); + scoped_ptr<URLRequest> r(default_context_.CreateRequest( + ftp_test_server_.GetURLWithUserAndPassword(kFtpTestFile, "chrome", + "chrome"), + DEFAULT_PRIORITY, &d)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -9444,9 +9453,9 @@ EXPECT_EQ(1, d.response_started_count()); EXPECT_FALSE(d.received_data_before_response()); EXPECT_EQ(GetTestFileContents(), d.data_received()); - EXPECT_EQ(test_server_.host_port_pair().host(), + EXPECT_EQ(ftp_test_server_.host_port_pair().host(), r->GetSocketAddress().host()); - EXPECT_EQ(test_server_.host_port_pair().port(), + EXPECT_EQ(ftp_test_server_.host_port_pair().port(), r->GetSocketAddress().port()); LoadTimingInfo load_timing_info; @@ -9456,13 +9465,13 @@ } TEST_F(URLRequestTestFTP, FTPCheckWrongPassword) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(ftp_test_server_.Start()); TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURLWithUserAndPassword(kFtpTestFile, "chrome", - "wrong_password"), + ftp_test_server_.GetURLWithUserAndPassword(kFtpTestFile, "chrome", + "wrong_password"), DEFAULT_PRIORITY, &d)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -9477,7 +9486,7 @@ } TEST_F(URLRequestTestFTP, FTPCheckWrongPasswordRestart) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(ftp_test_server_.Start()); TestDelegate d; // Set correct login credentials. The delegate will be asked for them when @@ -9485,8 +9494,8 @@ d.set_credentials(AuthCredentials(kChrome, kChrome)); { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURLWithUserAndPassword(kFtpTestFile, "chrome", - "wrong_password"), + ftp_test_server_.GetURLWithUserAndPassword(kFtpTestFile, "chrome", + "wrong_password"), DEFAULT_PRIORITY, &d)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -9501,13 +9510,13 @@ } TEST_F(URLRequestTestFTP, FTPCheckWrongUser) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(ftp_test_server_.Start()); TestDelegate d; { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURLWithUserAndPassword(kFtpTestFile, "wrong_user", - "chrome"), + ftp_test_server_.GetURLWithUserAndPassword(kFtpTestFile, "wrong_user", + "chrome"), DEFAULT_PRIORITY, &d)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -9522,7 +9531,7 @@ } TEST_F(URLRequestTestFTP, FTPCheckWrongUserRestart) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(ftp_test_server_.Start()); TestDelegate d; // Set correct login credentials. The delegate will be asked for them when @@ -9530,8 +9539,8 @@ d.set_credentials(AuthCredentials(kChrome, kChrome)); { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURLWithUserAndPassword(kFtpTestFile, "wrong_user", - "chrome"), + ftp_test_server_.GetURLWithUserAndPassword(kFtpTestFile, "wrong_user", + "chrome"), DEFAULT_PRIORITY, &d)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -9546,15 +9555,15 @@ } TEST_F(URLRequestTestFTP, FTPCacheURLCredentials) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(ftp_test_server_.Start()); scoped_ptr<TestDelegate> d(new TestDelegate); { // Pass correct login identity in the URL. - scoped_ptr<URLRequest> r( - default_context_.CreateRequest(test_server_.GetURLWithUserAndPassword( - kFtpTestFile, "chrome", "chrome"), - DEFAULT_PRIORITY, d.get())); + scoped_ptr<URLRequest> r(default_context_.CreateRequest( + ftp_test_server_.GetURLWithUserAndPassword(kFtpTestFile, "chrome", + "chrome"), + DEFAULT_PRIORITY, d.get())); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -9570,7 +9579,7 @@ { // This request should use cached identity from previous request. scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL(kFtpTestFile), DEFAULT_PRIORITY, d.get())); + ftp_test_server_.GetURL(kFtpTestFile), DEFAULT_PRIORITY, d.get())); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -9584,7 +9593,7 @@ } TEST_F(URLRequestTestFTP, FTPCacheLoginBoxCredentials) { - ASSERT_TRUE(test_server_.Start()); + ASSERT_TRUE(ftp_test_server_.Start()); scoped_ptr<TestDelegate> d(new TestDelegate); // Set correct login credentials. The delegate will be asked for them when @@ -9592,8 +9601,8 @@ d->set_credentials(AuthCredentials(kChrome, kChrome)); { scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURLWithUserAndPassword(kFtpTestFile, "chrome", - "wrong_password"), + ftp_test_server_.GetURLWithUserAndPassword(kFtpTestFile, "chrome", + "wrong_password"), DEFAULT_PRIORITY, d.get())); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -9613,7 +9622,7 @@ // Don't pass wrong credentials in the URL, they would override valid cached // ones. scoped_ptr<URLRequest> r(default_context_.CreateRequest( - test_server_.GetURL(kFtpTestFile), DEFAULT_PRIORITY, d.get())); + ftp_test_server_.GetURL(kFtpTestFile), DEFAULT_PRIORITY, d.get())); r->Start(); EXPECT_TRUE(r->is_pending());
diff --git a/net/websockets/websocket_end_to_end_test.cc b/net/websockets/websocket_end_to_end_test.cc index fef28095..c8cb10ee 100644 --- a/net/websockets/websocket_end_to_end_test.cc +++ b/net/websockets/websocket_end_to_end_test.cc
@@ -24,6 +24,7 @@ #include "net/base/network_delegate.h" #include "net/base/test_data_directory.h" #include "net/proxy/proxy_service.h" +#include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/spawned_test_server/spawned_test_server.h" #include "net/url_request/url_request_test_util.h" #include "net/websockets/websocket_channel.h" @@ -388,22 +389,22 @@ // Regression test for crbug.com/455215 "HSTS not applied to WebSocket" TEST_F(WebSocketEndToEndTest, DISABLED_ON_ANDROID(HstsHttpsToWebSocket)) { + EmbeddedTestServer https_server(net::EmbeddedTestServer::Type::TYPE_HTTPS); + https_server.SetSSLConfig( + net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN); + https_server.ServeFilesFromSourceDirectory("net/data/url_request_unittest"); + SpawnedTestServer::SSLOptions ssl_options( SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); - SpawnedTestServer https_server( - SpawnedTestServer::TYPE_HTTPS, ssl_options, - base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); SpawnedTestServer wss_server(SpawnedTestServer::TYPE_WSS, ssl_options, GetWebSocketTestDataDirectory()); - ASSERT_TRUE(https_server.StartInBackground()); - ASSERT_TRUE(wss_server.StartInBackground()); - ASSERT_TRUE(https_server.BlockUntilStarted()); - ASSERT_TRUE(wss_server.BlockUntilStarted()); + ASSERT_TRUE(https_server.Start()); + ASSERT_TRUE(wss_server.Start()); InitialiseContext(); // Set HSTS via https: TestDelegate delegate; - GURL https_page = https_server.GetURL("files/hsts-headers.html"); + GURL https_page = https_server.GetURL("/hsts-headers.html"); scoped_ptr<URLRequest> request( context_.CreateRequest(https_page, DEFAULT_PRIORITY, &delegate)); request->Start(); @@ -418,17 +419,17 @@ } TEST_F(WebSocketEndToEndTest, DISABLED_ON_ANDROID(HstsWebSocketToHttps)) { + EmbeddedTestServer https_server(net::EmbeddedTestServer::Type::TYPE_HTTPS); + https_server.SetSSLConfig( + net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN); + https_server.ServeFilesFromSourceDirectory("net/data/url_request_unittest"); + SpawnedTestServer::SSLOptions ssl_options( SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); - SpawnedTestServer https_server( - SpawnedTestServer::TYPE_HTTPS, ssl_options, - base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); SpawnedTestServer wss_server(SpawnedTestServer::TYPE_WSS, ssl_options, GetWebSocketTestDataDirectory()); - ASSERT_TRUE(https_server.StartInBackground()); - ASSERT_TRUE(wss_server.StartInBackground()); - ASSERT_TRUE(https_server.BlockUntilStarted()); - ASSERT_TRUE(wss_server.BlockUntilStarted()); + ASSERT_TRUE(https_server.Start()); + ASSERT_TRUE(wss_server.Start()); InitialiseContext(); // Set HSTS via wss: GURL wss_url = wss_server.GetURL("set-hsts"); @@ -437,7 +438,7 @@ // Verify via http: TestDelegate delegate; GURL http_page = - ReplaceUrlScheme(https_server.GetURL("files/simple.html"), "http"); + ReplaceUrlScheme(https_server.GetURL("/simple.html"), "http"); scoped_ptr<URLRequest> request( context_.CreateRequest(http_page, DEFAULT_PRIORITY, &delegate)); request->Start();
diff --git a/ppapi/proxy/compositor_layer_resource.cc b/ppapi/proxy/compositor_layer_resource.cc index c42776eb..3507c92 100644 --- a/ppapi/proxy/compositor_layer_resource.cc +++ b/ppapi/proxy/compositor_layer_resource.cc
@@ -10,6 +10,7 @@ #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/gles2_implementation.h" #include "gpu/command_buffer/common/mailbox.h" +#include "gpu/command_buffer/common/sync_token.h" #include "ppapi/proxy/compositor_resource.h" #include "ppapi/shared_impl/ppb_graphics_3d_shared.h" #include "ppapi/thunk/enter.h" @@ -30,14 +31,13 @@ return std::min(std::max(value, 0.0f), 1.0f); } -void OnTextureReleased( - const ScopedPPResource& layer, - const ScopedPPResource& context, - uint32_t texture, - const scoped_refptr<TrackedCallback>& release_callback, - int32_t result, - uint32_t sync_point, - bool is_lost) { +void OnTextureReleased(const ScopedPPResource& layer, + const ScopedPPResource& context, + uint32_t texture, + const scoped_refptr<TrackedCallback>& release_callback, + int32_t result, + const gpu::SyncToken& sync_token, + bool is_lost) { if (!TrackedCallback::IsPending(release_callback)) return; @@ -47,7 +47,7 @@ } do { - if (!sync_point) + if (!sync_token.HasData()) break; EnterResourceNoLock<PPB_Graphics3D_API> enter(context.get(), true); @@ -58,19 +58,18 @@ static_cast<PPB_Graphics3D_Shared*>(enter.object()); GLES2Implementation* gl = graphics->gles2_impl(); - gl->WaitSyncPointCHROMIUM(sync_point); + gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); } while (false); release_callback->Run(is_lost ? PP_ERROR_FAILED : PP_OK); } -void OnImageReleased( - const ScopedPPResource& layer, - const ScopedPPResource& image, - const scoped_refptr<TrackedCallback>& release_callback, - int32_t result, - uint32_t sync_point, - bool is_lost) { +void OnImageReleased(const ScopedPPResource& layer, + const ScopedPPResource& image, + const scoped_refptr<TrackedCallback>& release_callback, + int32_t result, + const gpu::SyncToken& sync_token, + bool is_lost) { if (!TrackedCallback::IsPending(release_callback)) return; release_callback->Run(result); @@ -175,7 +174,7 @@ data_.common.size = *size; data_.common.resource_id = compositor_->GenerateResourceId(); data_.texture->target = target; - data_.texture->sync_point = gl->InsertSyncPointCHROMIUM(); + data_.texture->sync_token = gpu::SyncToken(gl->InsertSyncPointCHROMIUM()); data_.texture->source_rect.point = PP_MakeFloatPoint(0.0f, 0.0f); data_.texture->source_rect.size = source_size_;
diff --git a/ppapi/proxy/compositor_layer_resource.h b/ppapi/proxy/compositor_layer_resource.h index dc6024f..8d4dfd3e 100644 --- a/ppapi/proxy/compositor_layer_resource.h +++ b/ppapi/proxy/compositor_layer_resource.h
@@ -12,6 +12,10 @@ #include "ppapi/shared_impl/scoped_pp_resource.h" #include "ppapi/thunk/ppb_compositor_layer_api.h" +namespace gpu { +struct SyncToken; +} + namespace ppapi { namespace proxy { @@ -22,7 +26,8 @@ public thunk::PPB_CompositorLayer_API { public: // Release callback for texture or image layer. - typedef base::Callback<void(int32_t, uint32_t, bool)> ReleaseCallback; + typedef base::Callback<void(int32_t, const gpu::SyncToken&, bool)> + ReleaseCallback; CompositorLayerResource(Connection connection, PP_Instance instance,
diff --git a/ppapi/proxy/compositor_resource.cc b/ppapi/proxy/compositor_resource.cc index 443d7a94..f15e402 100644 --- a/ppapi/proxy/compositor_resource.cc +++ b/ppapi/proxy/compositor_resource.cc
@@ -36,7 +36,7 @@ for (ReleaseCallbackMap::iterator it = release_callback_map_.begin(); it != release_callback_map_.end(); ++it) { if (!it->second.is_null()) - it->second.Run(PP_ERROR_ABORTED, 0, false); + it->second.Run(PP_ERROR_ABORTED, gpu::SyncToken(), false); } } @@ -126,12 +126,12 @@ void CompositorResource::OnPluginMsgReleaseResource( const ResourceMessageReplyParams& params, int32_t id, - uint32_t sync_point, + const gpu::SyncToken& sync_token, bool is_lost) { ReleaseCallbackMap::iterator it = release_callback_map_.find(id); DCHECK(it != release_callback_map_.end()) << "Can not found release_callback_ by id(" << id << ")!"; - it->second.Run(PP_OK, sync_point, is_lost); + it->second.Run(PP_OK, sync_token, is_lost); release_callback_map_.erase(it); } @@ -140,7 +140,8 @@ it != layers_.end(); ++it) { ReleaseCallback release_callback = (*it)->release_callback(); if (!release_callback.is_null()) { - release_callback.Run(is_aborted ? PP_ERROR_ABORTED : PP_OK, 0, false); + release_callback.Run(is_aborted ? PP_ERROR_ABORTED : PP_OK, + gpu::SyncToken(), false); (*it)->ResetReleaseCallback(); } (*it)->Invalidate();
diff --git a/ppapi/proxy/compositor_resource.h b/ppapi/proxy/compositor_resource.h index 0d3161d..49ccf3d 100644 --- a/ppapi/proxy/compositor_resource.h +++ b/ppapi/proxy/compositor_resource.h
@@ -13,6 +13,10 @@ #include "ppapi/shared_impl/proxy_lock.h" #include "ppapi/thunk/ppb_compositor_api.h" +namespace gpu { +struct SyncToken; +} + namespace ppapi { namespace proxy { @@ -44,11 +48,10 @@ // IPC msg handlers: void OnPluginMsgCommitLayersReply(const ResourceMessageReplyParams& params); - void OnPluginMsgReleaseResource( - const ResourceMessageReplyParams& params, - int32_t id, - uint32_t sync_point, - bool is_lost); + void OnPluginMsgReleaseResource(const ResourceMessageReplyParams& params, + int32_t id, + const gpu::SyncToken& sync_token, + bool is_lost); void ResetLayersInternal(bool is_aborted);
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index c36ceac5..a27a3ee 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h
@@ -15,6 +15,7 @@ #include "base/sync_socket.h" #include "gpu/command_buffer/common/command_buffer.h" #include "gpu/command_buffer/common/mailbox.h" +#include "gpu/command_buffer/common/sync_token.h" #include "gpu/ipc/gpu_command_buffer_traits.h" #include "ipc/ipc_channel_handle.h" #include "ipc/ipc_message_macros.h" @@ -278,8 +279,8 @@ IPC_STRUCT_TRAITS_BEGIN(ppapi::CompositorLayerData::TextureLayer) IPC_STRUCT_TRAITS_MEMBER(mailbox) + IPC_STRUCT_TRAITS_MEMBER(sync_token) IPC_STRUCT_TRAITS_MEMBER(target) - IPC_STRUCT_TRAITS_MEMBER(sync_point) IPC_STRUCT_TRAITS_MEMBER(source_rect) IPC_STRUCT_TRAITS_MEMBER(premult_alpha) IPC_STRUCT_TRAITS_END() @@ -1402,7 +1403,7 @@ IPC_MESSAGE_CONTROL0(PpapiPluginMsg_Compositor_CommitLayersReply) IPC_MESSAGE_CONTROL3(PpapiPluginMsg_Compositor_ReleaseResource, int32_t /* id */, - uint32_t /* sync_point */, + gpu::SyncToken /* sync_token */, bool /* is_lost */) // File chooser.
diff --git a/ppapi/shared_impl/compositor_layer_data.h b/ppapi/shared_impl/compositor_layer_data.h index 8cf096ea..d726e28 100644 --- a/ppapi/shared_impl/compositor_layer_data.h +++ b/ppapi/shared_impl/compositor_layer_data.h
@@ -10,6 +10,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/common/mailbox.h" +#include "gpu/command_buffer/common/sync_token.h" #include "ppapi/c/ppb_compositor_layer.h" #include "ppapi/shared_impl/host_resource.h" #include "ppapi/shared_impl/ppapi_shared_export.h" @@ -79,13 +80,12 @@ struct TextureLayer { TextureLayer() : target(0), - sync_point(0), source_rect(PP_MakeFloatRectFromXYWH(0.0f, 0.0f, 1.0f, 1.0f)), premult_alpha(true) {} gpu::Mailbox mailbox; + gpu::SyncToken sync_token; uint32_t target; - uint32_t sync_point; PP_FloatRect source_rect; bool premult_alpha; };
diff --git a/remoting/BUILD.gn b/remoting/BUILD.gn index 832549a2..51aa8179 100644 --- a/remoting/BUILD.gn +++ b/remoting/BUILD.gn
@@ -64,7 +64,7 @@ if (enable_me2me_host) { deps += [ "//remoting/host:remoting_me2me_host", - #"//remoting/host:remoting_me2me_host_archive", + "//remoting/host:remoting_me2me_host_archive", ] }
diff --git a/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java b/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java index f5b94983..5e4cd5e1 100644 --- a/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java +++ b/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java
@@ -77,7 +77,9 @@ SIGNALING_ERROR(6, R.string.error_p2p_failure), SIGNALING_TIMEOUT(7, R.string.error_p2p_failure), HOST_OVERLOAD(8, R.string.error_host_overload), - UNKNOWN_ERROR(9, R.string.error_unexpected); + MAX_SESSION_LENGTH(9, R.string.error_max_session_length), + HOST_CONFIGURATION_ERROR(10, R.string.error_host_configuration_error), + UNKNOWN_ERROR(11, R.string.error_unexpected); private final int mValue; private final int mMessage;
diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc index d29b608a3..eef2a20 100644 --- a/remoting/client/plugin/chromoting_instance.cc +++ b/remoting/client/plugin/chromoting_instance.cc
@@ -120,6 +120,12 @@ case protocol::HOST_OVERLOAD: return "HOST_OVERLOAD"; + case protocol::MAX_SESSION_LENGTH: + return "MAX_SESSION_LENGTH"; + + case protocol::HOST_CONFIGURATION_ERROR: + return "HOST_CONFIGURATION_ERROR"; + case protocol::CHANNEL_CONNECTION_ERROR: case protocol::SIGNALING_ERROR: case protocol::SIGNALING_TIMEOUT:
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn index 7d171a8..8bf1c5e 100644 --- a/remoting/host/BUILD.gn +++ b/remoting/host/BUILD.gn
@@ -2,17 +2,24 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/allocator.gni") import("//build/config/features.gni") import("//build/config/ui.gni") +import("//build/util/version.gni") import("//remoting/remoting_host.gni") import("//remoting/remoting_locales.gni") +import("//remoting/remoting_options.gni") import("//remoting/remoting_srcs.gni") import("//remoting/remoting_version.gni") import("//remoting/tools/build/remoting_localize.gni") # GYP version: remoting/remoting_host:remoting_host_credits action("credits") { - about_credits_file = "$target_gen_dir/CREDITS.txt" + # We put this in $root_build_dir/gen/remoting instead of + # $root_build_dir/gen/remoting/host (target_gen_dir) for + # compatibility w/ GYP, since the installer needs the file to + # be at the same location. + about_credits_file = "$root_build_dir/gen/remoting/CREDITS.txt" script = "//tools/licenses.py" inputs = [ @@ -153,6 +160,7 @@ sources -= [ "continue_window_linux.cc", + "curtain_mode_linux.cc", "disconnect_window_linux.cc", ] } @@ -418,21 +426,62 @@ deps += [ "//third_party/libjingle:libjingle_webrtc" ] } } + + action_foreach("remoting_native_messaging_manifests") { + if (is_mac) { + assert(false, "not implemented on mac yet") + } else if (is_win) { + assert(false, "not implemented on win yet") + } else { + me2me_host_path = + "/opt/google/chrome-remote-desktop/native-messaging-host" + it2me_host_path = + "/opt/google/chrome-remote-desktop/remote-assistance-host" + } + + script = "../tools/build/remoting_localize.py" + + sources = [ + "it2me/com.google.chrome.remote_assistance.json.jinja2", + "setup/com.google.chrome.remote_desktop.json.jinja2", + ] + + inputs = [ + branding_path, + ] + + outputs = [ + "$root_build_dir/remoting/{{source_name_part}}", + ] + + args = [ + "--define", + "ME2ME_HOST_PATH=$me2me_host_path", + "--define", + "IT2ME_HOST_PATH=$it2me_host_path", + "--variables", + branding_path, + "--template", + "{{source}}", + "--locale_output", + "remoting/{{source_name_part}}", + "en", + ] + } + + # TODO(crbug.com/512899) This still needs to be ported to GN. + group("remoting_infoplist_strings") { + } } if (enable_me2me_host) { source_set("remoting_me2me_host_static") { sources = [ - "curtain_mode.h", - "curtain_mode_linux.cc", - "curtain_mode_mac.cc", - "curtain_mode_win.cc", "pam_authorization_factory_posix.cc", "pam_authorization_factory_posix.h", - "posix/signal_handler.cc", - "posix/signal_handler.h", "remoting_me2me_host.cc", ] + defines = [] configs += [ "//remoting:version" ] @@ -461,6 +510,11 @@ if ((is_linux && !is_chromeos) || is_mac) { libs = [ "pam" ] } + + if (is_mac && is_official_build) { + sources += [ "internal/internal_mac-inl.h" ] + defines += [ "USE_REMOTING_MACOSX_INTERNAL" ] + } } if (!is_win) { @@ -476,6 +530,134 @@ "//build/config/sanitizers:deps", ] } + + executable("native_messaging_host") { + sources = [ + "setup/me2me_native_messaging_host_entry_point.cc", + "setup/me2me_native_messaging_host_main.cc", + "setup/me2me_native_messaging_host_main.h", + ] + + deps = [ + ":remoting_infoplist_strings", + "//base", + "//remoting/base:breakpad", + "//remoting/host", + "//remoting/host/setup", + "//remoting/host/native_messaging", + ] + + configs += [ "//build/config/compiler:wexit_time_destructors" ] + + # The |major|, |build| and |patch| versions are inherited from Chrome. + # Since Chrome's |minor| version is always '0', we replace it with a + # Chromoting-specific patch version. + defines = [ "VERSION=" + "$chrome_version_major" + "." + + "$remoting_version_patch" + "." + "$chrome_version_build" + + "." + "$chrome_version_patch" ] + + if (is_linux && use_allocator != "none") { + deps += [ "//base/allocator" ] + } else if (is_mac || is_win) { + assert(false, "not implemented on mac or win yet") + } + } + } + + if (is_chrome_branded && enable_me2me_host && !is_chromeos) { + # TODO(GYP): add support for archive_chromoting_tests variable? + + import("//build/config/zip.gni") + + build_deb_script = "installer/linux/build_deb.py" + deb_filename = + "$root_build_dir/" + exec_script(build_deb_script, + [ + "-p", + "-s", + rebase_path("//"), + ], + "string", + [ "installer/linux/build-deb.sh" ]) + changes_filename = + "$root_build_dir/" + get_path_info(deb_filename, "name") + ".changes" + + packaging_outputs = [ + deb_filename, + changes_filename, + + # TODO(GYP): These files will only be present if we're stripping + # binaries. We need to support linux_dump_symbols for this. + #"$root_build_dir/remoting_me2me_host.debug", + #"$root_build_dir/remoting_start_host.debug", + #"$root_build_dir/native_messaging_host.debug", + #"$root_build_dir/remote_assistance_host.debug", + ] + + zip("remoting_me2me_host_archive") { + # Store the installer package(s) into a zip file so there is a + # consistent filename to reference for build archiving (i.e. in + # FILES.cfg). This also avoids possible conflicts with "wildcard" + # package handling in other build/signing scripts. + inputs = packaging_outputs + output = "$root_build_dir/remoting-me2me-host-linux.zip" + deps = [ + ":remoting_me2me_host_copy", + ] + } + + copy("remoting_me2me_host_copy") { + # Copy the debian package file, which has version info in it, + # to a consistewnt filename for use on Chromoting swarming bots. + sources = [ + deb_filename, + ] + outputs = [ + "$root_build_dir/remoting-me2me-host.deb", + ] + public_deps = [ + ":remoting_me2me_host_deb_installer", + ] + } + + action("remoting_me2me_host_deb_installer") { + script = build_deb_script + inputs = [ + build_deb_script, + "installer/linux/Makefile", + "installer/linux/debian/chrome-remote-desktop.init", + "installer/linux/debian/chrome-remote-desktop.pam", + "installer/linux/debian/compat", + "installer/linux/debian/control", + "installer/linux/debian/copyright", + "installer/linux/debian/postinst", + "installer/linux/debian/preinst", + "installer/linux/debian/rules", + ] + outputs = packaging_outputs + sources = [ + "installer/linux/build-deb.sh", + ] + args = [ + "-s", + rebase_path("//"), + "-o", + rebase_path("$root_build_dir"), + ] + + deps = [ + ":native_messaging_host", + ":remoting_me2me_host", + ":remoting_native_messaging_manifests", + ":remoting_start_host", + "//remoting/host/it2me:remote_assistance_host", + "//remoting/resources", + "//third_party/icu:icudata", + ] + } + } else { + group("remoting_me2me_host_archive") { + } } } }
diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc index b2bd1f9..ff85892e 100644 --- a/remoting/host/chromoting_host.cc +++ b/remoting/host/chromoting_host.cc
@@ -94,7 +94,7 @@ // Disconnect all of the clients. while (!clients_.empty()) { - clients_.front()->DisconnectSession(); + clients_.front()->DisconnectSession(protocol::OK); } // Destroy the session manager to make sure that |signal_strategy_| does not @@ -177,7 +177,7 @@ if (login_backoff_.ShouldRejectRequest()) { LOG(WARNING) << "Disconnecting client " << client->client_jid() << " due to" " an overload of failed login attempts."; - client->DisconnectSession(); + client->DisconnectSession(protocol::HOST_OVERLOAD); return; } login_backoff_.InformOfRequest(false); @@ -195,7 +195,7 @@ while (it != clients_.end()) { ClientSession* other_client = *it++; if (other_client != client) - other_client->DisconnectSession(); + other_client->DisconnectSession(protocol::OK); } // Disconnects above must have destroyed all other clients. @@ -307,7 +307,7 @@ while (!clients_.empty()) { size_t size = clients_.size(); - clients_.front()->DisconnectSession(); + clients_.front()->DisconnectSession(protocol::OK); CHECK_EQ(clients_.size(), size - 1); } }
diff --git a/remoting/host/chromoting_host_unittest.cc b/remoting/host/chromoting_host_unittest.cc index 0eeac1b3..6cbc4ea 100644 --- a/remoting/host/chromoting_host_unittest.cc +++ b/remoting/host/chromoting_host_unittest.cc
@@ -367,7 +367,7 @@ MockConnectionToClient* connection = get_connection(connection_index); Expectation client_disconnected = - EXPECT_CALL(*connection, Disconnect()) + EXPECT_CALL(*connection, Disconnect(_)) .After(after) .WillOnce(InvokeWithoutArgs(CreateFunctor( this, &ChromotingHostTest::NotifyClientSessionClosed, @@ -568,7 +568,7 @@ TEST_F(ChromotingHostTest, IncomingSessionAccepted) { ExpectHostAndSessionManagerStart(); - EXPECT_CALL(*session_unowned1_, Close()).WillOnce(InvokeWithoutArgs( + EXPECT_CALL(*session_unowned1_, Close(_)).WillOnce(InvokeWithoutArgs( this, &ChromotingHostTest::NotifyConnectionClosed1)); EXPECT_CALL(host_status_observer_, OnAccessDenied(_)); EXPECT_CALL(host_status_observer_, OnShutdown()); @@ -586,7 +586,7 @@ TEST_F(ChromotingHostTest, LoginBackOffUponConnection) { ExpectHostAndSessionManagerStart(); - EXPECT_CALL(*session_unowned1_, Close()).WillOnce( + EXPECT_CALL(*session_unowned1_, Close(_)).WillOnce( InvokeWithoutArgs(this, &ChromotingHostTest::NotifyConnectionClosed1)); EXPECT_CALL(host_status_observer_, OnAccessDenied(_)); EXPECT_CALL(host_status_observer_, OnShutdown()); @@ -609,10 +609,10 @@ TEST_F(ChromotingHostTest, LoginBackOffUponAuthenticating) { Expectation start = ExpectHostAndSessionManagerStart(); - EXPECT_CALL(*session_unowned1_, Close()).WillOnce( + EXPECT_CALL(*session_unowned1_, Close(_)).WillOnce( InvokeWithoutArgs(this, &ChromotingHostTest::NotifyConnectionClosed1)); - EXPECT_CALL(*session_unowned2_, Close()).WillOnce( + EXPECT_CALL(*session_unowned2_, Close(_)).WillOnce( InvokeWithoutArgs(this, &ChromotingHostTest::NotifyConnectionClosed2)); EXPECT_CALL(host_status_observer_, OnShutdown());
diff --git a/remoting/host/chromoting_messages.h b/remoting/host/chromoting_messages.h index 3a27b38..793156bd 100644 --- a/remoting/host/chromoting_messages.h +++ b/remoting/host/chromoting_messages.h
@@ -9,6 +9,7 @@ #include "net/base/ip_endpoint.h" #include "remoting/host/chromoting_param_traits.h" #include "remoting/host/screen_resolution.h" +#include "remoting/protocol/errors.h" #include "remoting/protocol/transport.h" #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" @@ -180,8 +181,12 @@ IPC_MESSAGE_CONTROL1(ChromotingDesktopNetworkMsg_InjectClipboardEvent, std::string /* serialized_event */ ) +IPC_ENUM_TRAITS_MAX_VALUE(remoting::protocol::ErrorCode, + remoting::protocol::ERROR_CODE_MAX) + // Requests the network process to terminate the client session. -IPC_MESSAGE_CONTROL0(ChromotingDesktopNetworkMsg_DisconnectSession) +IPC_MESSAGE_CONTROL1(ChromotingDesktopNetworkMsg_DisconnectSession, + remoting::protocol::ErrorCode /* error */) // Carries an audio packet from the desktop session agent to the client. // |serialized_packet| is a serialized AudioPacket.
diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc index 1ddfd384..1008589 100644 --- a/remoting/host/client_session.cc +++ b/remoting/host/client_session.cc
@@ -288,15 +288,15 @@ is_authenticated_ = true; if (max_duration_ > base::TimeDelta()) { - // TODO(simonmorris): Let Disconnect() tell the client that the - // disconnection was caused by the session exceeding its maximum duration. - max_duration_timer_.Start(FROM_HERE, max_duration_, - this, &ClientSession::DisconnectSession); + max_duration_timer_.Start( + FROM_HERE, max_duration_, + base::Bind(&ClientSession::DisconnectSession, base::Unretained(this), + protocol::MAX_SESSION_LENGTH)); } // Disconnect the session if the connection was rejected by the host. if (!event_handler_->OnSessionAuthenticated(this)) { - DisconnectSession(); + DisconnectSession(protocol::SESSION_REJECTED); return; } @@ -305,8 +305,7 @@ desktop_environment_ = desktop_environment_factory_->Create(weak_factory_.GetWeakPtr()); if (!desktop_environment_) { - // TODO(sergeyu): Fix the host to return an error code (crbug.com/543334). - DisconnectSession(); + DisconnectSession(protocol::HOST_CONFIGURATION_ERROR); return; } @@ -428,7 +427,7 @@ return client_jid_; } -void ClientSession::DisconnectSession() { +void ClientSession::DisconnectSession(protocol::ErrorCode error) { DCHECK(CalledOnValidThread()); DCHECK(connection_.get()); @@ -436,7 +435,7 @@ // This triggers OnConnectionClosed(), and the session may be destroyed // as the result, so this call must be the last in this method. - connection_->Disconnect(); + connection_->Disconnect(error); } void ClientSession::OnLocalMouseMoved(const webrtc::DesktopVector& position) {
diff --git a/remoting/host/client_session.h b/remoting/host/client_session.h index d41e83e..348552d 100644 --- a/remoting/host/client_session.h +++ b/remoting/host/client_session.h
@@ -130,7 +130,7 @@ // ClientSessionControl interface. const std::string& client_jid() const override; - void DisconnectSession() override; + void DisconnectSession(protocol::ErrorCode error) override; void OnLocalMouseMoved(const webrtc::DesktopVector& position) override; void SetDisableInputs(bool disable_inputs) override; void ResetVideoPipeline() override;
diff --git a/remoting/host/client_session_control.h b/remoting/host/client_session_control.h index 30cb15b..47d2089 100644 --- a/remoting/host/client_session_control.h +++ b/remoting/host/client_session_control.h
@@ -6,6 +6,7 @@ #define REMOTING_HOST_CLIENT_SESSION_CONTROL_H_ #include "base/basictypes.h" +#include "remoting/protocol/errors.h" namespace webrtc { class DesktopVector; @@ -25,7 +26,7 @@ // Disconnects the client session, tears down transport resources and stops // scheduler components. - virtual void DisconnectSession() = 0; + virtual void DisconnectSession(protocol::ErrorCode error) = 0; // Called when local mouse movement is detected. virtual void OnLocalMouseMoved(const webrtc::DesktopVector& position) = 0;
diff --git a/remoting/host/client_session_unittest.cc b/remoting/host/client_session_unittest.cc index 696f83f..81a3b6f0 100644 --- a/remoting/host/client_session_unittest.cc +++ b/remoting/host/client_session_unittest.cc
@@ -239,7 +239,7 @@ EXPECT_CALL(*connection, client_stub()) .WillRepeatedly(Return(&client_stub_)); EXPECT_CALL(*connection, video_stub()).WillRepeatedly(Return(&video_stub_)); - EXPECT_CALL(*connection, Disconnect()); + EXPECT_CALL(*connection, Disconnect(_)); connection_ = connection.get(); client_session_.reset(new ClientSession( @@ -258,7 +258,7 @@ } void ClientSessionTest::DisconnectClientSession() { - client_session_->DisconnectSession(); + client_session_->DisconnectSession(protocol::OK); // MockSession won't trigger OnConnectionClosed, so fake it. client_session_->OnConnectionClosed(client_session_->connection(), protocol::OK); @@ -432,7 +432,7 @@ mouse_event.set_y(301); connection_->input_stub()->InjectMouseEvent(mouse_event); - client_session_->DisconnectSession(); + client_session_->DisconnectSession(protocol::OK); client_session_->OnConnectionClosed(connection_, protocol::OK); client_session_.reset(); }
diff --git a/remoting/host/continue_window.cc b/remoting/host/continue_window.cc index 35a7f90b5..9871591c9 100644 --- a/remoting/host/continue_window.cc +++ b/remoting/host/continue_window.cc
@@ -54,11 +54,10 @@ disconnect_timer_.Stop(); if (client_session_control_.get()) - client_session_control_->DisconnectSession(); + client_session_control_->DisconnectSession(protocol::MAX_SESSION_LENGTH); } -ContinueWindow::ContinueWindow() { -} +ContinueWindow::ContinueWindow() {} void ContinueWindow::OnSessionExpired() { DCHECK(CalledOnValidThread());
diff --git a/remoting/host/curtain_mode_mac.cc b/remoting/host/curtain_mode_mac.cc index 0ac4aa5..778731b 100644 --- a/remoting/host/curtain_mode_mac.cc +++ b/remoting/host/curtain_mode_mac.cc
@@ -16,11 +16,12 @@ #include "base/mac/scoped_cftyperef.h" #include "base/single_thread_task_runner.h" #include "remoting/host/client_session_control.h" +#include "remoting/protocol/errors.h" + +namespace remoting { namespace { -using remoting::ClientSessionControl; - const char* kCGSessionPath = "/System/Library/CoreServices/Menu Extras/User.menu/Contents/Resources/" "CGSession"; @@ -56,7 +57,7 @@ void RemoveEventHandler(); // Disconnects the client session. - void DisconnectSession(); + void DisconnectSession(protocol::ErrorCode error); // Handlers for the switch-in event. static OSStatus SessionActivateHandler(EventHandlerCallRef handler, @@ -122,7 +123,7 @@ // curtain mode on suitable versions of Lion. if (base::mac::IsOSLion()) { LOG(ERROR) << "Host curtaining is not supported on Mac OS X 10.7."; - DisconnectSession(); + DisconnectSession(protocol::ErrorCode::HOST_CONFIGURATION_ERROR); return; } @@ -130,7 +131,7 @@ // current session so that the console session is not affected if it fails. if (!InstallEventHandler()) { LOG(ERROR) << "Failed to install the switch-in handler."; - DisconnectSession(); + DisconnectSession(protocol::ErrorCode::HOST_CONFIGURATION_ERROR); return; } @@ -162,12 +163,12 @@ waitpid(child, &status, 0); if (status != 0) { LOG(ERROR) << kCGSessionPath << " failed."; - DisconnectSession(); + DisconnectSession(protocol::ErrorCode::HOST_CONFIGURATION_ERROR); return; } } else { LOG(ERROR) << "fork() failed."; - DisconnectSession(); + DisconnectSession(protocol::ErrorCode::HOST_CONFIGURATION_ERROR); return; } } @@ -185,7 +186,7 @@ &event_handler_); if (result != noErr) { event_handler_ = nullptr; - DisconnectSession(); + DisconnectSession(protocol::ErrorCode::HOST_CONFIGURATION_ERROR); return false; } @@ -201,28 +202,27 @@ } } -void SessionWatcher::DisconnectSession() { +void SessionWatcher::DisconnectSession(protocol::ErrorCode error) { if (!caller_task_runner_->BelongsToCurrentThread()) { caller_task_runner_->PostTask( - FROM_HERE, base::Bind(&SessionWatcher::DisconnectSession, this)); + FROM_HERE, base::Bind(&SessionWatcher::DisconnectSession, this, error)); return; } if (client_session_control_) - client_session_control_->DisconnectSession(); + client_session_control_->DisconnectSession(error); } OSStatus SessionWatcher::SessionActivateHandler(EventHandlerCallRef handler, EventRef event, void* user_data) { - static_cast<SessionWatcher*>(user_data)->DisconnectSession(); + static_cast<SessionWatcher*>(user_data) + ->DisconnectSession(protocol::ErrorCode::OK); return noErr; } } // namespace -namespace remoting { - class CurtainModeMac : public CurtainMode { public: CurtainModeMac(
diff --git a/remoting/host/desktop_session_agent.cc b/remoting/host/desktop_session_agent.cc index 840d5883..23d05f2 100644 --- a/remoting/host/desktop_session_agent.cc +++ b/remoting/host/desktop_session_agent.cc
@@ -24,6 +24,7 @@ #include "remoting/proto/control.pb.h" #include "remoting/proto/event.pb.h" #include "remoting/protocol/clipboard_stub.h" +#include "remoting/protocol/errors.h" #include "remoting/protocol/input_event_tracker.h" #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" @@ -222,8 +223,8 @@ return client_jid_; } -void DesktopSessionAgent::DisconnectSession() { - SendToNetwork(new ChromotingDesktopNetworkMsg_DisconnectSession()); +void DesktopSessionAgent::DisconnectSession(protocol::ErrorCode error) { + SendToNetwork(new ChromotingDesktopNetworkMsg_DisconnectSession(error)); } void DesktopSessionAgent::OnLocalMouseMoved(
diff --git a/remoting/host/desktop_session_agent.h b/remoting/host/desktop_session_agent.h index 9d6c4e07..8f407d1c 100644 --- a/remoting/host/desktop_session_agent.h +++ b/remoting/host/desktop_session_agent.h
@@ -107,7 +107,7 @@ // ClientSessionControl interface. const std::string& client_jid() const override; - void DisconnectSession() override; + void DisconnectSession(protocol::ErrorCode error) override; void OnLocalMouseMoved(const webrtc::DesktopVector& position) override; void SetDisableInputs(bool disable_inputs) override; void ResetVideoPipeline() override;
diff --git a/remoting/host/desktop_session_proxy.cc b/remoting/host/desktop_session_proxy.cc index 27e8af6..4536500 100644 --- a/remoting/host/desktop_session_proxy.cc +++ b/remoting/host/desktop_session_proxy.cc
@@ -331,12 +331,12 @@ mouse_cursor_monitor_ = mouse_cursor_monitor; } -void DesktopSessionProxy::DisconnectSession() { +void DesktopSessionProxy::DisconnectSession(protocol::ErrorCode error) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); // Disconnect the client session if it hasn't been disconnected yet. if (client_session_control_.get()) - client_session_control_->DisconnectSession(); + client_session_control_->DisconnectSession(error); } void DesktopSessionProxy::InjectClipboardEvent(
diff --git a/remoting/host/desktop_session_proxy.h b/remoting/host/desktop_session_proxy.h index bae2a80..7ebf6e8 100644 --- a/remoting/host/desktop_session_proxy.h +++ b/remoting/host/desktop_session_proxy.h
@@ -20,6 +20,7 @@ #include "remoting/host/screen_resolution.h" #include "remoting/proto/event.pb.h" #include "remoting/protocol/clipboard_stub.h" +#include "remoting/protocol/errors.h" #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h" namespace base { @@ -101,7 +102,7 @@ void DetachFromDesktop(); // Disconnects the client session that owns |this|. - void DisconnectSession(); + void DisconnectSession(protocol::ErrorCode error); // Stores |audio_capturer| to be used to post captured audio packets. Called // on the |audio_capture_task_runner_| thread.
diff --git a/remoting/host/disconnect_window_chromeos.cc b/remoting/host/disconnect_window_chromeos.cc index d2f8c01..981e3f6 100644 --- a/remoting/host/disconnect_window_chromeos.cc +++ b/remoting/host/disconnect_window_chromeos.cc
@@ -40,7 +40,7 @@ base::string16 helper_name; ash::Shell::GetInstance()->system_tray_notifier()->NotifyScreenShareStart( base::Bind(&ClientSessionControl::DisconnectSession, - client_session_control), + client_session_control, protocol::OK), helper_name); }
diff --git a/remoting/host/disconnect_window_linux.cc b/remoting/host/disconnect_window_linux.cc index b913ea55..0d9fae13 100644 --- a/remoting/host/disconnect_window_linux.cc +++ b/remoting/host/disconnect_window_linux.cc
@@ -172,7 +172,7 @@ DCHECK(CalledOnValidThread()); if (client_session_control_.get()) - client_session_control_->DisconnectSession(); + client_session_control_->DisconnectSession(protocol::OK); } gboolean DisconnectWindowGtk::OnDelete(GtkWidget* window, @@ -180,7 +180,7 @@ DCHECK(CalledOnValidThread()); if (client_session_control_.get()) - client_session_control_->DisconnectSession(); + client_session_control_->DisconnectSession(protocol::OK); return TRUE; }
diff --git a/remoting/host/disconnect_window_mac.mm b/remoting/host/disconnect_window_mac.mm index 623c3af..06c9762 100644 --- a/remoting/host/disconnect_window_mac.mm +++ b/remoting/host/disconnect_window_mac.mm
@@ -63,7 +63,7 @@ // Create the window. base::Closure disconnect_callback = base::Bind(&ClientSessionControl::DisconnectSession, - client_session_control); + client_session_control, protocol::OK); std::string client_jid = client_session_control->client_jid(); std::string username = client_jid.substr(0, client_jid.find('/')); window_controller_ =
diff --git a/remoting/host/disconnect_window_win.cc b/remoting/host/disconnect_window_win.cc index c0a7ecc1..dff48cec 100644 --- a/remoting/host/disconnect_window_win.cc +++ b/remoting/host/disconnect_window_win.cc
@@ -262,7 +262,7 @@ } if (client_session_control_) - client_session_control_->DisconnectSession(); + client_session_control_->DisconnectSession(protocol::OK); } // Returns |control| rectangle in the dialog coordinates.
diff --git a/remoting/host/host_mock_objects.h b/remoting/host/host_mock_objects.h index d4462c8..eaae574 100644 --- a/remoting/host/host_mock_objects.h +++ b/remoting/host/host_mock_objects.h
@@ -61,7 +61,7 @@ ~MockClientSessionControl() override; MOCK_CONST_METHOD0(client_jid, const std::string&()); - MOCK_METHOD0(DisconnectSession, void()); + MOCK_METHOD1(DisconnectSession, void(protocol::ErrorCode error)); MOCK_METHOD1(OnLocalMouseMoved, void(const webrtc::DesktopVector&)); MOCK_METHOD1(SetDisableInputs, void(bool)); MOCK_METHOD0(ResetVideoPipeline, void());
diff --git a/remoting/host/host_window_proxy.cc b/remoting/host/host_window_proxy.cc index bdaf519..e5be6167 100644 --- a/remoting/host/host_window_proxy.cc +++ b/remoting/host/host_window_proxy.cc
@@ -38,7 +38,7 @@ // ClientSessionControl interface. const std::string& client_jid() const override; - void DisconnectSession() override; + void DisconnectSession(protocol::ErrorCode error) override; void OnLocalMouseMoved(const webrtc::DesktopVector& position) override; void SetDisableInputs(bool disable_inputs) override; void ResetVideoPipeline() override; @@ -143,15 +143,15 @@ return client_jid_; } -void HostWindowProxy::Core::DisconnectSession() { +void HostWindowProxy::Core::DisconnectSession(protocol::ErrorCode error) { if (!caller_task_runner_->BelongsToCurrentThread()) { - caller_task_runner_->PostTask(FROM_HERE, - base::Bind(&Core::DisconnectSession, this)); + caller_task_runner_->PostTask( + FROM_HERE, base::Bind(&Core::DisconnectSession, this, error)); return; } if (client_session_control_.get()) - client_session_control_->DisconnectSession(); + client_session_control_->DisconnectSession(error); } void HostWindowProxy::Core::OnLocalMouseMoved(
diff --git a/remoting/host/installer/linux/Makefile b/remoting/host/installer/linux/Makefile index 06851ce4..73d11f49 100644 --- a/remoting/host/installer/linux/Makefile +++ b/remoting/host/installer/linux/Makefile
@@ -6,7 +6,9 @@ # variables not defined here, such as DESTDIR. SRC_DIR = ../../../.. -BUILD_DIR = $(SRC_DIR)/out/Release +ifndef BUILD_DIR + BUILD_DIR = $(SRC_DIR)/out/Release +endif CRON_DIR = $(DESTDIR)/etc/cron.daily DOC_DIR = $(DESTDIR)/usr/share/doc/chrome-remote-desktop
diff --git a/remoting/host/installer/linux/build-deb.sh b/remoting/host/installer/linux/build-deb.sh index 6f27d468..951d935 100755 --- a/remoting/host/installer/linux/build-deb.sh +++ b/remoting/host/installer/linux/build-deb.sh
@@ -40,7 +40,7 @@ echo "-h this help message" echo "-p just print the expected DEB filename that this will build." echo "-s path to the top of the src tree." - echo "-o path to write the DEB file to." + echo "-o output directory path." } while getopts ":s:o:ph" OPTNAME @@ -107,6 +107,10 @@ revision_text="(r$revision)" fi +if [[ ! "$OUTPUT_PATH" ]]; then + OUTPUT_PATH="${SCRIPTDIR}/../../../../out/Release" +fi + echo "Building version $version_full $revision_text" # Create a fresh debian/changelog. @@ -120,7 +124,7 @@ "New Debian package $revision_text" -CRON_SCRIPT_DIR="${SCRIPTDIR}/../../../../out/Release/remoting/installer/cron" +CRON_SCRIPT_DIR="${OUTPUT_PATH}/remoting/installer/cron" mkdir -p ${CRON_SCRIPT_DIR} process_template \ "${SCRIPTDIR}/../../../../chrome/installer/linux/common/repo.cron" \ @@ -134,10 +138,8 @@ # but it seems that we don't currently, so this is the most expediant fix. SAVE_LDLP=$LD_LIBRARY_PATH unset LD_LIBRARY_PATH -dpkg-buildpackage -b -us -uc +BUILD_DIR=$OUTPUT_PATH dpkg-buildpackage -b -us -uc LD_LIBRARY_PATH=$SAVE_LDLP -if [[ "$OUTPUT_PATH" ]]; then - mv ../${PACKAGE}_*.deb "$OUTPUT_PATH"/ - mv ../${PACKAGE}_*.changes "$OUTPUT_PATH"/ -fi +mv ../${PACKAGE}_*.deb "$OUTPUT_PATH"/ +mv ../${PACKAGE}_*.changes "$OUTPUT_PATH"/
diff --git a/remoting/host/installer/linux/build_deb.py b/remoting/host/installer/linux/build_deb.py new file mode 100644 index 0000000..3be7c421 --- /dev/null +++ b/remoting/host/installer/linux/build_deb.py
@@ -0,0 +1,22 @@ +# Copyright 2015 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. + +"""A simple python wrapper so GN can run build-deb.sh.""" +import os +import subprocess +import sys + + +def main(): + this_dir = os.path.dirname(os.path.abspath(__file__)) + build_deb_script = os.path.join(this_dir, 'build-deb.sh') + proc = subprocess.Popen([build_deb_script] + sys.argv[1:], + stdout=subprocess.PIPE) + out, _ = proc.communicate() + sys.stdout.write(out.strip()) + return proc.returncode + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/remoting/host/ipc_desktop_environment.cc b/remoting/host/ipc_desktop_environment.cc index 37bd89f..cc6417e 100644 --- a/remoting/host/ipc_desktop_environment.cc +++ b/remoting/host/ipc_desktop_environment.cc
@@ -222,7 +222,7 @@ active_connections_.erase(i); // Disconnect the client session. - desktop_session_proxy->DisconnectSession(); + desktop_session_proxy->DisconnectSession(protocol::OK); } }
diff --git a/remoting/host/ipc_desktop_environment_unittest.cc b/remoting/host/ipc_desktop_environment_unittest.cc index 9bfb621..1de0f29 100644 --- a/remoting/host/ipc_desktop_environment_unittest.cc +++ b/remoting/host/ipc_desktop_environment_unittest.cc
@@ -275,9 +275,9 @@ EXPECT_CALL(client_session_control_, client_jid()) .Times(AnyNumber()) .WillRepeatedly(ReturnRef(client_jid_)); - EXPECT_CALL(client_session_control_, DisconnectSession()) + EXPECT_CALL(client_session_control_, DisconnectSession(_)) .Times(AnyNumber()) - .WillRepeatedly(Invoke( + .WillRepeatedly(InvokeWithoutArgs( this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment)); EXPECT_CALL(client_session_control_, OnLocalMouseMoved(_)) .Times(0);
diff --git a/remoting/host/local_input_monitor_chromeos.cc b/remoting/host/local_input_monitor_chromeos.cc index dab02e5..1594f87 100644 --- a/remoting/host/local_input_monitor_chromeos.cc +++ b/remoting/host/local_input_monitor_chromeos.cc
@@ -133,7 +133,7 @@ key_event.key_code() == ui::VKEY_ESCAPE) { caller_task_runner_->PostTask( FROM_HERE, base::Bind(&ClientSessionControl::DisconnectSession, - client_session_control_)); + client_session_control_, protocol::OK)); } }
diff --git a/remoting/host/local_input_monitor_mac.mm b/remoting/host/local_input_monitor_mac.mm index e3bd3d5..1388877 100644 --- a/remoting/host/local_input_monitor_mac.mm +++ b/remoting/host/local_input_monitor_mac.mm
@@ -270,7 +270,7 @@ void LocalInputMonitorMac::Core::OnDisconnectShortcut() { caller_task_runner_->PostTask( FROM_HERE, base::Bind(&ClientSessionControl::DisconnectSession, - client_session_control_)); + client_session_control_, protocol::OK)); } } // namespace
diff --git a/remoting/host/local_input_monitor_unittest.cc b/remoting/host/local_input_monitor_unittest.cc index b483a0a..8f19af64 100644 --- a/remoting/host/local_input_monitor_unittest.cc +++ b/remoting/host/local_input_monitor_unittest.cc
@@ -67,7 +67,7 @@ EXPECT_CALL(client_session_control_, client_jid()) .Times(AnyNumber()) .WillRepeatedly(ReturnRef(client_jid_)); - EXPECT_CALL(client_session_control_, DisconnectSession()) + EXPECT_CALL(client_session_control_, DisconnectSession(_)) .Times(AnyNumber()); EXPECT_CALL(client_session_control_, OnLocalMouseMoved(_)) .Times(AnyNumber());
diff --git a/remoting/host/local_input_monitor_win.cc b/remoting/host/local_input_monitor_win.cc index 1b92e03..74975ec 100644 --- a/remoting/host/local_input_monitor_win.cc +++ b/remoting/host/local_input_monitor_win.cc
@@ -133,7 +133,7 @@ // the session. Disconnect the session now to prevent this. caller_task_runner_->PostTask( FROM_HERE, base::Bind(&ClientSessionControl::DisconnectSession, - client_session_control_)); + client_session_control_, protocol::OK)); } }
diff --git a/remoting/host/local_input_monitor_x11.cc b/remoting/host/local_input_monitor_x11.cc index 9e410f8f..b515b698 100644 --- a/remoting/host/local_input_monitor_x11.cc +++ b/remoting/host/local_input_monitor_x11.cc
@@ -300,7 +300,7 @@ } else if (key_sym == XK_Escape && down && alt_pressed_ && ctrl_pressed_) { caller_task_runner_->PostTask( FROM_HERE, base::Bind(&ClientSessionControl::DisconnectSession, - client_session_control_)); + client_session_control_, protocol::OK)); } } }
diff --git a/remoting/host/win/worker_process_launcher_unittest.cc b/remoting/host/win/worker_process_launcher_unittest.cc index a689c755..ee58120f 100644 --- a/remoting/host/win/worker_process_launcher_unittest.cc +++ b/remoting/host/win/worker_process_launcher_unittest.cc
@@ -303,8 +303,10 @@ } void WorkerProcessLauncherTest::SendFakeMessageToLauncher() { - if (channel_client_) - channel_client_->Send(new ChromotingDesktopNetworkMsg_DisconnectSession()); + if (channel_client_) { + channel_client_->Send( + new ChromotingDesktopNetworkMsg_DisconnectSession(protocol::OK)); + } } void WorkerProcessLauncherTest::CrashWorker() {
diff --git a/remoting/protocol/connection_to_client.cc b/remoting/protocol/connection_to_client.cc index 18943f4f..4cf331b 100644 --- a/remoting/protocol/connection_to_client.cc +++ b/remoting/protocol/connection_to_client.cc
@@ -36,14 +36,14 @@ return session_.get(); } -void ConnectionToClient::Disconnect() { +void ConnectionToClient::Disconnect(ErrorCode error) { DCHECK(CalledOnValidThread()); CloseChannels(); // This should trigger OnConnectionClosed() event and this object // may be destroyed as the result. - session_->Close(); + session_->Close(error); } void ConnectionToClient::OnInputEventReceived(int64_t timestamp) {
diff --git a/remoting/protocol/connection_to_client.h b/remoting/protocol/connection_to_client.h index 2425546..5e7bc67 100644 --- a/remoting/protocol/connection_to_client.h +++ b/remoting/protocol/connection_to_client.h
@@ -79,7 +79,7 @@ virtual Session* session(); // Disconnect the client connection. - virtual void Disconnect(); + virtual void Disconnect(ErrorCode error); // Callback for HostEventDispatcher to be called with a timestamp for each // received event.
diff --git a/remoting/protocol/connection_to_client_unittest.cc b/remoting/protocol/connection_to_client_unittest.cc index e62c2cb..472efcc7 100644 --- a/remoting/protocol/connection_to_client_unittest.cc +++ b/remoting/protocol/connection_to_client_unittest.cc
@@ -81,7 +81,7 @@ EXPECT_FALSE(channel->written_data().empty()); // And then close the connection to ConnectionToClient. - viewer_->Disconnect(); + viewer_->Disconnect(protocol::OK); base::RunLoop().RunUntilIdle(); } @@ -91,7 +91,7 @@ viewer_->video_stub()->ProcessVideoPacket(packet.Pass(), base::Closure()); // And then close the connection to ConnectionToClient. - viewer_->Disconnect(); + viewer_->Disconnect(protocol::OK); // The test will crash if data writer tries to write data to the // channel socket.
diff --git a/remoting/protocol/errors.cc b/remoting/protocol/errors.cc index 9c92e54..12b0b1d 100644 --- a/remoting/protocol/errors.cc +++ b/remoting/protocol/errors.cc
@@ -24,6 +24,8 @@ RETURN_STRING_LITERAL(SIGNALING_ERROR); RETURN_STRING_LITERAL(SIGNALING_TIMEOUT); RETURN_STRING_LITERAL(HOST_OVERLOAD); + RETURN_STRING_LITERAL(MAX_SESSION_LENGTH); + RETURN_STRING_LITERAL(HOST_CONFIGURATION_ERROR); RETURN_STRING_LITERAL(UNKNOWN_ERROR); } NOTREACHED();
diff --git a/remoting/protocol/errors.h b/remoting/protocol/errors.h index 4f91e23..4dcf4e9 100644 --- a/remoting/protocol/errors.h +++ b/remoting/protocol/errors.h
@@ -22,7 +22,11 @@ SIGNALING_ERROR, SIGNALING_TIMEOUT, HOST_OVERLOAD, + MAX_SESSION_LENGTH, + HOST_CONFIGURATION_ERROR, UNKNOWN_ERROR, + + ERROR_CODE_MAX = UNKNOWN_ERROR, }; // Returns the literal string of |error|.
diff --git a/remoting/protocol/fake_session.cc b/remoting/protocol/fake_session.cc index afebf4b..93b6f393 100644 --- a/remoting/protocol/fake_session.cc +++ b/remoting/protocol/fake_session.cc
@@ -69,8 +69,9 @@ return transport_.GetStreamChannelFactory(); } -void FakeSession::Close() { +void FakeSession::Close(ErrorCode error) { closed_ = true; + error_ = error; } } // namespace protocol
diff --git a/remoting/protocol/fake_session.h b/remoting/protocol/fake_session.h index 6800692..062a3f4 100644 --- a/remoting/protocol/fake_session.h +++ b/remoting/protocol/fake_session.h
@@ -56,7 +56,7 @@ const SessionConfig& config() override; FakeTransport* GetTransport() override; FakeStreamChannelFactory* GetQuicChannelFactory() override; - void Close() override; + void Close(ErrorCode error) override; public: EventHandler* event_handler_;
diff --git a/remoting/protocol/jingle_messages.cc b/remoting/protocol/jingle_messages.cc index bc248e9a8..2b73007 100644 --- a/remoting/protocol/jingle_messages.cc +++ b/remoting/protocol/jingle_messages.cc
@@ -43,7 +43,9 @@ { JingleMessage::SUCCESS, "success" }, { JingleMessage::DECLINE, "decline" }, { JingleMessage::CANCEL, "cancel" }, + { JingleMessage::EXPIRED, "expired" }, { JingleMessage::GENERAL_ERROR, "general-error" }, + { JingleMessage::FAILED_APPLICATION, "failed-application" }, { JingleMessage::INCOMPATIBLE_PARAMETERS, "incompatible-parameters" }, };
diff --git a/remoting/protocol/jingle_messages.h b/remoting/protocol/jingle_messages.h index 32b78c17..96a0f488 100644 --- a/remoting/protocol/jingle_messages.h +++ b/remoting/protocol/jingle_messages.h
@@ -32,7 +32,9 @@ SUCCESS, DECLINE, CANCEL, + EXPIRED, GENERAL_ERROR, + FAILED_APPLICATION, INCOMPATIBLE_PARAMETERS, };
diff --git a/remoting/protocol/jingle_session.cc b/remoting/protocol/jingle_session.cc index c1b8b7b5..46cc311b 100644 --- a/remoting/protocol/jingle_session.cc +++ b/remoting/protocol/jingle_session.cc
@@ -138,7 +138,7 @@ if (!config_) { LOG(WARNING) << "Rejecting connection from " << peer_jid_ << " because no compatible configuration has been found."; - CloseInternal(INCOMPATIBLE_PROTOCOL); + Close(INCOMPATIBLE_PROTOCOL); return; } @@ -146,7 +146,7 @@ quic_channel_factory_.reset(new QuicChannelFactory(session_id_, true)); if (!quic_channel_factory_->ProcessSessionInitiateConfigMessage( initiate_message.description->quic_config_message())) { - CloseInternal(INCOMPATIBLE_PROTOCOL); + Close(INCOMPATIBLE_PROTOCOL); } } @@ -162,7 +162,7 @@ initiate_message.description->authenticator_message(); if (!first_auth_message) { - CloseInternal(INCOMPATIBLE_PROTOCOL); + Close(INCOMPATIBLE_PROTOCOL); return; } @@ -176,8 +176,7 @@ void JingleSession::ContinueAcceptIncomingConnection() { DCHECK_NE(authenticator_->state(), Authenticator::PROCESSING_MESSAGE); if (authenticator_->state() == Authenticator::REJECTED) { - CloseInternal(AuthRejectionReasonToErrorCode( - authenticator_->rejection_reason())); + Close(AuthRejectionReasonToErrorCode(authenticator_->rejection_reason())); return; } @@ -230,10 +229,51 @@ return quic_channel_factory_.get(); } -void JingleSession::Close() { +void JingleSession::Close(protocol::ErrorCode error) { DCHECK(CalledOnValidThread()); - CloseInternal(OK); + if (is_session_active()) { + // Send session-terminate message with the appropriate error code. + JingleMessage::Reason reason; + switch (error) { + case OK: + reason = JingleMessage::SUCCESS; + break; + case SESSION_REJECTED: + case AUTHENTICATION_FAILED: + reason = JingleMessage::DECLINE; + break; + case INCOMPATIBLE_PROTOCOL: + reason = JingleMessage::INCOMPATIBLE_PARAMETERS; + break; + case HOST_OVERLOAD: + reason = JingleMessage::CANCEL; + break; + case MAX_SESSION_LENGTH: + reason = JingleMessage::EXPIRED; + break; + case HOST_CONFIGURATION_ERROR: + reason = JingleMessage::FAILED_APPLICATION; + break; + default: + reason = JingleMessage::GENERAL_ERROR; + } + + JingleMessage message(peer_jid_, JingleMessage::SESSION_TERMINATE, + session_id_); + message.reason = reason; + SendMessage(message); + } + + error_ = error; + + if (state_ != FAILED && state_ != CLOSED) { + if (error != OK) { + SetState(FAILED); + } else { + SetState(CLOSED); + } + } } void JingleSession::SendMessage(const JingleMessage& message) { @@ -274,7 +314,7 @@ // |response| will be nullptr if the request timed out. if (!response) { LOG(ERROR) << type_str << " request timed out."; - CloseInternal(SIGNALING_TIMEOUT); + Close(SIGNALING_TIMEOUT); return; } else { const std::string& type = @@ -286,7 +326,7 @@ // TODO(sergeyu): There may be different reasons for error // here. Parse the response stanza to find failure reason. - CloseInternal(PEER_IS_OFFLINE); + Close(PEER_IS_OFFLINE); } } } @@ -313,7 +353,7 @@ } void JingleSession::OnTransportError(ErrorCode error) { - CloseInternal(error); + Close(error); } void JingleSession::OnTransportInfoResponse(IqRequest* request, @@ -342,7 +382,7 @@ if (type != "result") { LOG(ERROR) << "Received error in response to transport-info message: \"" << response->Str() << "\". Terminating the session."; - CloseInternal(PEER_IS_OFFLINE); + Close(PEER_IS_OFFLINE); } } @@ -395,19 +435,19 @@ message.description->authenticator_message(); if (!auth_message) { DLOG(WARNING) << "Received session-accept without authentication message "; - CloseInternal(INCOMPATIBLE_PROTOCOL); + Close(INCOMPATIBLE_PROTOCOL); return; } if (!InitializeConfigFromDescription(message.description.get())) { - CloseInternal(INCOMPATIBLE_PROTOCOL); + Close(INCOMPATIBLE_PROTOCOL); return; } if (config_->is_using_quic()) { if (!quic_channel_factory_->ProcessSessionAcceptConfigMessage( message.description->quic_config_message())) { - CloseInternal(INCOMPATIBLE_PROTOCOL); + Close(INCOMPATIBLE_PROTOCOL); return; } } else { @@ -434,7 +474,7 @@ LOG(WARNING) << "Received unexpected authenticator message " << message.info->Str(); reply_callback.Run(JingleMessageReply::UNEXPECTED_REQUEST); - CloseInternal(INCOMPATIBLE_PROTOCOL); + Close(INCOMPATIBLE_PROTOCOL); return; } @@ -468,12 +508,18 @@ case JingleMessage::CANCEL: error_ = HOST_OVERLOAD; break; - case JingleMessage::GENERAL_ERROR: - error_ = CHANNEL_CONNECTION_ERROR; + case JingleMessage::EXPIRED: + error_ = MAX_SESSION_LENGTH; break; case JingleMessage::INCOMPATIBLE_PARAMETERS: error_ = INCOMPATIBLE_PROTOCOL; break; + case JingleMessage::FAILED_APPLICATION: + error_ = HOST_CONFIGURATION_ERROR; + break; + case JingleMessage::GENERAL_ERROR: + error_ = CHANNEL_CONNECTION_ERROR; + break; default: error_ = UNKNOWN_ERROR; } @@ -538,7 +584,7 @@ if (authenticator_->state() == Authenticator::ACCEPTED) { OnAuthenticated(); } else if (authenticator_->state() == Authenticator::REJECTED) { - CloseInternal(AuthRejectionReasonToErrorCode( + Close(AuthRejectionReasonToErrorCode( authenticator_->rejection_reason())); } } @@ -554,47 +600,6 @@ SetState(AUTHENTICATED); } -void JingleSession::CloseInternal(ErrorCode error) { - DCHECK(CalledOnValidThread()); - - if (is_session_active()) { - // Send session-terminate message with the appropriate error code. - JingleMessage::Reason reason; - switch (error) { - case OK: - reason = JingleMessage::SUCCESS; - break; - case SESSION_REJECTED: - case AUTHENTICATION_FAILED: - reason = JingleMessage::DECLINE; - break; - case INCOMPATIBLE_PROTOCOL: - reason = JingleMessage::INCOMPATIBLE_PARAMETERS; - break; - case HOST_OVERLOAD: - reason = JingleMessage::CANCEL; - break; - default: - reason = JingleMessage::GENERAL_ERROR; - } - - JingleMessage message(peer_jid_, JingleMessage::SESSION_TERMINATE, - session_id_); - message.reason = reason; - SendMessage(message); - } - - error_ = error; - - if (state_ != FAILED && state_ != CLOSED) { - if (error != OK) { - SetState(FAILED); - } else { - SetState(CLOSED); - } - } -} - void JingleSession::SetState(State new_state) { DCHECK(CalledOnValidThread());
diff --git a/remoting/protocol/jingle_session.h b/remoting/protocol/jingle_session.h index f4734641..cb8fd96 100644 --- a/remoting/protocol/jingle_session.h +++ b/remoting/protocol/jingle_session.h
@@ -44,7 +44,7 @@ const SessionConfig& config() override; Transport* GetTransport() override; StreamChannelFactory* GetQuicChannelFactory() override; - void Close() override; + void Close(protocol::ErrorCode error) override; private: friend class JingleSessionManager; @@ -113,11 +113,6 @@ // Called when authentication is finished. void OnAuthenticated(); - // Terminates the session and sends session-terminate if it is - // necessary. |error| specifies the error code in case when the - // session is being closed due to an error. - void CloseInternal(ErrorCode error); - // Sets |state_| to |new_state| and calls state change callback. void SetState(State new_state);
diff --git a/remoting/protocol/jingle_session_manager.cc b/remoting/protocol/jingle_session_manager.cc index c0a0d8a6..d6300854 100644 --- a/remoting/protocol/jingle_session_manager.cc +++ b/remoting/protocol/jingle_session_manager.cc
@@ -141,7 +141,7 @@ error = SESSION_REJECTED; } - session->CloseInternal(error); + session->Close(error); delete session; DCHECK(sessions_.find(message.sid) == sessions_.end()); }
diff --git a/remoting/protocol/protocol_mock_objects.h b/remoting/protocol/protocol_mock_objects.h index 6c67588..fcfa120 100644 --- a/remoting/protocol/protocol_mock_objects.h +++ b/remoting/protocol/protocol_mock_objects.h
@@ -39,7 +39,7 @@ MOCK_METHOD0(video_stub, VideoStub*()); MOCK_METHOD0(client_stub, ClientStub*()); MOCK_METHOD0(session, Session*()); - MOCK_METHOD0(Disconnect, void()); + MOCK_METHOD1(Disconnect, void(ErrorCode error)); void set_clipboard_stub(ClipboardStub* clipboard_stub) override { clipboard_stub_ = clipboard_stub; @@ -213,7 +213,7 @@ MOCK_METHOD1(set_receiver_token, void(const std::string& receiver_token)); MOCK_METHOD1(set_shared_secret, void(const std::string& secret)); MOCK_METHOD0(shared_secret, const std::string&()); - MOCK_METHOD0(Close, void()); + MOCK_METHOD1(Close, void(ErrorCode error)); private: DISALLOW_COPY_AND_ASSIGN(MockSession);
diff --git a/remoting/protocol/session.h b/remoting/protocol/session.h index 9e539e5e..9710ad6 100644 --- a/remoting/protocol/session.h +++ b/remoting/protocol/session.h
@@ -89,10 +89,10 @@ // disabled for the session. virtual StreamChannelFactory* GetQuicChannelFactory() = 0; - // Closes connection. Callbacks are guaranteed not to be called - // after this method returns. Must be called before the object is - // destroyed, unless the state is set to FAILED or CLOSED. - virtual void Close() = 0; + // Closes connection. Callbacks are guaranteed not to be called after this + // method returns. |error| specifies the error code in case when the session + // is being closed due to an error. + virtual void Close(ErrorCode error) = 0; private: DISALLOW_COPY_AND_ASSIGN(Session);
diff --git a/remoting/remoting_host.gypi b/remoting/remoting_host.gypi index de2a5d96..99794b22 100644 --- a/remoting/remoting_host.gypi +++ b/remoting/remoting_host.gypi
@@ -95,6 +95,7 @@ 'sources!' : [ 'host/clipboard_x11.cc', 'host/continue_window_linux.cc', + 'host/curtain_mode_linux.cc', 'host/disconnect_window_linux.cc', 'host/linux/x_server_clipboard.cc', 'host/linux/x_server_clipboard.h', @@ -264,6 +265,7 @@ # Generates native messaging manifest files. { + # GN: //remoting/host:remoting_native_messaging_manifests 'target_name': 'remoting_native_messaging_manifests', 'type': 'none', 'conditions': [ @@ -339,6 +341,7 @@ ], }, # end of target 'remoting_start_host' { + # GN: //remoting/host:remoting_infoplist_strings 'target_name': 'remoting_infoplist_strings', 'type': 'none', 'dependencies': [ @@ -419,14 +422,8 @@ 'VERSION=<(version_full)', ], 'sources': [ - 'host/curtain_mode.h', - 'host/curtain_mode_linux.cc', - 'host/curtain_mode_mac.cc', - 'host/curtain_mode_win.cc', 'host/pam_authorization_factory_posix.cc', 'host/pam_authorization_factory_posix.h', - 'host/posix/signal_handler.cc', - 'host/posix/signal_handler.h', 'host/remoting_me2me_host.cc', ], 'conditions': [ @@ -557,6 +554,7 @@ ], # end of 'conditions' }, # end of target 'remoting_me2me_host' { + # GN: //remoting/host:native_messaging_host 'target_name': 'remoting_me2me_native_messaging_host', 'type': 'executable', 'product_name': 'native_messaging_host', @@ -649,6 +647,7 @@ ['chromeos==0', { 'targets': [ { + # GN: //remoting/host/it2me:remote_assistance_host 'target_name': 'remoting_it2me_native_messaging_host', 'type': 'executable', 'product_name': 'remote_assistance_host',
diff --git a/remoting/remoting_host_linux.gypi b/remoting/remoting_host_linux.gypi index f9b89ea..ec890ea 100644 --- a/remoting/remoting_host_linux.gypi +++ b/remoting/remoting_host_linux.gypi
@@ -8,7 +8,7 @@ 'variables': { 'build_deb_script': 'host/installer/linux/build-deb.sh', - 'deb_filename': 'host/installer/<!(["<(build_deb_script)", "-p", "-s", "<(DEPTH)"])', + 'deb_filename': '<(PRODUCT_DIR)/<!(["<(build_deb_script)", "-p", "-s", "<(DEPTH)"])', 'packaging_outputs': [ '<(deb_filename)', '<!(echo <(deb_filename) | sed -e "s/.deb$/.changes/")', @@ -84,7 +84,11 @@ 'outputs': [ '<@(packaging_outputs)', ], - 'action': [ '<(build_deb_script)', '-s', '<(DEPTH)' ], + 'action': [ + '<(build_deb_script)', + '-s', '<(DEPTH)', + '-o', '<(PRODUCT_DIR)' + ], }, ], },
diff --git a/remoting/remoting_host_srcs.gypi b/remoting/remoting_host_srcs.gypi index 363a67d..306c070f 100644 --- a/remoting/remoting_host_srcs.gypi +++ b/remoting/remoting_host_srcs.gypi
@@ -64,6 +64,10 @@ 'host/continue_window_linux.cc', 'host/continue_window_mac.mm', 'host/continue_window_win.cc', + 'host/curtain_mode.h', + 'host/curtain_mode_linux.cc', + 'host/curtain_mode_mac.cc', + 'host/curtain_mode_win.cc', 'host/daemon_process.cc', 'host/daemon_process.h', 'host/daemon_process_win.cc', @@ -201,6 +205,8 @@ 'host/pin_hash.h', 'host/policy_watcher.cc', 'host/policy_watcher.h', + 'host/posix/signal_handler.cc', + 'host/posix/signal_handler.h', 'host/register_support_host_request.cc', 'host/register_support_host_request.h', 'host/remote_input_filter.cc',
diff --git a/remoting/remoting_options.gni b/remoting/remoting_options.gni index 2185f21..5f3d5b95 100644 --- a/remoting/remoting_options.gni +++ b/remoting/remoting_options.gni
@@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chrome_build.gni") + # These arguments can be overridden from the command line (see "gn help args"). declare_args() { # Set this to run the jscompile checks after building the webapp. @@ -26,7 +28,11 @@ remoting_rdp_session = 1 -branding_path = "../remoting/branding_<(branding)" +if (is_chrome_branded) { + branding_path = rebase_path("//remoting/branding_Chrome", root_build_dir) +} else { + branding_path = rebase_path("//remoting/branding_Chromium", root_build_dir) +} # The ar_service_environment variable is used to define the target # environment for the app being built.
diff --git a/remoting/resources/remoting_strings.grd b/remoting/resources/remoting_strings.grd index 46b6998..37102a7 100644 --- a/remoting/resources/remoting_strings.grd +++ b/remoting/resources/remoting_strings.grd
@@ -731,6 +731,13 @@ <message desc="Error that is shown on the client side when the host is blocking all connections due to failed authentication attempts." name="IDS_ERROR_HOST_OVERLOAD" formatter_data="android_java"> Connections to the remote computer are temporarily blocked because somebody was trying to connect to it with invalid PIN. Please try again later. </message> + <message desc="Error that is shown on the client side after the host has terminated connection that lasted more than maximum allowed duration." name="IDS_ERROR_MAX_SESSION_LENGTH" formatter_data="android_java"> + The remote session has expired. + </message> + <message desc="Error that is shown on the client side the host has failed to accept the connection due to a configuration issue." name="IDS_ERROR_HOST_CONFIGURATION_ERROR" formatter_data="android_java"> + The remote computer has failed to initialize the session. If problem persist please try to configure the host again. + </message> + <message desc="Error that is shown on the client side when we don't get a response from the host." name="IDS_ERROR_HOST_IS_OFFLINE" formatter_data="android_java"> The remote computer is not responding to connection requests. Please verify that it is online and try again. </message>
diff --git a/remoting/webapp/BUILD.gn b/remoting/webapp/BUILD.gn index f318ec7..3bc132b 100644 --- a/remoting/webapp/BUILD.gn +++ b/remoting/webapp/BUILD.gn
@@ -35,12 +35,8 @@ desktop_remoting_webapp("webapp") { webapp_type = "desktop" output_dir = "$root_build_dir/remoting/remoting-webapp.v2" - zip_path = "$root_build_dir/remoting/remoting-webapp.v2.zip" - extra_files = [ - "crd/remoting_client_pnacl.nmf.jinja2", - # TODO(garykac): Get correct path to this. - #"<(PRODUCT_DIR)/remoting_client_plugin_newlib.pexe", - ] + zip_path = "$root_build_dir/remoting-webapp.v2.zip" + extra_files = [ "crd/remoting_client_pnacl.nmf.jinja2" ] } app_remoting_webapp("ar_sample_app") {
diff --git a/remoting/webapp/base/js/chromoting_event.js b/remoting/webapp/base/js/chromoting_event.js index fad1074..1842e36 100644 --- a/remoting/webapp/base/js/chromoting_event.js +++ b/remoting/webapp/base/js/chromoting_event.js
@@ -264,6 +264,8 @@ UNEXPECTED: 13, CLIENT_SUSPENDED: 14, NACL_DISABLED: 15, + MAX_SESSION_LENGTH: 16, + HOST_CONFIGURATION_ERROR: 17, }; /** @enum {number} */
diff --git a/remoting/webapp/base/js/client_session.js b/remoting/webapp/base/js/client_session.js index f5bb9ba2..7b3f0cb 100644 --- a/remoting/webapp/base/js/client_session.js +++ b/remoting/webapp/base/js/client_session.js
@@ -178,7 +178,9 @@ SESSION_REJECTED: 2, INCOMPATIBLE_PROTOCOL: 3, NETWORK_FAILURE: 4, - HOST_OVERLOAD: 5 + HOST_OVERLOAD: 5, + MAX_SESSION_LENGTH: 6, + HOST_CONFIGURATION_ERROR: 7 }; /** @@ -456,24 +458,28 @@ if (status == remoting.ClientSession.State.FAILED) { switch (error) { case remoting.ClientSession.ConnectionError.HOST_IS_OFFLINE: - this.error_ = new remoting.Error( - remoting.Error.Tag.HOST_IS_OFFLINE); + this.error_ = new remoting.Error(remoting.Error.Tag.HOST_IS_OFFLINE); break; case remoting.ClientSession.ConnectionError.SESSION_REJECTED: - this.error_ = new remoting.Error( - remoting.Error.Tag.INVALID_ACCESS_CODE); + this.error_ = + new remoting.Error(remoting.Error.Tag.INVALID_ACCESS_CODE); break; case remoting.ClientSession.ConnectionError.INCOMPATIBLE_PROTOCOL: - this.error_ = new remoting.Error( - remoting.Error.Tag.INCOMPATIBLE_PROTOCOL); + this.error_ = + new remoting.Error(remoting.Error.Tag.INCOMPATIBLE_PROTOCOL); break; case remoting.ClientSession.ConnectionError.NETWORK_FAILURE: - this.error_ = new remoting.Error( - remoting.Error.Tag.P2P_FAILURE); + this.error_ = new remoting.Error(remoting.Error.Tag.P2P_FAILURE); break; case remoting.ClientSession.ConnectionError.HOST_OVERLOAD: - this.error_ = new remoting.Error( - remoting.Error.Tag.HOST_OVERLOAD); + this.error_ = new remoting.Error(remoting.Error.Tag.HOST_OVERLOAD); + break; + case remoting.ClientSession.ConnectionError.MAX_SESSION_LENGTH: + this.error_ = new remoting.Error(remoting.Error.Tag.MAX_SESSION_LENGTH); + break; + case remoting.ClientSession.ConnectionError.HOST_CONFIGURATION_ERROR: + this.error_ = + new remoting.Error(remoting.Error.Tag.HOST_CONFIGURATION_ERROR); break; default: this.error_ = remoting.Error.unexpected();
diff --git a/remoting/webapp/base/js/error.js b/remoting/webapp/base/js/error.js index 23ee1f8..697fde7 100644 --- a/remoting/webapp/base/js/error.js +++ b/remoting/webapp/base/js/error.js
@@ -62,6 +62,10 @@ return ConnectionError.NETWORK_FAILURE; case Tag.HOST_OVERLOAD: return ConnectionError.HOST_OVERLOAD; + case Tag.MAX_SESSION_LENGTH: + return ConnectionError.MAX_SESSION_LENGTH; + case Tag.HOST_CONFIGURATION_ERROR: + return ConnectionError.HOST_CONFIGURATION_ERROR; case Tag.P2P_FAILURE: return ConnectionError.P2P_FAILURE; case Tag.NACL_DISABLED: @@ -170,6 +174,8 @@ BAD_VERSION: /*i18n-content*/ 'ERROR_BAD_PLUGIN_VERSION', NETWORK_FAILURE: /*i18n-content*/ 'ERROR_NETWORK_FAILURE', HOST_OVERLOAD: /*i18n-content*/ 'ERROR_HOST_OVERLOAD', + MAX_SESSION_LENGTH: /*i18n-content*/ 'ERROR_MAX_SESSION_LENGTH', + HOST_CONFIGURATION_ERROR: /*i18n-content*/ 'ERROR_HOST_CONFIGURATION_ERROR', UNEXPECTED: /*i18n-content*/ 'ERROR_UNEXPECTED', SERVICE_UNAVAILABLE: /*i18n-content*/ 'ERROR_SERVICE_UNAVAILABLE', NOT_AUTHENTICATED: /*i18n-content*/ 'ERROR_NOT_AUTHENTICATED',
diff --git a/sandbox/linux/tests/unit_tests.cc b/sandbox/linux/tests/unit_tests.cc index 7ea28156..20966cb 100644 --- a/sandbox/linux/tests/unit_tests.cc +++ b/sandbox/linux/tests/unit_tests.cc
@@ -85,8 +85,8 @@ static const int kExitForTimeout = 2; #endif -#if defined(SANDBOX_USES_BASE_TEST_SUITE) -// This is due to StackDumpSignalHandler() performing _exit(1). +#if defined(ADDRESS_SANITIZER) +// ASAN catches SIGSEGV and then performs _exit(1). // TODO(jln): get rid of the collision with kExitWithAssertionFailure. const int kExitAfterSIGSEGV = 1; #endif @@ -305,14 +305,13 @@ std::string details(TestFailedMessage(msg)); const char* expected_msg = static_cast<const char*>(aux); -#if !defined(SANDBOX_USES_BASE_TEST_SUITE) - const bool subprocess_got_sigsegv = - WIFSIGNALED(status) && (SIGSEGV == WTERMSIG(status)); -#else - // This hack is required when a signal handler is installed - // for SEGV that will _exit(1). +#if defined(ADDRESS_SANITIZER) + // ASAN catches SIGSEGV and calls _exit(1). const bool subprocess_got_sigsegv = WIFEXITED(status) && (kExitAfterSIGSEGV == WEXITSTATUS(status)); +#else + const bool subprocess_got_sigsegv = + WIFSIGNALED(status) && (SIGSEGV == WTERMSIG(status)); #endif ASSERT_TRUE(subprocess_got_sigsegv) << "Exit status: " << status
diff --git a/sync/BUILD.gn b/sync/BUILD.gn index cfc2846..16ce82de 100644 --- a/sync/BUILD.gn +++ b/sync/BUILD.gn
@@ -167,6 +167,8 @@ "internal_api/js_sync_encryption_handler_observer.h", "internal_api/js_sync_manager_observer.cc", "internal_api/js_sync_manager_observer.h", + "internal_api/model_type_store_backend.cc", + "internal_api/model_type_store_impl.cc", "internal_api/protocol_event_buffer.cc", "internal_api/protocol_event_buffer.h", "internal_api/public/activation_context.h", @@ -235,6 +237,8 @@ "internal_api/public/internal_components_factory_impl.h", "internal_api/public/model_type_processor.cc", "internal_api/public/model_type_processor.h", + "internal_api/public/model_type_store_backend.h", + "internal_api/public/model_type_store_impl.h", "internal_api/public/network_resources.h", "internal_api/public/non_blocking_sync_common.cc", "internal_api/public/non_blocking_sync_common.h", @@ -573,6 +577,8 @@ "api/fake_sync_change_processor.h", "api/fake_syncable_service.cc", "api/fake_syncable_service.h", + "api/mock_model_type_store.cc", + "api/mock_model_type_store.h", "api/sync_change_processor_wrapper_for_test.cc", "api/sync_change_processor_wrapper_for_test.h", "api/sync_error_factory_mock.cc", @@ -635,6 +641,7 @@ "internal_api/js_mutation_event_observer_unittest.cc", "internal_api/js_sync_encryption_handler_observer_unittest.cc", "internal_api/js_sync_manager_observer_unittest.cc", + "internal_api/model_type_store_impl_unittest.cc", "internal_api/protocol_event_buffer_unittest.cc", "internal_api/public/base/attachment_id_proto_unittest.cc", "internal_api/public/base/cancelation_signal_unittest.cc",
diff --git a/sync/api/mock_model_type_store.cc b/sync/api/mock_model_type_store.cc new file mode 100644 index 0000000..6759be6c --- /dev/null +++ b/sync/api/mock_model_type_store.cc
@@ -0,0 +1,149 @@ +// Copyright 2015 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 "sync/api/mock_model_type_store.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" + +namespace syncer_v2 { + +MockModelTypeStore::MockModelTypeStore() {} + +MockModelTypeStore::~MockModelTypeStore() {} + +void MockModelTypeStore::ReadData(const IdList& id_list, + const ReadRecordsCallback& callback) { + if (!read_data_handler_.is_null()) { + read_data_handler_.Run(id_list, callback); + } else { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(callback, Result::SUCCESS, + base::Passed(scoped_ptr<RecordList>()))); + } +} + +void MockModelTypeStore::ReadAllData(const ReadRecordsCallback& callback) { + if (!read_all_data_handler_.is_null()) { + read_all_data_handler_.Run(callback); + } else { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(callback, Result::SUCCESS, + base::Passed(scoped_ptr<RecordList>()))); + } +} + +void MockModelTypeStore::ReadAllMetadata(const ReadMetadataCallback& callback) { + if (!read_all_metadata_handler_.is_null()) { + read_all_metadata_handler_.Run(callback); + } else { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(callback, Result::SUCCESS, + base::Passed(scoped_ptr<RecordList>()), std::string())); + } +} + +scoped_ptr<MockModelTypeStore::WriteBatch> +MockModelTypeStore::CreateWriteBatch() { + return make_scoped_ptr(new MockModelTypeStore::WriteBatch()); +} + +void MockModelTypeStore::CommitWriteBatch(scoped_ptr<WriteBatch> write_batch, + const CallbackWithResult& callback) { + if (!commit_write_batch_handler_.is_null()) { + commit_write_batch_handler_.Run(write_batch.Pass(), callback); + } else { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(callback, Result::SUCCESS)); + } +} + +void MockModelTypeStore::WriteData(WriteBatch* write_batch, + const std::string& id, + const std::string& value) { + if (!write_data_handler_.is_null()) { + write_data_handler_.Run(write_batch, id, value); + } +} + +void MockModelTypeStore::WriteMetadata(WriteBatch* write_batch, + const std::string& id, + const std::string& value) { + if (!write_metadata_handler_.is_null()) { + write_metadata_handler_.Run(write_batch, id, value); + } +} + +void MockModelTypeStore::WriteGlobalMetadata(WriteBatch* write_batch, + const std::string& value) { + if (!write_global_metadata_handler_.is_null()) { + write_global_metadata_handler_.Run(write_batch, value); + } +} + +void MockModelTypeStore::DeleteData(WriteBatch* write_batch, + const std::string& id) { + if (!delete_data_handler_.is_null()) { + delete_data_handler_.Run(write_batch, id); + } +} + +void MockModelTypeStore::DeleteMetadata(WriteBatch* write_batch, + const std::string& id) { + if (!delete_metadata_handler_.is_null()) { + delete_metadata_handler_.Run(write_batch, id); + } +} + +void MockModelTypeStore::DeleteGlobalMetadata(WriteBatch* write_batch) { + if (!delete_global_metadata_handler_.is_null()) { + delete_global_metadata_handler_.Run(write_batch); + } +} + +void MockModelTypeStore::RegisterReadDataHandler( + const ReadRecordsSignature& handler) { + read_data_handler_ = handler; +} + +void MockModelTypeStore::RegisterReadAllDataHandler( + const ReadAllRecordsSignature& handler) { + read_all_data_handler_ = handler; +} + +void MockModelTypeStore::RegisterReadAllMetadataHandler( + const ReadAllMetadataSignature& handler) { + read_all_metadata_handler_ = handler; +} + +void MockModelTypeStore::RegisterCommitWriteBatchHandler( + const CommitWriteBatchSignature& handler) { + commit_write_batch_handler_ = handler; +} + +void MockModelTypeStore::RegisterWriteDataHandler( + const WriteRecordSignature& handler) { + write_data_handler_ = handler; +} + +void MockModelTypeStore::RegisterWriteMetadataHandler( + const WriteRecordSignature& handler) { + write_metadata_handler_ = handler; +} + +void MockModelTypeStore::RegisterDeleteDataHandler( + const DeleteRecordSignature& handler) { + delete_data_handler_ = handler; +} + +void MockModelTypeStore::RegisterDeleteMetadataHandler( + const DeleteRecordSignature& handler) { + delete_metadata_handler_ = handler; +} + +} // namespace syncer_v2
diff --git a/sync/api/mock_model_type_store.h b/sync/api/mock_model_type_store.h new file mode 100644 index 0000000..123d456e --- /dev/null +++ b/sync/api/mock_model_type_store.h
@@ -0,0 +1,118 @@ +// Copyright 2015 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 SYNC_API_MOCK_MODEL_TYPE_STORE_H_ +#define SYNC_API_MOCK_MODEL_TYPE_STORE_H_ + +#include <string> + +#include "base/callback.h" +#include "sync/api/model_type_store.h" + +namespace syncer_v2 { + +// MockModelTypeStore is implementation of ModelTypeStore that does nothing. +// Use it when testing components that depend on ModelTypeStore. +// +// By default all methods return SUCCESS and empty results. It is possible to +// register custom handlers for certain functions to override behavior. It is +// responsibility of handler to post callback with result. +// Here is an example: +// === +// void OnReadData(const ModelTypeStore::IdList& id_list, +// const ModelTypeStore::ReadRecordsCallback& callback) { +// // Verify id_list here. +// // Prepare fake response. +// scoped_ptr<ModelTypeStore::RecordList> record_list( +// new ModelTypeStore::RecordList); +// record_list->push_back(ModelTypeStore::Record("id1", "value1")); +// base::ThreadTaskRunnerHandle::Get()->PostTask( +// FROM_HERE, base::Bind(callback, Result::SUCCESS, +// base::Passed(record_list))); +// } +// +// MockModelTypeStore mock_model_type_store; +// mock_model_type_store.RegisterReadDataHandler(base::Bind(&OnReadData)); +// ModelTypeStore::IdList id_list; +// id_list.push_back("id1"); +// mock_model_type_store.ReadData(id_list, base::Bind(&ReadDone)); +// === +// TODO(pavel): When in-memory store is available this class should delegate all +// calls to it instead of returning empty successful results. +class MockModelTypeStore : public ModelTypeStore { + public: + // Signatures for all ModelTypeStore virtual functions. + typedef base::Callback<void(const ReadRecordsCallback&)> + ReadAllRecordsSignature; + typedef base::Callback<void(const IdList&, const ReadRecordsCallback&)> + ReadRecordsSignature; + typedef base::Callback<void(const ReadMetadataCallback& callback)> + ReadAllMetadataSignature; + typedef base::Callback<void(scoped_ptr<WriteBatch>, CallbackWithResult)> + CommitWriteBatchSignature; + typedef base::Callback<void(WriteBatch*, + const std::string&, + const std::string&)> WriteRecordSignature; + typedef base::Callback<void(WriteBatch*, const std::string&)> + WriteGlobalMetadataSignature; + typedef base::Callback<void(WriteBatch*, const std::string&)> + DeleteRecordSignature; + typedef base::Callback<void(WriteBatch*)> DeleteGlobalMetadataSignature; + + MockModelTypeStore(); + ~MockModelTypeStore() override; + + // ModelTypeStore implementation. + void ReadData(const IdList& id_list, + const ReadRecordsCallback& callback) override; + void ReadAllData(const ReadRecordsCallback& callback) override; + void ReadAllMetadata(const ReadMetadataCallback& callback) override; + + scoped_ptr<WriteBatch> CreateWriteBatch() override; + void CommitWriteBatch(scoped_ptr<WriteBatch> write_batch, + const CallbackWithResult& callback) override; + + void WriteData(WriteBatch* write_batch, + const std::string& id, + const std::string& value) override; + void WriteMetadata(WriteBatch* write_batch, + const std::string& id, + const std::string& value) override; + void WriteGlobalMetadata(WriteBatch* write_batch, + const std::string& value) override; + void DeleteData(WriteBatch* write_batch, const std::string& id) override; + void DeleteMetadata(WriteBatch* write_batch, const std::string& id) override; + void DeleteGlobalMetadata(WriteBatch* write_batch) override; + + // Register handler functions. + void RegisterReadDataHandler(const ReadRecordsSignature& handler); + void RegisterReadAllDataHandler(const ReadAllRecordsSignature& handler); + void RegisterReadAllMetadataHandler(const ReadAllMetadataSignature& handler); + void RegisterCommitWriteBatchHandler( + const CommitWriteBatchSignature& handler); + void RegisterWriteDataHandler(const WriteRecordSignature& handler); + void RegisterWriteMetadataHandler(const WriteRecordSignature& handler); + void RegisterWriteGlobalMetadataHandler( + const WriteGlobalMetadataSignature& handler); + void RegisterDeleteDataHandler(const DeleteRecordSignature& handler); + void RegisterDeleteMetadataHandler(const DeleteRecordSignature& handler); + void RegisterDeleteGlobalMetadataHandler( + const DeleteGlobalMetadataSignature& handler); + + private: + ReadRecordsSignature read_data_handler_; + ReadAllRecordsSignature read_all_data_handler_; + ReadAllMetadataSignature read_all_metadata_handler_; + CommitWriteBatchSignature commit_write_batch_handler_; + WriteRecordSignature write_data_handler_; + WriteRecordSignature write_metadata_handler_; + WriteGlobalMetadataSignature write_global_metadata_handler_; + DeleteRecordSignature delete_data_handler_; + DeleteRecordSignature delete_metadata_handler_; + DeleteGlobalMetadataSignature delete_global_metadata_handler_; +}; + +} // namespace syncer_v2 + +#endif // SYNC_API_MOCK_MODEL_TYPE_STORE_H_
diff --git a/sync/api/model_type_store.cc b/sync/api/model_type_store.cc index 2555ddc..72af0467 100644 --- a/sync/api/model_type_store.cc +++ b/sync/api/model_type_store.cc
@@ -4,10 +4,19 @@ #include "sync/api/model_type_store.h" +#include "sync/internal_api/public/model_type_store_impl.h" + namespace syncer_v2 { -ModelTypeStore::ModelTypeStore() {} +// static +void ModelTypeStore::CreateInMemoryStoreForTest(const InitCallback& callback) { + ModelTypeStoreImpl::CreateInMemoryStoreForTest(callback); +} ModelTypeStore::~ModelTypeStore() {} -} // namespace sync_v2 +ModelTypeStore::WriteBatch::WriteBatch() {} + +ModelTypeStore::WriteBatch::~WriteBatch() {} + +} // namespace syncer_v2
diff --git a/sync/api/model_type_store.h b/sync/api/model_type_store.h index 817238e..2c0e4d3 100644 --- a/sync/api/model_type_store.h +++ b/sync/api/model_type_store.h
@@ -5,14 +5,124 @@ #ifndef SYNC_API_MODEL_TYPE_STORE_H_ #define SYNC_API_MODEL_TYPE_STORE_H_ +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/macros.h" +#include "sync/base/sync_export.h" + namespace syncer_v2 { -// Interface for store used by ModelTypeProcessor for persisting sync related -// data (entity state and data type state). -class ModelTypeStore { +// ModelTypeStore is leveldb backed store for model type's data, metadata and +// global metadata. +// +// Store keeps records for entries identified by ids. For each entry store keeps +// data and metadata. Also store keeps one record for global metadata. +// +// To create store call one of Create*Store static factory functions. Model type +// controls store's lifetime with returned scoped_ptr. Call to Create*Store +// function triggers asynchronous store backend initialization, callback will be +// called with results when initialization is done. +// +// Read operations are asynchronous, initiated with one of Read* functions, +// provided callback will be called with result code and output of read +// operation. +// +// Write operations are done in context of write batch. To get one call +// CreateWriteBatch(). After that pass write batch object to Write/Delete +// functions. WriteBatch only accumulates pending changes, doesn't actually do +// data modification. Calling CommitWriteBatch writes all accumulated changes to +// disk atomically. Callback passed to CommitWriteBatch will be called with +// result of write operation. If write batch object is destroyed without +// comitting accumulated write operations will not be persisted. +// +// Destroying store object doesn't necessarily cancel asynchronous operations +// issued previously. You should be prepared to handle callbacks from those +// operations. +class SYNC_EXPORT ModelTypeStore { public: - ModelTypeStore(); + // Result of store operations. + enum class Result { + SUCCESS, + UNSPECIFIED_ERROR, + }; + + // Output of read operations is passed back as list of Record structures. + struct Record { + Record(const std::string& id, const std::string& value) + : id(id), value(value) {} + + std::string id; + std::string value; + }; + + // WriteBatch object is used in all modification operations. + class SYNC_EXPORT WriteBatch { + public: + virtual ~WriteBatch(); + + protected: + friend class MockModelTypeStore; + WriteBatch(); + }; + + typedef std::vector<Record> RecordList; + typedef std::vector<std::string> IdList; + + typedef base::Callback<void(Result, scoped_ptr<ModelTypeStore>)> InitCallback; + typedef base::Callback<void(Result)> CallbackWithResult; + typedef base::Callback<void(Result, scoped_ptr<RecordList>)> + ReadRecordsCallback; + typedef base::Callback<void(Result, + scoped_ptr<RecordList>, + const std::string&)> ReadMetadataCallback; + + // Creates store object backed by in-memory leveldb database. It is used in + // tests. + static void CreateInMemoryStoreForTest(const InitCallback& callback); + virtual ~ModelTypeStore(); + + // Read operations return records either for all entries or only for ones + // identified in |id_list|. Result is SUCCESS if all records were read + // successfully. If reading any of records fails result is UNSPECIFIED_ERROR + // and RecordList contains some records that were read successfully. There is + // no guarantee that RecordList will contain all successfully read records in + // this case. + virtual void ReadData(const IdList& id_list, + const ReadRecordsCallback& callback) = 0; + virtual void ReadAllData(const ReadRecordsCallback& callback) = 0; + // ReadMetadataCallback will be invoked with three parameters: result of + // operation, list of metadata records and global metadata. + virtual void ReadAllMetadata(const ReadMetadataCallback& callback) = 0; + + // Creates write batch for write operations. + virtual scoped_ptr<WriteBatch> CreateWriteBatch() = 0; + + // Commits write operations accumulated in write batch. If write operation + // fails result is UNSPECIFIED_ERROR and write operations will not be + // reflected in the store. + virtual void CommitWriteBatch(scoped_ptr<WriteBatch> write_batch, + const CallbackWithResult& callback) = 0; + + // Write operations. + virtual void WriteData(WriteBatch* write_batch, + const std::string& id, + const std::string& value) = 0; + virtual void WriteMetadata(WriteBatch* write_batch, + const std::string& id, + const std::string& value) = 0; + virtual void WriteGlobalMetadata(WriteBatch* write_batch, + const std::string& value) = 0; + virtual void DeleteData(WriteBatch* write_batch, const std::string& id) = 0; + virtual void DeleteMetadata(WriteBatch* write_batch, + const std::string& id) = 0; + virtual void DeleteGlobalMetadata(WriteBatch* write_batch) = 0; + // TODO(pavely): Consider implementing DeleteAllMetadata with following + // signature: + // virtual void DeleteAllMetadata(const CallbackWithResult& callback) = 0. + // It will delete all metadata records and global metadata record. }; } // namespace syncer_v2
diff --git a/sync/internal_api/model_type_store_backend.cc b/sync/internal_api/model_type_store_backend.cc new file mode 100644 index 0000000..dc4cf1f6 --- /dev/null +++ b/sync/internal_api/model_type_store_backend.cc
@@ -0,0 +1,24 @@ +// Copyright 2015 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 "sync/internal_api/public/model_type_store_backend.h" + +namespace syncer_v2 { + +ModelTypeStoreBackend::ModelTypeStoreBackend() { + // ModelTypeStoreBackend is used on different thread from the one where it is + // created. + DetachFromThread(); +} + +ModelTypeStoreBackend::~ModelTypeStoreBackend() { + DCHECK(CalledOnValidThread()); +} + +ModelTypeStore::Result ModelTypeStoreBackend::Init() { + DCHECK(CalledOnValidThread()); + return ModelTypeStore::Result::SUCCESS; +} + +} // namespace syncer_v2
diff --git a/sync/internal_api/model_type_store_impl.cc b/sync/internal_api/model_type_store_impl.cc new file mode 100644 index 0000000..e7fdcf02 --- /dev/null +++ b/sync/internal_api/model_type_store_impl.cc
@@ -0,0 +1,133 @@ +// Copyright 2015 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 "sync/internal_api/public/model_type_store_impl.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/task_runner_util.h" +#include "base/thread_task_runner_handle.h" +#include "sync/internal_api/public/model_type_store_backend.h" + +namespace syncer_v2 { + +namespace { + +void NoOpForBackendDtor(scoped_ptr<ModelTypeStoreBackend> backend) { + // This function was intentionally left blank. +} + +} // namespace + +ModelTypeStoreImpl::ModelTypeStoreImpl( + scoped_ptr<ModelTypeStoreBackend> backend, + scoped_refptr<base::SingleThreadTaskRunner> backend_task_runner) + : backend_(backend.Pass()), backend_task_runner_(backend_task_runner) { + DCHECK(backend_); + DCHECK(backend_task_runner_); +} + +ModelTypeStoreImpl::~ModelTypeStoreImpl() { + DCHECK(CalledOnValidThread()); + backend_task_runner_->PostTask( + FROM_HERE, base::Bind(&NoOpForBackendDtor, base::Passed(&backend_))); +} + +// static +void ModelTypeStoreImpl::CreateInMemoryStoreForTest( + const InitCallback& callback) { + DCHECK(!callback.is_null()); + // In-memory store backend works on the same thread as test. + scoped_refptr<base::SingleThreadTaskRunner> task_runner = + base::ThreadTaskRunnerHandle::Get(); + + scoped_ptr<ModelTypeStoreBackend> backend(new ModelTypeStoreBackend()); + scoped_ptr<ModelTypeStoreImpl> store( + new ModelTypeStoreImpl(backend.Pass(), task_runner)); + auto task = base::Bind(&ModelTypeStoreBackend::Init, + base::Unretained(store->backend_.get())); + auto reply = base::Bind(&ModelTypeStoreImpl::BackendInitDone, callback, + base::Passed(&store)); + + base::PostTaskAndReplyWithResult(task_runner.get(), FROM_HERE, task, reply); +} + +// static +void ModelTypeStoreImpl::BackendInitDone(const InitCallback& callback, + scoped_ptr<ModelTypeStoreImpl> store, + Result result) { + DCHECK(store->CalledOnValidThread()); + if (result != Result::SUCCESS) { + store.reset(); + } + callback.Run(result, store.Pass()); +} + +void ModelTypeStoreImpl::ReadData(const IdList& id_list, + const ReadRecordsCallback& callback) { + DCHECK(CalledOnValidThread()); + NOTIMPLEMENTED(); +} + +void ModelTypeStoreImpl::ReadAllData(const ReadRecordsCallback& callback) { + DCHECK(CalledOnValidThread()); + NOTIMPLEMENTED(); +} + +void ModelTypeStoreImpl::ReadAllMetadata(const ReadMetadataCallback& callback) { + DCHECK(CalledOnValidThread()); + NOTIMPLEMENTED(); +} + +scoped_ptr<ModelTypeStore::WriteBatch> ModelTypeStoreImpl::CreateWriteBatch() { + DCHECK(CalledOnValidThread()); + NOTIMPLEMENTED(); + return make_scoped_ptr(new WriteBatchImpl()); +} + +void ModelTypeStoreImpl::CommitWriteBatch(scoped_ptr<WriteBatch> write_batch, + const CallbackWithResult& callback) { + DCHECK(CalledOnValidThread()); + NOTIMPLEMENTED(); +} + +void ModelTypeStoreImpl::WriteData(WriteBatch* write_batch, + const std::string& id, + const std::string& value) { + DCHECK(CalledOnValidThread()); + NOTIMPLEMENTED(); +} + +void ModelTypeStoreImpl::WriteMetadata(WriteBatch* write_batch, + const std::string& id, + const std::string& value) { + DCHECK(CalledOnValidThread()); + NOTIMPLEMENTED(); +} + +void ModelTypeStoreImpl::WriteGlobalMetadata(WriteBatch* write_batch, + const std::string& value) { + DCHECK(CalledOnValidThread()); + NOTIMPLEMENTED(); +} + +void ModelTypeStoreImpl::DeleteData(WriteBatch* write_batch, + const std::string& id) { + DCHECK(CalledOnValidThread()); + NOTIMPLEMENTED(); +} + +void ModelTypeStoreImpl::DeleteMetadata(WriteBatch* write_batch, + const std::string& id) { + DCHECK(CalledOnValidThread()); + NOTIMPLEMENTED(); +} + +void ModelTypeStoreImpl::DeleteGlobalMetadata(WriteBatch* write_batch) { + DCHECK(CalledOnValidThread()); + NOTIMPLEMENTED(); +} + +} // namespace syncer_v2
diff --git a/sync/internal_api/model_type_store_impl_unittest.cc b/sync/internal_api/model_type_store_impl_unittest.cc new file mode 100644 index 0000000..9bba031 --- /dev/null +++ b/sync/internal_api/model_type_store_impl_unittest.cc
@@ -0,0 +1,51 @@ +// Copyright 2015 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 "sync/internal_api/public/model_type_store_impl.h" + +#include "base/bind.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace syncer_v2 { + +class ModelTypeStoreImplTest : public testing::Test { + public: + void TearDown() override { + if (store_) { + store_.reset(); + PumpLoop(); + } + } + + ModelTypeStore* store() { return store_.get(); } + + void OnInitDone(ModelTypeStore::Result result, + scoped_ptr<ModelTypeStore> store) { + ASSERT_EQ(ModelTypeStore::Result::SUCCESS, result); + store_ = store.Pass(); + } + + void PumpLoop() { + base::RunLoop run_loop; + run_loop.RunUntilIdle(); + } + + private: + base::MessageLoop message_loop_; + scoped_ptr<ModelTypeStore> store_; +}; + +// Test that CreateInMemoryStoreForTest triggers store initialization that +// results with callback being calleds with valid store pointer. +TEST_F(ModelTypeStoreImplTest, CreateInMemoryStore) { + ModelTypeStore::CreateInMemoryStoreForTest( + base::Bind(&ModelTypeStoreImplTest::OnInitDone, base::Unretained(this))); + ASSERT_EQ(nullptr, store()); + PumpLoop(); + ASSERT_NE(nullptr, store()); +} + +} // namespace syncer_v2
diff --git a/sync/internal_api/public/model_type_store_backend.h b/sync/internal_api/public/model_type_store_backend.h new file mode 100644 index 0000000..cdbcd7b --- /dev/null +++ b/sync/internal_api/public/model_type_store_backend.h
@@ -0,0 +1,26 @@ +// Copyright 2015 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 SYNC_INTERNAL_API_PUBLIC_MODEL_TYPE_STORE_BACKEND_H_ +#define SYNC_INTERNAL_API_PUBLIC_MODEL_TYPE_STORE_BACKEND_H_ + +#include "base/threading/non_thread_safe.h" +#include "sync/api/model_type_store.h" + +namespace syncer_v2 { + +// ModelTypeStoreBackend handles operations with leveldb. It is oblivious of the +// fact that it is called from separate thread (with the exception of ctor), +// meaning it shouldn't deal with callbacks and task_runners. +class ModelTypeStoreBackend : public base::NonThreadSafe { + public: + ModelTypeStoreBackend(); + ~ModelTypeStoreBackend(); + + ModelTypeStore::Result Init(); +}; + +} // namespace syncer_v2 + +#endif // SYNC_INTERNAL_API_PUBLIC_MODEL_TYPE_STORE_BACKEND_H_
diff --git a/sync/internal_api/public/model_type_store_impl.h b/sync/internal_api/public/model_type_store_impl.h new file mode 100644 index 0000000..5ee4fab --- /dev/null +++ b/sync/internal_api/public/model_type_store_impl.h
@@ -0,0 +1,71 @@ +// Copyright 2015 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 SYNC_INTERNAL_API_PUBLIC_MODEL_TYPE_STORE_IMPL_H_ +#define SYNC_INTERNAL_API_PUBLIC_MODEL_TYPE_STORE_IMPL_H_ + +#include <string> + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/non_thread_safe.h" +#include "sync/api/model_type_store.h" + +namespace syncer_v2 { + +class ModelTypeStoreBackend; + +// ModelTypeStoreImpl handles details of store initialization, threading and +// leveldb key formatting. Actual leveldb IO calls are performed by +// ModelTypeStoreBackend. +class ModelTypeStoreImpl : public ModelTypeStore, public base::NonThreadSafe { + public: + ~ModelTypeStoreImpl() override; + + static void CreateInMemoryStoreForTest(const InitCallback& callback); + + // ModelTypeStore implementation. + void ReadData(const IdList& id_list, + const ReadRecordsCallback& callback) override; + void ReadAllData(const ReadRecordsCallback& callback) override; + void ReadAllMetadata(const ReadMetadataCallback& callback) override; + scoped_ptr<WriteBatch> CreateWriteBatch() override; + void CommitWriteBatch(scoped_ptr<WriteBatch> write_batch, + const CallbackWithResult& callback) override; + void WriteData(WriteBatch* write_batch, + const std::string& id, + const std::string& value) override; + void WriteMetadata(WriteBatch* write_batch, + const std::string& id, + const std::string& value) override; + void WriteGlobalMetadata(WriteBatch* write_batch, + const std::string& value) override; + void DeleteData(WriteBatch* write_batch, const std::string& id) override; + void DeleteMetadata(WriteBatch* write_batch, const std::string& id) override; + void DeleteGlobalMetadata(WriteBatch* write_batch) override; + + private: + class WriteBatchImpl : public ModelTypeStore::WriteBatch { + public: + }; + + static void BackendInitDone(const InitCallback& callback, + scoped_ptr<ModelTypeStoreImpl> store, + Result result); + + ModelTypeStoreImpl( + scoped_ptr<ModelTypeStoreBackend> backend, + scoped_refptr<base::SingleThreadTaskRunner> backend_task_runner); + + // Backend is owned by store, but should be deleted on backend thread. To + // accomplish this store's dtor posts task to backend thread passing backend + // ownership to task parameter. + scoped_ptr<ModelTypeStoreBackend> backend_; + scoped_refptr<base::SingleThreadTaskRunner> backend_task_runner_; +}; + +} // namespace syncer_v2 + +#endif // SYNC_INTERNAL_API_PUBLIC_MODEL_TYPE_STORE_IMPL_H_
diff --git a/sync/sync.gyp b/sync/sync.gyp index 02e72fb..863347984 100644 --- a/sync/sync.gyp +++ b/sync/sync.gyp
@@ -218,6 +218,8 @@ 'internal_api/js_sync_encryption_handler_observer.h', 'internal_api/js_sync_manager_observer.cc', 'internal_api/js_sync_manager_observer.h', + 'internal_api/model_type_store_backend.cc', + 'internal_api/model_type_store_impl.cc', 'internal_api/protocol_event_buffer.cc', 'internal_api/protocol_event_buffer.h', 'internal_api/public/activation_context.h', @@ -289,6 +291,8 @@ 'internal_api/public/internal_components_factory_impl.h', 'internal_api/public/model_type_processor.cc', 'internal_api/public/model_type_processor.h', + 'internal_api/public/model_type_store_backend.h', + 'internal_api/public/model_type_store_impl.h', 'internal_api/public/network_resources.h', 'internal_api/public/non_blocking_sync_common.cc', 'internal_api/public/non_blocking_sync_common.h',
diff --git a/sync/sync_tests.gypi b/sync/sync_tests.gypi index 6983456..c595fc6 100644 --- a/sync/sync_tests.gypi +++ b/sync/sync_tests.gypi
@@ -224,6 +224,8 @@ 'api/fake_sync_change_processor.h', 'api/fake_syncable_service.cc', 'api/fake_syncable_service.h', + 'api/mock_model_type_store.cc', + 'api/mock_model_type_store.h', 'api/sync_change_processor_wrapper_for_test.cc', 'api/sync_change_processor_wrapper_for_test.h', 'api/sync_error_factory_mock.cc', @@ -297,6 +299,7 @@ 'internal_api/js_mutation_event_observer_unittest.cc', 'internal_api/js_sync_encryption_handler_observer_unittest.cc', 'internal_api/js_sync_manager_observer_unittest.cc', + 'internal_api/model_type_store_impl_unittest.cc', 'internal_api/protocol_event_buffer_unittest.cc', 'internal_api/public/base/attachment_id_proto_unittest.cc', 'internal_api/public/base/cancelation_signal_unittest.cc',
diff --git a/sync/syncable/directory.cc b/sync/syncable/directory.cc index 33cb6d4b..afac3be 100644 --- a/sync/syncable/directory.cc +++ b/sync/syncable/directory.cc
@@ -656,9 +656,16 @@ // Note: do not modify the root node in order to preserve the // initial sync ended bit for this type (else on the next restart // this type will be treated as disabled and therefore fully purged). - if (IsRealDataType(server_type) && - ModelTypeToRootTag(server_type) == entry->ref(UNIQUE_SERVER_TAG)) { - return; + if (entry->ref(PARENT_ID).IsRoot()) { + ModelType root_type = server_type; + // Support both server created and client created type root folders. + if (!IsRealDataType(root_type)) { + root_type = GetModelTypeFromSpecifics(entry->ref(SPECIFICS)); + } + if (IsRealDataType(root_type) && + ModelTypeToRootTag(root_type) == entry->ref(UNIQUE_SERVER_TAG)) { + return; + } } // Set the unapplied bit if this item has server data. @@ -1006,8 +1013,10 @@ // Some tests don't bother creating type root. Need to check if the root // exists before clearing its base version. - if (root.good() && root.GetBaseVersion() == CHANGES_VERSION) { - root.PutBaseVersion(0); + if (root.good()) { + DCHECK(!root.GetIsDel()); + if (root.GetBaseVersion() == CHANGES_VERSION) + root.PutBaseVersion(0); } }
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 5e0ab16..d31cd8f 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -506,6 +506,13 @@ "swarming": { "can_use_on_swarming_builders": true } + }, + { + "isolate_name": "telemetry_perf_unittests", + "name": "telemetry_perf_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } } ], "scripts": [ @@ -514,10 +521,6 @@ "script": "telemetry_unittests.py" }, { - "name": "telemetry_perf_unittests", - "script": "telemetry_perf_unittests.py" - }, - { "name": "nacl_integration", "script": "nacl_integration.py" } @@ -1058,6 +1061,175 @@ } ] }, + "ClangToTLinuxUBSanVptr tester": { + "gtest_tests": [ + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "accessibility_unittests" + }, + { + "test": "angle_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 5 + }, + "test": "browser_tests" + }, + { + "test": "cacheinvalidation_unittests" + }, + { + "test": "cast_unittests" + }, + { + "test": "cc_unittests" + }, + { + "test": "components_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "crypto_unittests" + }, + { + "test": "device_unittests" + }, + { + "test": "display_unittests" + }, + { + "test": "extensions_browsertests" + }, + { + "test": "extensions_unittests" + }, + { + "test": "gcm_unit_tests" + }, + { + "test": "gfx_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "google_apis_unittests" + }, + { + "test": "gpu_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "interactive_ui_tests" + }, + { + "test": "ipc_tests" + }, + { + "test": "jingle_unittests" + }, + { + "test": "media_blink_unittests" + }, + { + "test": "media_unittests" + }, + { + "test": "midi_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 4 + }, + "test": "net_unittests" + }, + { + "test": "ppapi_unittests" + }, + { + "test": "printing_unittests" + }, + { + "test": "remoting_unittests" + }, + { + "test": "sandbox_linux_unittests" + }, + { + "test": "skia_unittests" + }, + { + "test": "sql_unittests" + }, + { + "test": "sync_unit_tests" + }, + { + "test": "ui_base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 2 + }, + "test": "unit_tests" + }, + { + "test": "url_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" + } + ] + }, "ClangToTMac tester": { "gtest_tests": [ { @@ -1261,6 +1433,13 @@ "swarming": { "can_use_on_swarming_builders": true } + }, + { + "isolate_name": "telemetry_perf_unittests", + "name": "telemetry_perf_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } } ], "scripts": [ @@ -1269,10 +1448,6 @@ "script": "telemetry_unittests.py" }, { - "name": "telemetry_perf_unittests", - "script": "telemetry_perf_unittests.py" - }, - { "name": "nacl_integration", "script": "nacl_integration.py" } @@ -1472,6 +1647,13 @@ "swarming": { "can_use_on_swarming_builders": true } + }, + { + "isolate_name": "telemetry_perf_unittests", + "name": "telemetry_perf_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } } ], "scripts": [ @@ -1480,10 +1662,6 @@ "script": "telemetry_unittests.py" }, { - "name": "telemetry_perf_unittests", - "script": "telemetry_perf_unittests.py" - }, - { "name": "nacl_integration", "script": "nacl_integration.py" } @@ -4540,6 +4718,13 @@ "swarming": { "can_use_on_swarming_builders": true } + }, + { + "isolate_name": "telemetry_perf_unittests", + "name": "telemetry_perf_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } } ], "scripts": [ @@ -4548,10 +4733,6 @@ "script": "telemetry_unittests.py" }, { - "name": "telemetry_perf_unittests", - "script": "telemetry_perf_unittests.py" - }, - { "name": "nacl_integration", "script": "nacl_integration.py" } @@ -4735,6 +4916,13 @@ "swarming": { "can_use_on_swarming_builders": true } + }, + { + "isolate_name": "telemetry_perf_unittests", + "name": "telemetry_perf_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } } ], "scripts": [ @@ -4743,10 +4931,6 @@ "script": "telemetry_unittests.py" }, { - "name": "telemetry_perf_unittests", - "script": "telemetry_perf_unittests.py" - }, - { "name": "nacl_integration", "script": "nacl_integration.py" } @@ -5035,6 +5219,13 @@ "swarming": { "can_use_on_swarming_builders": true } + }, + { + "isolate_name": "telemetry_perf_unittests", + "name": "telemetry_perf_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } } ], "scripts": [ @@ -5043,10 +5234,6 @@ "script": "telemetry_unittests.py" }, { - "name": "telemetry_perf_unittests", - "script": "telemetry_perf_unittests.py" - }, - { "name": "nacl_integration", "script": "nacl_integration.py" } @@ -5218,6 +5405,13 @@ "swarming": { "can_use_on_swarming_builders": true } + }, + { + "isolate_name": "telemetry_perf_unittests", + "name": "telemetry_perf_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } } ], "scripts": [ @@ -5226,10 +5420,6 @@ "script": "telemetry_unittests.py" }, { - "name": "telemetry_perf_unittests", - "script": "telemetry_perf_unittests.py" - }, - { "name": "nacl_integration", "script": "nacl_integration.py" }
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index ae22afd..e5499ada 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -111,6 +111,9 @@ "test": "sync_unit_tests" }, { + "test": "ui_android_unittests" + }, + { "test": "ui_base_unittests" }, { @@ -672,7 +675,10 @@ }, { "isolate_name": "telemetry_perf_unittests", - "name": "telemetry_perf_unittests" + "name": "telemetry_perf_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } } ], "scripts": [ @@ -1041,7 +1047,10 @@ }, { "isolate_name": "telemetry_perf_unittests", - "name": "telemetry_perf_unittests" + "name": "telemetry_perf_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } } ], "scripts": [
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index cff05000..f62cc5f 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -314,6 +314,13 @@ "swarming": { "can_use_on_swarming_builders": true } + }, + { + "isolate_name": "telemetry_perf_unittests", + "name": "telemetry_perf_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } } ], "scripts": [ @@ -322,10 +329,6 @@ "script": "telemetry_unittests.py" }, { - "name": "telemetry_perf_unittests", - "script": "telemetry_perf_unittests.py" - }, - { "name": "nacl_integration", "script": "nacl_integration.py" } @@ -600,6 +603,13 @@ "swarming": { "can_use_on_swarming_builders": true } + }, + { + "isolate_name": "telemetry_perf_unittests", + "name": "telemetry_perf_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } } ], "scripts": [ @@ -608,10 +618,6 @@ "script": "telemetry_unittests.py" }, { - "name": "telemetry_perf_unittests", - "script": "telemetry_perf_unittests.py" - }, - { "name": "nacl_integration", "script": "nacl_integration.py" } @@ -886,6 +892,13 @@ "swarming": { "can_use_on_swarming_builders": true } + }, + { + "isolate_name": "telemetry_perf_unittests", + "name": "telemetry_perf_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } } ], "scripts": [ @@ -894,10 +907,6 @@ "script": "telemetry_unittests.py" }, { - "name": "telemetry_perf_unittests", - "script": "telemetry_perf_unittests.py" - }, - { "name": "nacl_integration", "script": "nacl_integration.py" } @@ -1172,6 +1181,13 @@ "swarming": { "can_use_on_swarming_builders": true } + }, + { + "isolate_name": "telemetry_perf_unittests", + "name": "telemetry_perf_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } } ], "scripts": [ @@ -1180,10 +1196,6 @@ "script": "telemetry_unittests.py" }, { - "name": "telemetry_perf_unittests", - "script": "telemetry_perf_unittests.py" - }, - { "name": "nacl_integration", "script": "nacl_integration.py" } @@ -1459,6 +1471,13 @@ "swarming": { "can_use_on_swarming_builders": true } + }, + { + "isolate_name": "telemetry_perf_unittests", + "name": "telemetry_perf_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } } ], "scripts": [ @@ -1467,10 +1486,6 @@ "script": "telemetry_unittests.py" }, { - "name": "telemetry_perf_unittests", - "script": "telemetry_perf_unittests.py" - }, - { "name": "nacl_integration", "script": "nacl_integration.py" }
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index eedcb78b..a87beb9 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -407,6 +407,10 @@ "-v", ], }, + "ui_android_unittests": { + "label": "//ui/android:ui_android_unittests", + "type": "console_test_launcher", + }, "ui_base_unittests": { "label": "//ui/base:ui_base_unittests", "type": "windowed_test_launcher",
diff --git a/testing/libfuzzer/BUILD.gn b/testing/libfuzzer/BUILD.gn index 46fead84..519c4a79 100644 --- a/testing/libfuzzer/BUILD.gn +++ b/testing/libfuzzer/BUILD.gn
@@ -62,39 +62,6 @@ ] } -test("es_parser_adts_fuzzer") { - sources = [ - "es_parser_adts_fuzzer.cc", - ] - deps = [ - ":libfuzzer_main", - "//base", - "//media", - ] -} - -test("es_parser_h264_fuzzer") { - sources = [ - "es_parser_h264_fuzzer.cc", - ] - deps = [ - ":libfuzzer_main", - "//base", - "//media", - ] -} - -test("es_parser_mpeg1audio_fuzzer") { - sources = [ - "es_parser_mpeg1audio_fuzzer.cc", - ] - deps = [ - ":libfuzzer_main", - "//base", - "//media", - ] -} - test("ftp_ctrl_response_fuzzer") { sources = [ "ftp_ctrl_response_fuzzer.cc", @@ -138,6 +105,39 @@ "//media", ] } + + test("es_parser_adts_fuzzer") { + sources = [ + "es_parser_adts_fuzzer.cc", + ] + deps = [ + ":libfuzzer_main", + "//base", + "//media", + ] + } + + test("es_parser_h264_fuzzer") { + sources = [ + "es_parser_h264_fuzzer.cc", + ] + deps = [ + ":libfuzzer_main", + "//base", + "//media", + ] + } + + test("es_parser_mpeg1audio_fuzzer") { + sources = [ + "es_parser_mpeg1audio_fuzzer.cc", + ] + deps = [ + ":libfuzzer_main", + "//base", + "//media", + ] + } } test("snappy_fuzzer") {
diff --git a/third_party/WebKit/LayoutTests/NeverFixTests b/third_party/WebKit/LayoutTests/NeverFixTests index 982b17ac..b0c1514 100644 --- a/third_party/WebKit/LayoutTests/NeverFixTests +++ b/third_party/WebKit/LayoutTests/NeverFixTests
@@ -191,6 +191,11 @@ [ XP ] imported/csswg-test/css-writing-modes-3/text-orientation-script-001m.html [ WontFix ] [ XP ] imported/csswg-test/css-writing-modes-3/text-orientation-script-001n.html [ WontFix ] [ XP ] imported/csswg-test/css-writing-modes-3/text-orientation-script-001o.html [ WontFix ] +[ XP ] imported/csswg-test/css-writing-modes-3/vertical-alignment-vlr-023.xht [ WontFix ] +[ XP ] imported/csswg-test/css-writing-modes-3/vertical-alignment-vlr-025.xht [ WontFix ] +[ XP ] imported/csswg-test/css-writing-modes-3/vertical-alignment-vlr-027.xht [ WontFix ] +[ XP ] imported/csswg-test/css-writing-modes-3/vertical-alignment-vrl-022.xht [ WontFix ] +[ XP ] imported/csswg-test/css-writing-modes-3/vertical-alignment-vrl-024.xht [ WontFix ] [ XP ] imported/csswg-test/css-writing-modes-3/vertical-alignment-vrl-026.xht [ WontFix ] # Relies on precise timing which isn't reliable on XP.
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index b6b7979..ad0472fd 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -57,9 +57,9 @@ crbug.com/539226 [ Win7 ] http/tests/xmlhttprequest/open-in-body-onload-sync-to-invalid-redirect-response-handling.html [ Timeout ] crbug.com/539226 [ Win7 ] http/tests/xmlhttprequest/open-in-body-onload-sync-to-invalid-preflight-handling.html [ Timeout ] -crbug.com/539247 [ Win10 ] http/tests/xmlhttprequest/open-in-body-onload-sync-to-invalid-cross-origin-response-handling.html [ Timeout Failure ] -crbug.com/539247 [ Win10 ] http/tests/xmlhttprequest/open-in-body-onload-sync-to-invalid-redirect-response-handling.html [ Timeout Failure ] -crbug.com/539247 [ Win10 ] http/tests/xmlhttprequest/open-in-body-onload-sync-to-invalid-preflight-handling.html [ Timeout Failure ] +crbug.com/539247 [ Win10 ] http/tests/xmlhttprequest/open-in-body-onload-sync-to-invalid-cross-origin-response-handling.html [ Timeout Pass ] +crbug.com/539247 [ Win10 ] http/tests/xmlhttprequest/open-in-body-onload-sync-to-invalid-redirect-response-handling.html [ Timeout Pass ] +crbug.com/539247 [ Win10 ] http/tests/xmlhttprequest/open-in-body-onload-sync-to-invalid-preflight-handling.html [ Timeout Pass ] crbug.com/417782 [ Linux Win ] virtual/rootlayerscrolls/fast/scrolling/fractional-scroll-offset-fixed-position-non-composited.html [ Failure ] crbug.com/492664 [ Linux XP ] imported/csswg-test/css-writing-modes-3/box-offsets-rel-pos-vlr-005.xht [ Failure ] @@ -82,6 +82,11 @@ crbug.com/267206 [ Mac ] virtual/rootlayerscrolls/fast/scrolling/scrollbar-tickmarks-hittest.html [ Timeout ] +crbug.com/465126 imported/gecko/variables/variable-declaration-24.html [ Failure ] +crbug.com/465126 imported/gecko/variables/variable-declaration-25.html [ Failure ] +crbug.com/465126 imported/gecko/variables/variable-supports-13.html [ Failure ] +crbug.com/465126 imported/gecko/variables/variable-external-font-face-01.html [ Failure ] + crbug.com/280342 [ Linux Win ] http/tests/media/progress-events-generated-correctly.html [ Failure ] crbug.com/520739 [ Mac ] http/tests/websocket/close-code-and-reason.html [ Failure Pass Timeout ] @@ -172,8 +177,7 @@ crbug.com/518995 media/track/media-element-move-to-new-document-assert.html [ Failure Pass ] crbug.com/518998 media/video-poster-after-loadedmetadata.html [ Failure Pass ] -crbug.com/526594 [ Win10 ] plugins/webview-plugin-lifecycle.html [ Failure Pass ] -crbug.com/518999 [ Win7 ] plugins/webview-plugin-lifecycle.html [ Failure Pass ] +crbug.com/526594 [ Win ] plugins/webview-plugin-lifecycle.html [ Failure ] crbug.com/519001 storage/indexeddb/pending-version-change-stuck-works-with-terminate.html [ Pass Timeout ] crbug.com/519002 storage/indexeddb/pending-version-change-stuck.html [ Pass Timeout ] @@ -192,25 +196,12 @@ crbug.com/320139 virtual/syncpaint/fast/repaint/block-layout-inline-children-replaced.html [ Skip ] crbug.com/518929 [ Precise Debug ] http/tests/appcache/obsolete-error-events.html [ Failure Pass Timeout ] crbug.com/518929 [ Precise Debug ] http/tests/appcache/remove-cache.html [ Failure Pass ] -crbug.com/518929 [ Win10 ] http/tests/appcache/remove-cache.html [ Failure Pass ] crbug.com/248938 virtual/threaded/transitions/cancel-and-start-new.html [ Pass Failure ] crbug.com/248938 virtual/threaded/animations/change-keyframes-name.html [ Failure Pass Timeout ] crbug.com/248938 virtual/threaded/animations/change-one-anim.html [ Failure Pass ] crbug.com/326139 crbug.com/390125 media/video-frame-accurate-seek.html [ Failure Pass ] crbug.com/352856 [ Mac ] svg/batik/text/textPosition.svg [ Failure Pass ] crbug.com/352856 [ Mac ] svg/batik/text/textPosition2.svg [ Failure Pass ] -crbug.com/392640 [ Release ] svg/as-object/sizing/svg-in-object-placeholder-auto-auto-intrinsic-ratio.html [ Timeout Pass ] -crbug.com/392640 [ Release ] svg/as-object/sizing/svg-in-object-placeholder-auto-auto-no-intrinsic-ratio.html [ Timeout Pass ] -crbug.com/392640 [ Release ] svg/as-object/sizing/svg-in-object-placeholder-auto-fixed-intrinsic-ratio.html [ Timeout Pass ] -crbug.com/392640 [ Release ] svg/as-object/sizing/svg-in-object-placeholder-auto-fixed-no-intrinsic-ratio.html [ Timeout Pass ] -crbug.com/392640 [ Release ] svg/as-object/sizing/svg-in-object-placeholder-auto-percentage-intrinsic-ratio.html [ Timeout Pass ] -crbug.com/392640 [ Release ] svg/as-object/sizing/svg-in-object-placeholder-auto-percentage-no-intrinsic-ratio.html [ Timeout Pass ] -crbug.com/392640 [ Debug ] svg/as-object/sizing/svg-in-object-placeholder-auto-auto-intrinsic-ratio.html [ Failure Timeout Pass ] -crbug.com/392640 [ Debug ] svg/as-object/sizing/svg-in-object-placeholder-auto-auto-no-intrinsic-ratio.html [ Failure Timeout Pass ] -crbug.com/392640 [ Debug ] svg/as-object/sizing/svg-in-object-placeholder-auto-fixed-intrinsic-ratio.html [ Failure Timeout Pass ] -crbug.com/392640 [ Debug ] svg/as-object/sizing/svg-in-object-placeholder-auto-fixed-no-intrinsic-ratio.html [ Failure Timeout Pass ] -crbug.com/392640 [ Debug ] svg/as-object/sizing/svg-in-object-placeholder-auto-percentage-intrinsic-ratio.html [ Failure Timeout Pass ] -crbug.com/392640 [ Debug ] svg/as-object/sizing/svg-in-object-placeholder-auto-percentage-no-intrinsic-ratio.html [ Failure Timeout Pass ] crbug.com/413604 http/tests/loading/script-priorities.html [ Failure Pass ] crbug.com/479181 inspector-protocol/animation/animation-multiple-frames.html [ Failure Pass ] crbug.com/495523 svg/wicd/test-rightsizing-b.xhtml [ Failure Pass ] @@ -226,24 +217,6 @@ crbug.com/446385 [ Linux Mac ] http/tests/xmlhttprequest/xmlhttprequest-json-response-overflow.html [ Pass Timeout ] crbug.com/446385 [ Win7 Debug ] http/tests/xmlhttprequest/xmlhttprequest-json-response-overflow.html [ Crash Pass Timeout ] crbug.com/441705 fast/media/media-svg-crash.html [ Pass Failure ] -crbug.com/392640 [ Debug ] svg/as-object/sizing/svg-in-object-placeholder-percentage-auto-intrinsic-ratio.html [ Pass Failure Timeout ] -crbug.com/392640 [ Debug ] svg/as-object/sizing/svg-in-object-placeholder-percentage-auto-no-intrinsic-ratio.html [ Pass Failure Timeout ] -crbug.com/392640 [ Debug ] svg/as-object/sizing/svg-in-object-placeholder-percentage-fixed-intrinsic-ratio.html [ Pass Failure Timeout ] -crbug.com/392640 [ Debug ] svg/as-object/sizing/svg-in-object-placeholder-percentage-fixed-no-intrinsic-ratio.html [ Pass Failure Timeout ] -crbug.com/392640 [ Debug ] svg/as-object/sizing/svg-in-object-placeholder-percentage-percentage-intrinsic-ratio.html [ Pass Failure Timeout ] -crbug.com/392640 [ Debug ] svg/as-object/sizing/svg-in-object-placeholder-percentage-percentage-no-intrinsic-ratio.html [ Pass Failure Timeout ] -crbug.com/392640 [ Release ] svg/as-object/sizing/svg-in-object-placeholder-percentage-auto-intrinsic-ratio.html [ Pass Timeout ] -crbug.com/392640 [ Release ] svg/as-object/sizing/svg-in-object-placeholder-percentage-auto-no-intrinsic-ratio.html [ Pass Timeout ] -crbug.com/392640 [ Release ] svg/as-object/sizing/svg-in-object-placeholder-percentage-fixed-intrinsic-ratio.html [ Pass Timeout ] -crbug.com/392640 [ Release ] svg/as-object/sizing/svg-in-object-placeholder-percentage-fixed-no-intrinsic-ratio.html [ Pass Timeout ] -crbug.com/392640 [ Release ] svg/as-object/sizing/svg-in-object-placeholder-percentage-percentage-intrinsic-ratio.html [ Pass Timeout ] -crbug.com/392640 [ Release ] svg/as-object/sizing/svg-in-object-placeholder-percentage-percentage-no-intrinsic-ratio.html [ Pass Timeout ] -crbug.com/392640 svg/as-object/sizing/svg-in-object-placeholder-fixed-auto-intrinsic-ratio.html [ Pass Failure Timeout ] -crbug.com/392640 svg/as-object/sizing/svg-in-object-placeholder-fixed-auto-no-intrinsic-ratio.html [ Pass Failure Timeout ] -crbug.com/392640 svg/as-object/sizing/svg-in-object-placeholder-fixed-fixed-intrinsic-ratio.html [ Pass Failure Timeout ] -crbug.com/392640 svg/as-object/sizing/svg-in-object-placeholder-fixed-fixed-no-intrinsic-ratio.html [ Pass Failure Timeout ] -crbug.com/392640 svg/as-object/sizing/svg-in-object-placeholder-fixed-percentage-intrinsic-ratio.html [ Pass Failure Timeout ] -crbug.com/392640 svg/as-object/sizing/svg-in-object-placeholder-fixed-percentage-no-intrinsic-ratio.html [ Pass Failure Timeout ] crbug.com/248938 virtual/threaded/transitions/interrupt-transform-transition.html [ Pass Failure ] crbug.com/248938 virtual/threaded/animations/dynamic-stylesheet-loading.html [ Pass Failure Timeout ] crbug.com/248938 virtual/threaded/transitions/change-duration-during-transition.html [ Pass Failure ] @@ -533,7 +506,7 @@ crbug.com/505364 imported/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-interface-type-is-a-type-extension.html [ Failure ] -crbug.com/517836 [ Android XP Win7 Mac Linux ] imported/web-platform-tests/screen-orientation/lock-bad-argument.html [ Failure ] +crbug.com/517836 imported/web-platform-tests/screen-orientation/lock-bad-argument.html [ Failure ] crbug.com/517836 imported/web-platform-tests/screen-orientation/orientation-reading.html [ Failure ] crbug.com/517836 imported/web-platform-tests/screen-orientation/onchange-event-subframe.html [ Failure Timeout ] crbug.com/517836 imported/web-platform-tests/screen-orientation/onchange-event.html [ Failure Timeout ] @@ -758,8 +731,6 @@ crbug.com/492664 [ Mac ] imported/csswg-test/css-writing-modes-3/row-progression-009.xht [ Failure ] crbug.com/492664 [ Mac ] imported/csswg-test/css-writing-modes-3/text-baseline-006.xht [ Failure ] crbug.com/492664 [ Mac ] imported/csswg-test/css-writing-modes-3/text-baseline-007.xht [ Failure ] -crbug.com/539425 [ XP ] imported/csswg-test/css-writing-modes-3/vertical-alignment-vrl-022.xht [ Failure ] -crbug.com/539425 [ XP ] imported/csswg-test/css-writing-modes-3/vertical-alignment-vrl-024.xht [ Failure ] crbug.com/498845 [ Win ] fast/multicol/vertical-rl/float-content-break.html [ Failure ] @@ -788,7 +759,7 @@ crbug.com/397232 [ XP ] css2.1/20110323/c541-word-sp-000.htm [ Failure ] crbug.com/397232 [ XP ] css2.1/20110323/vertical-align-boxes-001.htm [ Failure ] crbug.com/397255 [ Linux XP ] css3/masking/clip-path-reference-userSpaceOnUse.html [ Failure ] -crbug.com/475882 [ Mac Win7 ] fast/writing-mode/table-vertical-child-width.html [ Failure ] +crbug.com/475882 [ Mac Win ] fast/writing-mode/table-vertical-child-width.html [ Failure ] crbug.com/396940 ietestcenter/css3/multicolumn/column-containing-block-001.htm [ Failure ] crbug.com/396940 ietestcenter/css3/multicolumn/column-containing-block-002.htm [ Failure ] crbug.com/396941 ietestcenter/css3/multicolumn/column-width-applies-to-007.htm [ Failure ] @@ -796,12 +767,12 @@ crbug.com/396941 ietestcenter/css3/multicolumn/column-width-applies-to-010.htm [ Failure ] crbug.com/396941 ietestcenter/css3/multicolumn/column-width-applies-to-012.htm [ Failure ] crbug.com/396941 ietestcenter/css3/multicolumn/column-width-applies-to-015.htm [ Failure ] -crbug.com/378610 [ Win7 ] svg/custom/focus-ring-text.svg [ Failure ] +crbug.com/378610 svg/custom/focus-ring-text.svg [ Failure ] crbug.com/515454 [ Mac Win7 Win10 Android Linux ] css3/fonts/font-style-matching.html [ Slow ] crbug.com/523021 [ XP ] css3/fonts/font-style-matching.html [ Failure Slow ] -crbug.com/474987 [ Win7 Mac ] css3/flexbox/auto-margins.html [ Failure ] +crbug.com/474987 [ Win Mac ] css3/flexbox/auto-margins.html [ Failure ] crbug.com/267206 [ Mac ] fast/scrolling/scrollbar-tickmarks-hittest.html [ Timeout ] crbug.com/267206 [ Mac ] virtual/scroll_customization/fast/scrolling/scrollbar-tickmarks-hittest.html [ Timeout ] @@ -895,8 +866,6 @@ crbug.com/418091 [ SnowLeopard ] fast/text/international/zerowidthjoiner.html [ Failure ] -crbug.com/507351 [ Mac ] fast/text/international/kana-voiced-sound-marks.html [ Failure ] - crbug.com/425345 [ Mac ] fast/text/line-break-after-question-mark.html [ Failure ] # When drawing subpixel smoothed glyphs, CoreGraphics will fake bold the glyphs. @@ -921,8 +890,6 @@ crbug.com/364225 virtual/gpu/fast/canvas/canvas-composite-text-alpha.html [ Pass Slow Timeout ] crbug.com/440452 virtual/display_list_2d_canvas/fast/canvas/canvas-partial-invalidation-zoomed.html [ Pass Slow Timeout ] -#crbug.com/440452 [ Win10 ] virtual/display_list_2d_canvas/fast/canvas/alpha.html [ Pass Slow Timeout ] -#crbug.com/440452 [ Win10 ] virtual/display_list_2d_canvas/fast/canvas/arc360.html [ Pass Slow Timeout ] crbug.com/364614 [ Mac ] fast/scroll-behavior/overflow-scroll-animates.html [ Skip ] crbug.com/364614 [ Mac ] virtual/threaded/fast/scroll-behavior/overflow-scroll-animates.html [ Skip ] @@ -1134,364 +1101,201 @@ crbug.com/507590 fast/block/float/containing-block-change-compositing.html [ Failure ] -# Win10 specific failures that still need triaging. -crbug.com/521730 [ Win10 ] fast/text/shaping/same-script-different-lang.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/dom/Window/property-access-on-cached-properties-after-frame-navigated.html [ Failure ] -crbug.com/521730 [ Win10 ] fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced.html [ Failure ] -crbug.com/521730 [ Win10 ] fast/dom/Window/property-access-on-cached-properties-after-frame-removed.html [ Failure ] -crbug.com/521730 [ Win10 Release ] fast/dom/Window/property-access-on-cached-window-after-frame-navigated.html [ Failure ] -crbug.com/521730 [ Win10 ] fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced.html [ Failure ] -crbug.com/521730 [ Win10 ] fast/dom/Window/property-access-on-cached-window-after-frame-removed.html [ Failure ] -crbug.com/521730 [ Win10 ] fast/dom/Window/window-appendages-cleared.html [ Failure ] +crbug.com/521730 [ Win10 ] compositing/plugins/invalidate_rect.html [ Crash ] +crbug.com/521730 [ Win10 ] plugins/mouse-click-plugin-clears-selection.html [ Crash ] +crbug.com/521730 [ Win10 ] plugins/windowless_plugin_paint_test.html [ Crash ] + +crbug.com/521730 [ Win10 ] fast/text/shaping/same-script-different-lang.html [ Failure ] crbug.com/521730 [ Win10 ] fast/forms/month-multiple-fields/month-multiple-fields-preserve-value-after-history-back.html [ Failure ] crbug.com/521730 [ Win10 ] fast/forms/month-multiple-fields/month-multiple-fields-value-set-empty.html [ Failure ] crbug.com/521730 [ Win10 ] fast/forms/suggested-value.html [ Failure ] crbug.com/521730 [ Win10 ] fast/forms/text-control-intrinsic-widths.html [ Failure ] crbug.com/521730 [ Win10 ] fast/forms/time-multiple-fields/time-multiple-fields-localization.html [ Failure ] crbug.com/521730 [ Win10 ] fast/text/international/vertical-text-metrics-test.html [ Failure ] -crbug.com/521730 [ Win10 ] http/tests/inspector/search/sources-search-scope-in-files.html [ Failure ] -crbug.com/521730 [ Win10 ] imported/web-platform-tests/screen-orientation/lock-basic.html [ Failure ] -crbug.com/521730 [ Win10 ] imported/web-platform-tests/screen-orientation/orientation-api.html [ Failure ] -crbug.com/521730 [ Win10 ] inspector/screen-orientation-override.html [ Failure ] -crbug.com/521730 [ Win10 ] screen_orientation/lockOrientation-basic.html [ Failure ] -crbug.com/521730 [ Win10 ] screen_orientation/orientation-reading.html [ Failure ] -crbug.com/521730 [ Win10 ] screen_orientation/screenorientation-api.html [ Failure ] -crbug.com/521730 [ Win10 Release ] screen_orientation/screenorientation-detached-notify-no-crash.html [ Failure ] crbug.com/521730 [ Win10 ] svg/custom/svg-fonts-in-text-controls.html [ Failure ] -crbug.com/521730 [ Win10 ] virtual/prefer_compositing_to_lcd_text/compositing/overflow/do-not-repaint-if-scrolling-composited-layers.html [ Failure ] -crbug.com/521730 [ Win10 ] virtual/stable/webexposed/global-interface-listing.html [ Failure ] -#crbug.com/521730 [ Win10 ] webexposed/global-interface-listing.html [ Failure ] -crbug.com/521730 [ Win10 ] css3/flexbox/auto-margins.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/forms/datetimelocal/datetimelocal-appearance-l10n.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/forms/month/month-appearance-basic.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/forms/select/popup-menu-appearance-styled.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text-autosizing/hackernews-comments.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text-autosizing/list-item-above-dbcat.html [ Failure Timeout ] +crbug.com/521730 [ Win10 ] fast/forms/datetimelocal/datetimelocal-appearance-l10n.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/forms/month/month-appearance-basic.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/forms/select/popup-menu-appearance-styled.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text-autosizing/hackernews-comments.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text-autosizing/list-item-above-dbcat.html [ Failure ] crbug.com/521730 [ Win10 ] fast/text-autosizing/supercluster-multiple-layout.html [ Timeout Failure ] -crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/fixed-table-single-cell-lots-of-text.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/nested-tables.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/single-percent-width-cell-lots-of-text.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/table-cell-inflation.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/table-for-layout.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/table-with-inline-block.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/wide-percentage-width.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/wide-specified-width.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] virtual/threaded/inspector/tracing/timeline-event-dispatch.html [ Failure ] -crbug.com/521730 [ Win10 ] fast/text/atsui-kerning-and-ligatures.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/atsui-multiple-renderers.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/atsui-spacing-features.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/basic/009.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/basic/generic-family-changes.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/capitalize-boundaries.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/drawBidiText.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/emoji-web-font.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/firstline/001.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/firstline/002.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/firstline/003.html [ Failure Timeout ] +crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/fixed-table-single-cell-lots-of-text.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/nested-tables.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/single-percent-width-cell-lots-of-text.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/table-cell-inflation.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/table-for-layout.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/table-with-inline-block.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/wide-percentage-width.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/wide-specified-width.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/atsui-kerning-and-ligatures.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/atsui-multiple-renderers.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/atsui-spacing-features.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/basic/009.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/basic/generic-family-changes.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/capitalize-boundaries.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/drawBidiText.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/emoji-web-font.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/firstline/001.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/firstline/002.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/firstline/003.html [ Failure ] crbug.com/521730 [ Win10 ] fast/text/font-stretch.html [ Timeout Failure ] -crbug.com/521730 [ Win10 ] fast/text/format-control.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/international/alef-connected.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/international/bidi-linebreak-001.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/international/bidi-linebreak-003.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/international/bidi-word-spacing-rtl.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/international/inline-block-with-mixed-direction-words.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/international/kana-voiced-sound-marks.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/international/mixed-directionality-selection.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/international/plane2.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/letter-spacing-negative-opacity.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/line-breaks-after-white-space.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/line-breaks.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/shadow-no-blur.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/stroking-decorations.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/trailing-white-space-2.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/whitespace/nbsp-mode-and-linewraps.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/writing-mode/table-vertical-child-width.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/writing-mode/vertical-font-fallback.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-dirLTR-ubNone.svg [ Failure Timeout ] -crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-dirLTR-ubOverride.svg [ Failure Timeout ] -crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirLTR-ubOverride-in-ltr-context.svg [ Failure Timeout ] +crbug.com/521730 [ Win10 ] fast/text/format-control.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/alef-connected.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/bidi-linebreak-001.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/bidi-linebreak-003.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/bidi-word-spacing-rtl.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/inline-block-with-mixed-direction-words.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/mixed-directionality-selection.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/plane2.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/letter-spacing-negative-opacity.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/line-breaks-after-white-space.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/line-breaks.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/shadow-no-blur.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/stroking-decorations.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/trailing-white-space-2.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/whitespace/nbsp-mode-and-linewraps.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/writing-mode/vertical-font-fallback.html [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-dirLTR-ubNone.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-dirLTR-ubOverride.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirLTR-ubOverride-in-ltr-context.svg [ Failure ] crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirRTL-ubEmbed-in-default-context.svg [ Failure ] -crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirRTL-ubNone-in-ltr-context.svg [ Failure Timeout ] -crbug.com/521730 [ Win10 ] svg/W3C-SVG-1.1/text-intro-03-b.svg [ Failure Timeout ] -crbug.com/521730 [ Win10 ] svg/carto.net/combobox.svg [ Failure Timeout ] -crbug.com/521730 [ Win10 ] svg/css/text-gradient-shadow.svg [ Failure Timeout ] -crbug.com/521730 [ Win10 ] compositing/plugins/invalidate_rect.html [ Crash ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirRTL-ubNone-in-ltr-context.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-SVG-1.1/text-intro-03-b.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/carto.net/combobox.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/css/text-gradient-shadow.svg [ Failure ] crbug.com/521730 [ Win10 ] compositing/squashing/squashing-print.html [ Failure ] -crbug.com/521730 [ Win10 ] fast/replaced/no-focus-ring-embed.html [ Crash ] -crbug.com/521730 [ Win10 ] fast/replaced/no-focus-ring-object.html [ Crash ] -crbug.com/521730 [ Win10 ] plugins/focus.html [ Crash ] -crbug.com/521730 [ Win10 ] plugins/keyboard-events.html [ Crash ] -crbug.com/521730 [ Win10 ] plugins/mouse-click-plugin-clears-selection.html [ Crash ] -crbug.com/521730 [ Win10 ] plugins/mouse-events-fixedpos.html [ Crash ] -crbug.com/521730 [ Win10 ] plugins/mouse-events.html [ Crash ] -crbug.com/521730 [ Win10 ] plugins/plugin-initiate-popup-window.html [ Crash ] -crbug.com/521730 [ Win10 ] plugins/tabindex.html [ Crash ] -crbug.com/521730 [ Win10 ] plugins/windowless_plugin_paint_test.html [ Crash ] crbug.com/521730 [ Win10 ] printing/iframe-print.html [ Failure ] -crbug.com/548883 [ Win10 ] printing/quirks-percentage-height-body.html [ Failure ] -crbug.com/548883 [ Win10 ] printing/quirks-percentage-height.html [ Failure ] +crbug.com/521730 [ Win10 ] printing/quirks-percentage-height-body.html [ Failure ] +crbug.com/521730 [ Win10 ] printing/quirks-percentage-height.html [ Failure ] crbug.com/521730 [ Win10 ] printing/simultaneous-position-float-change.html [ Failure ] -crbug.com/548883 [ Win10 ] printing/standards-percentage-heights.html [ Failure ] -crbug.com/548883 [ Win10 ] printing/subframes-percentage-height.html [ Failure ] +crbug.com/521730 [ Win10 ] printing/standards-percentage-heights.html [ Failure ] +crbug.com/521730 [ Win10 ] printing/subframes-percentage-height.html [ Failure ] crbug.com/521730 [ Win10 ] printing/webgl-repeated-printing-preservedrawingbuffer.html [ Failure ] crbug.com/521730 [ Win10 ] virtual/threaded/printing/iframe-print.html [ Failure ] -crbug.com/548883 [ Win10 ] virtual/threaded/printing/quirks-percentage-height-body.html [ Failure ] -crbug.com/548883 [ Win10 ] virtual/threaded/printing/quirks-percentage-height.html [ Failure ] +crbug.com/521730 [ Win10 ] virtual/threaded/printing/quirks-percentage-height-body.html [ Failure ] +crbug.com/521730 [ Win10 ] virtual/threaded/printing/quirks-percentage-height.html [ Failure ] crbug.com/521730 [ Win10 ] virtual/threaded/printing/simultaneous-position-float-change.html [ Failure ] -crbug.com/548883 [ Win10 ] virtual/threaded/printing/standards-percentage-heights.html [ Failure ] -crbug.com/548883 [ Win10 ] virtual/threaded/printing/subframes-percentage-height.html [ Failure ] +crbug.com/521730 [ Win10 ] virtual/threaded/printing/standards-percentage-heights.html [ Failure ] +crbug.com/521730 [ Win10 ] virtual/threaded/printing/subframes-percentage-height.html [ Failure ] crbug.com/521730 [ Win10 ] virtual/threaded/printing/webgl-repeated-printing-preservedrawingbuffer.html [ Failure ] -#crbug.com/521730 [ Win10 ] imported/web-platform-tests/screen-orientation/lock-bad-argument.html [ Timeout ] -crbug.com/521730 [ Win10 ] imported/web-platform-tests/screen-orientation/lock-sandboxed-iframe.html [ Timeout ] -crbug.com/521730 [ Win10 ] screen_orientation/lockOrientation-bad-argument.html [ Timeout ] -crbug.com/521730 [ Win10 ] screen_orientation/lockOrientation-sandboxed-iframe.html [ Timeout ] -crbug.com/521730 [ Win10 ] screen_orientation/orientationchange-event-subframe.html [ Timeout ] -crbug.com/521730 [ Win10 ] screen_orientation/orientationchange-event.html [ Timeout ] -crbug.com/521730 [ Win10 ] screen_orientation/page-visibility.html [ Timeout ] -crbug.com/521730 [ Win10 ] fast/dynamic/text-combine.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/ruby/base-shorter-than-text.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/emphasis-combined-text.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/emphasis-complex.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/font-weight-variant.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/international/003.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/international/bold-bengali.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/international/complex-character-based-fallback.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/international/hindi-spacing.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/international/hindi-whitespace.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/text/justify-ideograph-leading-expansion.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/writing-mode/Kusa-Makura-background-canvas.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/writing-mode/border-vertical-lr.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] fast/writing-mode/japanese-ruby-vertical-lr.html [ Failure Timeout ] +crbug.com/521730 [ Win10 ] fast/dynamic/text-combine.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/ruby/base-shorter-than-text.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/emphasis-combined-text.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/emphasis-complex.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/font-weight-variant.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/003.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/bold-bengali.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/complex-character-based-fallback.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/hindi-spacing.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/hindi-whitespace.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/justify-ideograph-leading-expansion.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/writing-mode/Kusa-Makura-background-canvas.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/writing-mode/border-vertical-lr.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/writing-mode/japanese-ruby-vertical-lr.html [ Failure ] crbug.com/521730 [ Win10 ] media/track/track-cue-rendering-vertical.html [ Failure ] crbug.com/521730 [ Win10 ] svg/W3C-SVG-1.1-SE/text-intro-05-t.svg [ Failure ] -crbug.com/521730 [ Win10 ] svg/W3C-SVG-1.1/text-align-08-b.svg [ Failure Timeout ] -crbug.com/521730 [ Win10 ] virtual/display_list_2d_canvas/fast/canvas/canvas-lose-restore-max-int-size.html [ Failure ] -crbug.com/521730 [ Win10 ] virtual/trustedeventsdefaultaction/fast/events/drag-svg-image-crash.html [ Timeout ] -crbug.com/521730 [ Win10 ] webexposed/global-interface-listing.html [ Failure ] -crbug.com/521730 [ Win10 ] virtual/display_list_2d_canvas/fast/canvas/canvas-lose-restore-googol-size.html [ Failure ] -crbug.com/521730 [ Win10 ] virtual/gpu/fast/canvas/canvas-lose-restore-googol-size.html [ Failure ] -crbug.com/521730 [ Win10 ] virtual/gpu/fast/canvas/canvas-lose-restore-max-int-size.html [ Failure ] -crbug.com/521730 [ Win10 ] virtual/gpu/fast/canvas/canvas-lost-gpu-context.html [ Failure ] -crbug.com/521730 [ Win10 ] virtual/trustedeventsdefaultaction/fast/events/message-port-multi.html [ Failure ] -crbug.com/521730 [ Win10 ] css3/filters/direct-image-dynamic-filter.html [ Pass Timeout ] -crbug.com/521730 [ Win10 ] fast/canvas/toBlob/canvas-toBlob-defaultpng.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] fast/css-generated-content/first-letter-in-nested-before.html [ Failure Pass Timeout ] -crbug.com/521730 [ Win10 ] fast/css/font-face-unicode-range-overlap-load.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] fast/css/fontface-arraybuffer.html [ Pass Timeout ] -crbug.com/521730 [ Win10 ] fast/css/fontfaceset-events.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] fast/dom/StyleSheet/detached-style-pi-2.xhtml [ Failure Pass ] -crbug.com/521730 [ Win10 ] fast/dom/Window/post-message-detach-in-handler.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] fast/dom/custom/crash-without-dom-wrapper.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] fast/forms/autofocus-input-css-style-change.html [ Pass Timeout ] -crbug.com/521730 [ Win10 ] fast/forms/time-multiple-fields/time-multiple-fields-keyboard-events.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] fast/history/scroll-restoration/scroll-restoration-scale-not-impacted.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] fast/preloader/first-base-tag-wins.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] fast/preloader/noscript.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] fast/preloader/script.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] fast/repaint/stacking-context-lost.html [ Pass Timeout ] -crbug.com/521730 [ Win10 ] virtual/syncpaint/fast/repaint/stacking-context-lost.html [ Skip ] -crbug.com/521730 [ Win10 ] fast/scroll-behavior/overflow-scroll-animates.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] fast/table/cell-change-baseline-then-border.html [ Pass Timeout ] -crbug.com/521730 [ Win10 ] http/tests/history/back-to-post.html [ Failure Pass Timeout ] -crbug.com/521730 [ Win10 ] http/tests/navigation/location-reload-after-post.php [ Failure Pass ] -crbug.com/521730 [ Win10 ] http/tests/security/XFrameOptions/x-frame-options-allowall.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-in-body.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] http/tests/security/XFrameOptions/x-frame-options-deny.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] http/tests/security/XFrameOptions/x-frame-options-invalid.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] http/tests/security/XFrameOptions/x-frame-options-multiple-headers-sameorigin-allow.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] http/tests/security/mixedContent/insecure-srcset-in-main-frame-blocked.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] inspector/console/console-format-collections.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] inspector/console/console-log-short-hand-method.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] inspector/file-reader-with-network-panel.html [ Failure Pass ] -crbug.com/521730 [ Win10 ] inspector/sources/debugger-step/debugger-step-out-document-write.html [ Pass Timeout ] -crbug.com/521730 [ Win10 ] media/W3C/audio/error/error_onerror_called_on_bogus_source.html [ Pass Timeout ] -crbug.com/521730 [ Win10 ] paint/inline/outline-offset.html [ Failure Timeout ] -crbug.com/521730 [ Win10 ] virtual/syncpaint/paint/inline/outline-offset.html [ Skip ] -crbug.com/521730 [ Win10 ] svg/as-image/svg-object-intrinsic-size.html [ Missing Timeout ] -#crbug.com/521730 [ Win10 ] svg/as-object/nested-embedded-svg-size-changes.html [ Pass Timeout ] -crbug.com/521730 [ Win10 ] svg/custom/rounded-rect-update-to-empty.html [ Pass Timeout ] -# TODO(wangxianzhu): Restore this after manual rebaseline. -# crbug.com/521730 [ Win10 ] transforms/2d/transform-borderbox.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] virtual/gpu/fast/canvas/canvas-composite-transformclip.html [ Timeout ] -crbug.com/521764 [ Win10 ] imported/web-platform-tests/screen-orientation/lock-bad-argument.html [ Timeout Failure ] -crbug.com/521764 [ Win10 ] accessibility/is-richly-editable.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] accessibility/menu-list-selection-changed.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] animations/interpolation/scale-interpolation.html [ Crash Pass Timeout ] -crbug.com/521764 [ Win10 ] animations/interpolation/translate-interpolation.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] compositing/images/direct-image-dynamic-border-radius.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] compositing/overflow/do-not-crash-use-after-free-update-widget-positions.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/canvas/canvas-lose-restore-googol-size.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/canvas/canvas-lose-restore-max-int-size.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/canvas/webgl/texture-color-profile.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/css/line-height-determined-by-primary-font.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/dom/HTMLImageElement/image-srcset-in-iframe-external.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] fast/dom/HTMLLinkElement/subresource.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/dom/shadow/event-path-load.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] fast/dom/shadow/focus-shadowhost-display-none.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/dom/shadow/iframe-shadow.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/dom/wrapper-classes.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/events/touch/gesture/pad-gesture-cancel.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/forms/month/month-appearance-l10n.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/forms/month/month-appearance-pseudo-elements.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/forms/search/search-appearance-basic.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/html/imports/rel-style-to-import.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] fast/inline/justify-emphasis-inline-box.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/loader/scroll-restore-overrides-fragment.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/loader/scroll-restore-target-pseudo.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/preloader/input.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/preloader/link.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/preloader/scan-body-from-head-script.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/preloader/understands-base-tag.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/repaint/fixed-element-repaint-after-compositing-update.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] virtual/syncpaint/fast/repaint/fixed-element-repaint-after-compositing-update.html [ Skip ] -crbug.com/521764 [ Win10 ] fast/ruby/nested-ruby.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text-autosizing/cluster-inline-block-or-table.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] fast/text-autosizing/cluster-inline-grid-flex-box.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] fast/text-autosizing/display-type-change.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text-autosizing/pseudo-scale-factor.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] fast/text-autosizing/tables/css-table-single-cell-lots-of-text.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text-autosizing/tables/nested-table-wrapping.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text-autosizing/tables/single-cell-lots-of-text.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/atsui-negative-spacing-features.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/basic/011.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/basic/013.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/basic/generic-family-reset.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/cg-fallback-bolding.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/cg-vs-atsui.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/decorations-with-text-combine.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/emoticons.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/emphasis-ellipsis-complextext.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/font-ascent-mac.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/font-stretch-variant.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/font-weight.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/international/002.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/international/bidi-linebreak-002.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/international/danda-space.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/international/hebrew-vowels.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/international/khmer-selection.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/international/lang-glyph-cache-separation.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/international/pop-up-button-text-alignment-and-direction.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/international/rtl-white-space-pre-wrap.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/international/text-spliced-font.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/international/wrap-CJK-001.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/midword-break-hang.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/selection-multiple-runs.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/stroking.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/sub-pixel/text-scaling-pixel.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/trailing-white-space.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/text/wide-zero-width-space.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/tokenizer/001.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] fast/writing-mode/fallback-orientation.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/writing-mode/japanese-lr-text.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/writing-mode/japanese-rl-text.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/writing-mode/japanese-ruby-vertical-rl.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/writing-mode/vertical-align-table-baseline.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fast/writing-mode/vertical-baseline-alignment.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] fonts/fantasy.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] http/tests/inspector/network/network-xhr-redirect-method.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] http/tests/inspector/resource-tree/resource-tree-document-url.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] http/tests/security/XFrameOptions/x-frame-options-multiple-headers-sameorigin-deny.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] http/tests/security/XFrameOptions/x-frame-options-parent-same-origin-allow.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] http/tests/security/XFrameOptions/x-frame-options-parent-same-origin-deny.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] http/tests/security/suborigins/suborigin-valid-names.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] http/tests/xmlhttprequest/xmlhttprequest-post-crash.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] ietestcenter/css3/text/textshadow-002.htm [ Failure Timeout ] -crbug.com/521764 [ Win10 ] ietestcenter/css3/text/textshadow-010.htm [ Failure Timeout ] -crbug.com/521764 [ Win10 ] inspector/console/console-format-table.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] inspector/editor/text-editor-search-switch-editor.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] inspector/elements/styles-4/styles-should-not-force-sync-style-recalc.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] inspector/sources/debugger/debug-inlined-scripts.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] inspector/tracing/timeline-script-tag-2.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] media/track/track-active-cues.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] media/track/track-kind.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] media/track/track-selection-metadata.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] media/video-seek-past-end-paused.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] media/video-source-error.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] printing/webgl-repeated-printing.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] virtual/threaded/printing/webgl-repeated-printing.html [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/g-dirLTR-ubNone.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/g-dirLTR-ubOverride.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/g-dirRTL-ubNone.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/g-dirRTL-ubOverride.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-anchor-dirLTR-anchorEnd.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-anchor-dirLTR-anchorMiddle.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-anchor-dirLTR-anchorStart.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-anchor-dirNone-anchorEnd.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-anchor-dirNone-anchorMiddle.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-anchor-dirNone-anchorStart.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-anchor-dirRTL-anchorEnd.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-anchor-dirRTL-anchorMiddle.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-anchor-dirRTL-anchorStart.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorEnd.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorMiddle.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorStart.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorEnd.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorMiddle.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorStart.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-anchor-no-markup.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-dirRTL-ubNone.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/text-dirRTL-ubOverride.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/tspan-dirLTR-ubEmbed-in-rtl-context.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/tspan-dirLTR-ubNone-in-rtl-context.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/tspan-dirLTR-ubOverride-in-default-context.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/tspan-dirLTR-ubOverride-in-rtl-context.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/tspan-dirNone-ubOverride-in-default-context.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/tspan-dirNone-ubOverride-in-ltr-context.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/tspan-dirNone-ubOverride-in-rtl-context.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/tspan-dirRTL-ubEmbed-in-ltr-context.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/tspan-dirRTL-ubNone-in-default-context.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/tspan-dirRTL-ubOverride-in-default-context.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/tspan-dirRTL-ubOverride-in-ltr-context.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/tspan-dirRTL-ubOverride-in-rtl-context.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/tspan-direction-ltr.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-I18N/tspan-direction-rtl.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-SVG-1.1/text-fonts-01-t.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-SVG-1.1/text-intro-01-t.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/W3C-SVG-1.1/text-intro-04-t.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/as-image/svg-canvas-xhtml-tainted.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] svg/css/text-shadow-multiple.xhtml [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/custom/focus-ring-text.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/custom/textPath-change-id2-pattern.svg [ Failure Pass Timeout ] -crbug.com/521764 [ Win10 ] svg/text/bidi-text-query.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/text/bidi-tspans.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/text/obb-paintserver.html [ Failure Pass Timeout ] -crbug.com/521764 [ Win10 ] svg/text/text-selection-fonts-01-t.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] svg/text/text-selection-intro-05-t.svg [ Failure Timeout ] -crbug.com/521764 [ Win10 ] animations/interpolation/background-position-origin-interpolation.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] animations/interpolation/background-size-interpolation.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] animations/interpolation/font-size-zoom-interpolation.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] animations/interpolation/webkit-mask-image-interpolation.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] animations/interpolation/webkit-mask-size-interpolation.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/canvas/webgl/framebuffer-bindings-unaffected-on-resize.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/dom/Range/range-clone-contents.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] inspector/sources/debugger-pause/pause-in-inline-script.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] plugins/no-mime-with-valid-extension.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] plugins/plugin-cancel-sync-xhr.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] fast/css/fontfaceset-add-remove-while-loading.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/loader/local-image-from-local.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/preloader/scan-body-from-head-import.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/preloader/style.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/scroll-behavior/overflow-scroll-root-frame-animates.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] http/tests/inspector/network/network-image-404.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] http/tests/inspector/network/network-xhr-redirect-body.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] http/tests/loading/redirect-methods.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] inspector/console/console-copy-treeoutline.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] inspector/console/console-tests.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] inspector/tracing/timeline-auto-record.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] inspector/tracing/timeline-timer-fired-from-eval-call-site.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] plugins/netscape-plugin-map-data-to-src.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] plugins/update-widgets-crash.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] svg/custom/textPath-remove-path-pattern.svg [ Failure Pass Timeout ] -crbug.com/521764 [ Win10 ] accessibility/inline-text-changes.html [ Failure Pass ] -crbug.com/521764 [ Win10 ] fast/loader/javascript-detached-frame-no-crash.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] virtual/display_list_2d_canvas/fast/canvas/canvas-resize-reset.html [ Pass Timeout ] -crbug.com/521764 [ Win10 ] transitions/equivalent-background-image-no-transition.html [ Pass Timeout ] +crbug.com/521730 [ Win10 ] svg/W3C-SVG-1.1/text-align-08-b.svg [ Failure ] +crbug.com/521730 [ Win10 ] fast/css/line-height-determined-by-primary-font.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/forms/month/month-appearance-l10n.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/forms/month/month-appearance-pseudo-elements.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/forms/search/search-appearance-basic.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/inline/justify-emphasis-inline-box.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/ruby/nested-ruby.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text-autosizing/display-type-change.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/css-table-single-cell-lots-of-text.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/nested-table-wrapping.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text-autosizing/tables/single-cell-lots-of-text.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/atsui-negative-spacing-features.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/basic/011.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/basic/013.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/basic/generic-family-reset.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/cg-fallback-bolding.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/cg-vs-atsui.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/decorations-with-text-combine.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/emoticons.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/emphasis-ellipsis-complextext.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/font-ascent-mac.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/font-stretch-variant.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/font-weight.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/002.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/bidi-linebreak-002.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/danda-space.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/hebrew-vowels.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/khmer-selection.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/lang-glyph-cache-separation.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/pop-up-button-text-alignment-and-direction.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/rtl-white-space-pre-wrap.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/text-spliced-font.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/international/wrap-CJK-001.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/midword-break-hang.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/selection-multiple-runs.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/stroking.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/sub-pixel/text-scaling-pixel.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/trailing-white-space.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/text/wide-zero-width-space.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/writing-mode/fallback-orientation.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/writing-mode/japanese-lr-text.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/writing-mode/japanese-rl-text.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/writing-mode/japanese-ruby-vertical-rl.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/writing-mode/vertical-align-table-baseline.html [ Failure ] +crbug.com/521730 [ Win10 ] fast/writing-mode/vertical-baseline-alignment.html [ Failure ] +crbug.com/521730 [ Win10 ] fonts/fantasy.html [ Failure ] +crbug.com/521730 [ Win10 ] ietestcenter/css3/text/textshadow-002.htm [ Failure ] +crbug.com/521730 [ Win10 ] ietestcenter/css3/text/textshadow-010.htm [ Failure ] +crbug.com/521730 [ Win10 ] printing/webgl-repeated-printing.html [ Failure ] +crbug.com/521730 [ Win10 ] virtual/threaded/printing/webgl-repeated-printing.html [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/g-dirLTR-ubNone.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/g-dirLTR-ubOverride.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/g-dirRTL-ubNone.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/g-dirRTL-ubOverride.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-anchor-dirLTR-anchorEnd.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-anchor-dirLTR-anchorMiddle.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-anchor-dirLTR-anchorStart.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-anchor-dirNone-anchorEnd.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-anchor-dirNone-anchorMiddle.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-anchor-dirNone-anchorStart.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-anchor-dirRTL-anchorEnd.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-anchor-dirRTL-anchorMiddle.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-anchor-dirRTL-anchorStart.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorEnd.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorMiddle.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorStart.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorEnd.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorMiddle.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorStart.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-anchor-no-markup.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-dirRTL-ubNone.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/text-dirRTL-ubOverride.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirLTR-ubEmbed-in-rtl-context.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirLTR-ubNone-in-rtl-context.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirLTR-ubOverride-in-default-context.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirLTR-ubOverride-in-rtl-context.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirNone-ubOverride-in-default-context.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirNone-ubOverride-in-ltr-context.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirNone-ubOverride-in-rtl-context.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirRTL-ubEmbed-in-ltr-context.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirRTL-ubNone-in-default-context.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirRTL-ubOverride-in-default-context.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirRTL-ubOverride-in-ltr-context.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirRTL-ubOverride-in-rtl-context.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-direction-ltr.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-direction-rtl.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-SVG-1.1/text-fonts-01-t.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-SVG-1.1/text-intro-01-t.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/W3C-SVG-1.1/text-intro-04-t.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/as-image/svg-canvas-xhtml-tainted.html [ Failure ] +crbug.com/521730 [ Win10 ] svg/css/text-shadow-multiple.xhtml [ Failure ] +crbug.com/521730 [ Win10 ] svg/custom/textPath-change-id2-pattern.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/text/bidi-text-query.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/text/bidi-tspans.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/text/text-selection-fonts-01-t.svg [ Failure ] +crbug.com/521730 [ Win10 ] svg/text/text-selection-intro-05-t.svg [ Failure ] crbug.com/550430 fast/html/details-writing-mode.html [ Failure Pass ] crbug.com/550285 [ SnowLeopard ] virtual/syncpaint/compositing/repaint/newly-composited-on-scroll.html [ Failure ] crbug.com/550285 [ SnowLeopard ] virtual/syncpaint/fast/repaint/background-image-paint-invalidation-large-abspos-div.html [ Failure ] crbug.com/550285 [ SnowLeopard ] virtual/syncpaint/fast/repaint/repaint-during-scroll.html [ Failure ] +crbug.com/550285 [ XP ] virtual/syncpaint/fast/repaint/float-overflow-right.html [ Failure ] crbug.com/474759 fast/writing-mode/vertical-rl-replaced-selection.html [ Failure ] crbug.com/474759 fast/block/line-layout/selection-highlight-overlap.html [ Failure ] @@ -1502,33 +1306,7 @@ crbug.com/353746 virtual/android/fullscreen/video-specified-size.html [ Failure Pass ] -crbug.com/524764 [ Win10 ] virtual/trustedeventsdefaultaction/fast/events/selectstart-prevent-selectall.html [ Failure Pass ] -crbug.com/524764 [ Win10 ] virtual/pointerevent/fast/events/selectstart-prevent-selectall.html [ Failure Pass ] - -crbug.com/524804 [ Win10 ] animations/interpolation/border-image-source-interpolation.html [ Failure Pass ] -crbug.com/524804 [ Win10 ] animations/interpolation/border-image-width-interpolation.html [ Failure Pass ] -crbug.com/524804 [ Win10 ] animations/interpolation/display-interpolation.html [ Failure Pass ] -crbug.com/524804 [ Win10 ] animations/interpolation/filter-interpolation.html [ Failure Pass ] -crbug.com/524804 [ Win10 ] animations/interpolation/font-size-adjust-interpolation.html [ Pass Timeout ] -crbug.com/524804 [ Win10 ] animations/interpolation/font-weight-interpolation.html [ Pass Timeout ] -crbug.com/524804 [ Win10 ] animations/interpolation/list-style-image-interpolation.html [ Failure Pass ] -crbug.com/524804 [ Win10 ] animations/interpolation/rotate-interpolation.html [ Pass Timeout ] -crbug.com/524804 [ Win10 ] animations/interpolation/svg-stroke-dasharray-interpolation.html [ Failure Pass ] -crbug.com/524804 [ Win10 ] animations/interpolation/webkit-mask-box-image-width-interpolation.html [ Failure Pass ] -crbug.com/524804 [ Win10 ] animations/interpolation/z-index-interpolation.html [ Pass Timeout ] -crbug.com/524804 [ Win10 ] animations/interpolation/webkit-mask-box-image-source-interpolation.html [ Failure Pass ] - -crbug.com/529753 [ Win10 ] virtual/pointerevent/fast/events/mouseover-mouseout.html [ Failure Pass ] -crbug.com/529753 [ Win10 ] virtual/trustedeventsdefaultaction/fast/events/mouseover-mouseout.html [ Failure Pass ] -crbug.com/529753 [ Win10 ] virtual/trustedeventsdefaultaction/fast/events/pointer-events-2.html [ Failure Pass ] -crbug.com/529753 [ Win10 ] virtual/pointerevent/fast/events/pointer-events-2.html [ Failure Pass ] - crbug.com/527270 accessibility/name-calc-img.html [ Failure Pass Timeout ] -crbug.com/527278 [ Win10 ] compositing/layer-creation/compositing-reason-removed.html [ Pass Timeout ] - -crbug.com/524826 [ Win10 ] compositing/squashing/squashing-reflection-disallowed.html [ Pass Timeout ] - -crbug.com/526752 [ Win10 ] fast/css/fontfaceset-check-platform-fonts.html [ Failure Pass ] # This test has different results in Debug and Release. crbug.com/529038 [ Debug ] virtual/gpu/fast/canvas/canvas-composite-repaint-by-all-imagesource.html [ Failure ] @@ -1538,14 +1316,12 @@ crbug.com/532643 [ Mac ] virtual/pointerevent/fast/events/hit-test-cache-scrollbar-no-crash.html [ Pass Failure ] # The Win10 result for fast/text/emoji-font-fallback-win.html does not match the description -crbug.com/527044 [ Win10 ] fast/text/emoji-font-fallback-win.html [ Failure Timeout ] +crbug.com/527044 [ Win10 ] fast/text/emoji-font-fallback-win.html [ Failure ] crbug.com/525065 webaudio/audionode-disconnect-audioparam.html [ Failure Pass ] crbug.com/525296 fast/css/font-load-while-styleresolver-missing.html [ Crash Failure Pass ] -crbug.com/525299 [ MountainLion Mavericks XP Win10 ] http/tests/security/redirect-BLOCKED-to-localURL.html [ Failure Pass ] - crbug.com/240576 fullscreen/api/element-ready-check-containing-iframe.html [ Timeout Failure Pass ] crbug.com/240576 virtual/android/fullscreen/api/element-ready-check-containing-iframe.html [ Timeout Failure Pass ] @@ -1553,10 +1329,6 @@ crbug.com/457273 [ Mac ] http/tests/websocket/close.html [ Pass Timeout ] -crbug.com/538526 [ Win7 Win10 ] virtual/spv2/paint/invalidation/spv2/fixed-img-src-change-after-scroll.html [ Failure ] - -crbug.com/527743 [ Win10 ] paint/masks/table-cell-masks.html [ Pass Timeout ] -crbug.com/527743 [ Win10 ] virtual/syncpaint/paint/masks/table-cell-masks.html [ Skip ] crbug.com/531286 virtual/gpu/fast/canvas/yuv-video-on-accelerated-canvas.html [ Failure ] crbug.com/535478 [ Win ] virtual/threaded/inspector/tracing/decode-resize.html [ Slow Pass Failure ] @@ -1581,3 +1353,10 @@ crbug.com/549314 [ XP ] inspector-protocol/layout-fonts/unicode-range-combining-chars-fallback.html [ Failure ] +crbug.com/551057 [ XP ] imported/csswg-test/css-writing-modes-3/vertical-alignment-vlr-023.xht [ Failure ] +crbug.com/551057 [ XP ] imported/csswg-test/css-writing-modes-3/vertical-alignment-vlr-025.xht [ Failure ] +crbug.com/551057 [ XP ] imported/csswg-test/css-writing-modes-3/vertical-alignment-vlr-027.xht [ Failure ] + +crbug.com/551272 fast/js/getOwnPropertyDescriptor.html [ NeedsManualRebaseline ] +crbug.com/551272 fast/js/pic/cached-named-property-getter.html [ NeedsManualRebaseline ] +crbug.com/551272 fast/js/mozilla/strict/15.10.7.html [ NeedsManualRebaseline ]
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flex-column-relayout-assert-expected.txt b/third_party/WebKit/LayoutTests/css3/flexbox/flex-column-relayout-assert-expected.txt new file mode 100644 index 0000000..8dc051e --- /dev/null +++ b/third_party/WebKit/LayoutTests/css3/flexbox/flex-column-relayout-assert-expected.txt
@@ -0,0 +1,3 @@ +You should see a green rectangle, 20px high. + +PASS
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flex-column-relayout-assert.html b/third_party/WebKit/LayoutTests/css3/flexbox/flex-column-relayout-assert.html new file mode 100644 index 0000000..da253ef --- /dev/null +++ b/third_party/WebKit/LayoutTests/css3/flexbox/flex-column-relayout-assert.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<link href="resources/flexbox.css" rel="stylesheet"> +<style> +.flexbox { + background-color: green; +} +</style> +<script src="../../resources/check-layout.js"></script> +<body onload="checkLayout('.flexbox')"> + +<p>You should see a green rectangle, 20px high.</p> + +<div class="flexbox column" data-expected-height="40"> + <div id="child" data-expected-height="40"></div> +</div> + +<script> +document.getElementById('child').offsetHeight; +document.getElementById('child').style.padding = "20px"; +</script>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/stretched-child-shrink-on-relayout.html b/third_party/WebKit/LayoutTests/css3/flexbox/stretched-child-shrink-on-relayout.html index 8f3adee..c384d561 100644 --- a/third_party/WebKit/LayoutTests/css3/flexbox/stretched-child-shrink-on-relayout.html +++ b/third_party/WebKit/LayoutTests/css3/flexbox/stretched-child-shrink-on-relayout.html
@@ -53,20 +53,18 @@ <div class="horizontal-tb" data-expected-height=10 data-expected-width=40></div> <div class="largeitem"></div> </div> - <div class="flexbox"> <div class="vertical-lr" data-expected-height=10 data-expected-width=10></div> <div class="largeitem"></div> </div> <div class="flexbox column"> - <div class="vertical-lr" data-expected-height=10 data-expected-width=10></div> + <div class="vertical-lr" data-expected-height=10 data-expected-width=40></div> <div class="largeitem"></div> </div> - <script> document.body.offsetTop; var targets = document.getElementsByClassName('largeitem'); for (var i = targets.length - 1; i >= 0; i--) { targets[i].remove(); }; -</script> \ No newline at end of file +</script>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/stretching-orthogonal-flows-expected.html b/third_party/WebKit/LayoutTests/css3/flexbox/stretching-orthogonal-flows-expected.html new file mode 100644 index 0000000..3a3efaa --- /dev/null +++ b/third_party/WebKit/LayoutTests/css3/flexbox/stretching-orthogonal-flows-expected.html
@@ -0,0 +1,5 @@ +<!DOCTYPE html> + +<p>You should see no red.</p> + +<div style="height: 40px; background-color: green;"></div>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/stretching-orthogonal-flows.html b/third_party/WebKit/LayoutTests/css3/flexbox/stretching-orthogonal-flows.html new file mode 100644 index 0000000..b60ad8f --- /dev/null +++ b/third_party/WebKit/LayoutTests/css3/flexbox/stretching-orthogonal-flows.html
@@ -0,0 +1,9 @@ +<!DOCTYPE html> +<link href="resources/flexbox.css" rel="stylesheet"> + +<p>You should see no red.</p> + +<div class="flexbox column align-items-stretch" style="background-color: red;"> + <div style="background-color: green; height: 20px;"></div> + <div style="writing-mode: vertical-lr; background-color: green; height: 20px;"></div> +</div>
diff --git a/third_party/WebKit/LayoutTests/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed.html b/third_party/WebKit/LayoutTests/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed.html new file mode 100644 index 0000000..d957e405 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<object> + <ul> </ul> + <table> + <option> <option> + </table> +</object> +<script> + window.setInterval(function(){ + var oe = document.getElementsByTagName("*"); + for (var i = 0; i < oe.length; i++) { + var o = oe.item(i); + if (!o.firstElementChild && o != document.documentElement) { + p = o.parentNode; + p.replaceChild(document.createTextNode("PASS"), o) + } + } + }); +</script> +<p id="title">crbug.com/549544: Don't clean up anonymous wrappers when the element's branch or sub-tree is being destroyed.</p>
diff --git a/third_party/WebKit/LayoutTests/fast/css/rem-in-linked-stylesheet-on-body-expected.html b/third_party/WebKit/LayoutTests/fast/css/rem-in-linked-stylesheet-on-body-expected.html new file mode 100644 index 0000000..62ab925 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/css/rem-in-linked-stylesheet-on-body-expected.html
@@ -0,0 +1,10 @@ +<style> +body, div { + font-size: 12px; +} +</style> + +<body> + Test to see that rem units are applied correctly on body elements, this line should have a font-size of 12px. + <div>Test to see that rem units are applied correctly on div elements, this line should have a font-size of 12px.</div> +</body>
diff --git a/third_party/WebKit/LayoutTests/fast/css/rem-in-linked-stylesheet-on-body.css b/third_party/WebKit/LayoutTests/fast/css/rem-in-linked-stylesheet-on-body.css new file mode 100644 index 0000000..1cc150c --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/css/rem-in-linked-stylesheet-on-body.css
@@ -0,0 +1,7 @@ +:root { + font-size: 6px; +} + +body, div { + font-size: 2rem; +}
diff --git a/third_party/WebKit/LayoutTests/fast/css/rem-in-linked-stylesheet-on-body.html b/third_party/WebKit/LayoutTests/fast/css/rem-in-linked-stylesheet-on-body.html new file mode 100644 index 0000000..438c6f3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/css/rem-in-linked-stylesheet-on-body.html
@@ -0,0 +1,9 @@ +<!DOCTYPE html> + +<link href="rem-in-linked-stylesheet-on-body.css" type="text/css" rel="stylesheet"> + +<body> + Test to see that rem units are applied correctly on body elements, this line should have a font-size of 12px. + <div>Test to see that rem units are applied correctly on div elements, this line should have a font-size of 12px.</div> +</body> +
diff --git a/third_party/WebKit/LayoutTests/fast/css/variables/reference-with-no-closing-parenthesis-expected.html b/third_party/WebKit/LayoutTests/fast/css/variables/reference-with-no-closing-parenthesis-expected.html new file mode 100644 index 0000000..d707850 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/css/variables/reference-with-no-closing-parenthesis-expected.html
@@ -0,0 +1,3 @@ +<!DOCTYPE html> +<style>div { color: green }</style> +<div>This text should be green.</div> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/css/variables/reference-with-no-closing-parenthesis.html b/third_party/WebKit/LayoutTests/fast/css/variables/reference-with-no-closing-parenthesis.html new file mode 100644 index 0000000..7bfbdc48 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/css/variables/reference-with-no-closing-parenthesis.html
@@ -0,0 +1,3 @@ +<!DOCTYPE html> +<style>div { color: var(--a, green</style> +<div>This text should be green.</div> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLScriptElement/script-sync-onerror-not-repeated-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/HTMLScriptElement/script-sync-onerror-not-repeated-expected.txt new file mode 100644 index 0000000..392a70d7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLScriptElement/script-sync-onerror-not-repeated-expected.txt
@@ -0,0 +1,10 @@ +Script that fails to load should not dispatch multiple error events + +On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + + +PASS numberOfTimesOnErrorHandlerHasRun is 0 +PASS successfullyParsed is true + +TEST COMPLETE +
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLScriptElement/script-sync-onerror-not-repeated.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLScriptElement/script-sync-onerror-not-repeated.html new file mode 100644 index 0000000..d0a65dd --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLScriptElement/script-sync-onerror-not-repeated.html
@@ -0,0 +1,47 @@ +<!DOCTYPE html> +<html> +<head> +<script src="../../../resources/js-test.js"></script> +<script> +function loadScript(url, async, onload, onerror) { + var script = document.createElement("script"); + script.async = async; + script.onload = onload; + if (onerror) + script.onerror = onerror; + script.src = url; + document.head.appendChild(script); +} +</script> +</head> +<body> +<script> +description("Script that fails to load should not dispatch multiple error events"); + +window.jsTestIsAsync = true; + +if (window.testRunner) { + testRunner.dumpAsText(); + testRunner.waitUntilDone(); +} + +var numberOfTimesOnErrorHandlerHasRun = 0; +function step2() { + shouldBeZero("numberOfTimesOnErrorHandlerHasRun"); + numberOfTimesOnErrorHandlerHasRun++; + // Issue another script load so as to have the script runner + // revisit its script queue. It must not include the sync script + // that triggered the dispatch of an error event and the running of + // this handler. + loadScript("resources/script-load.js", true, finishJSTest); +} + +function unexpectedLoad() { + testFailed("Script should not have loaded"); + finishJSTest(); +} + +loadScript("non-existing.js", false, unexpectedLoad, step2); +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/document-dir-property-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/document-dir-property-expected.txt index 7ca479c7..5025229 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/document-dir-property-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/dom/document-dir-property-expected.txt
@@ -15,6 +15,9 @@ Read document.documentElement.dir in body PASS document.documentElement.dir is "rtl" +Read document.documentElement.getAttribute('dir') in body +PASS document.documentElement.getAttribute('dir') is "rtl" + Read document.body.dir in body PASS document.body.dir is "" @@ -27,14 +30,23 @@ Read document.body.dir in body PASS document.body.dir is "" +Read document.documentElement.getAttribute('dir') in body +PASS document.documentElement.getAttribute('dir') is "ltr" + Write non-canonical case document.dir in body PASS document.dir = 'RTL' did not throw exception. PASS document.dir is "rtl" +Read document.documentElement.getAttribute('dir') in body +PASS document.documentElement.getAttribute('dir') is "RTL" + Write invalid document.dir in body PASS document.dir = 'WRONG' did not throw exception. PASS document.dir is "" +Read document.documentElement.getAttribute('dir') in body +PASS document.documentElement.getAttribute('dir') is "WRONG" + Write non-canonical case document.body.dir in body PASS document.body.dir = 'RTL' did not throw exception. PASS document.body.dir is "rtl" @@ -43,6 +55,12 @@ PASS document.body.dir = 'WRONG' did not throw exception. PASS document.body.dir is "" +Read document.dir in body +PASS document.dir is "" + +Read document.documentElement.getAttribute('dir') in body +PASS document.documentElement.getAttribute('dir') is "null" + PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/dom/document-dir-property.html b/third_party/WebKit/LayoutTests/fast/dom/document-dir-property.html index fce0786e..08b2700 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/document-dir-property.html +++ b/third_party/WebKit/LayoutTests/fast/dom/document-dir-property.html
@@ -28,6 +28,10 @@ shouldBeEqualToString("document.documentElement.dir", "rtl"); debug(""); +debug("Read document.documentElement.getAttribute('dir') in body"); +shouldBeEqualToString("document.documentElement.getAttribute('dir')", "rtl"); +debug(""); + debug("Read document.body.dir in body"); shouldBeEqualToString("document.body.dir", ""); debug(""); @@ -45,16 +49,28 @@ shouldBeEqualToString("document.body.dir", ""); debug(""); +debug("Read document.documentElement.getAttribute('dir') in body"); +shouldBeEqualToString("document.documentElement.getAttribute('dir')", "ltr"); +debug(""); + debug("Write non-canonical case document.dir in body"); shouldNotThrow("document.dir = 'RTL'"); shouldBeEqualToString("document.dir", "rtl"); debug(""); +debug("Read document.documentElement.getAttribute('dir') in body"); +shouldBeEqualToString("document.documentElement.getAttribute('dir')", "RTL"); +debug(""); + debug("Write invalid document.dir in body"); shouldNotThrow("document.dir = 'WRONG'"); shouldBeEqualToString("document.dir", ""); debug(""); +debug("Read document.documentElement.getAttribute('dir') in body"); +shouldBeEqualToString("document.documentElement.getAttribute('dir')", "WRONG"); +debug(""); + debug("Write non-canonical case document.body.dir in body"); shouldNotThrow("document.body.dir = 'RTL'"); shouldBeEqualToString("document.body.dir", "rtl"); @@ -64,6 +80,16 @@ shouldNotThrow("document.body.dir = 'WRONG'"); shouldBeEqualToString("document.body.dir", ""); debug(""); + +document.dir = null; +debug("Read document.dir in body"); +shouldBeEqualToString("document.dir", ""); +debug(""); + +debug("Read document.documentElement.getAttribute('dir') in body"); +shouldBeEqualToString("document.documentElement.getAttribute('dir')", "null"); +debug(""); + </script> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/multiple-backgrounds-style-change-expected.txt b/third_party/WebKit/LayoutTests/fast/repaint/multiple-backgrounds-style-change-expected.txt new file mode 100644 index 0000000..b8a8dcc --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/repaint/multiple-backgrounds-style-change-expected.txt
@@ -0,0 +1,24 @@ +{ + "bounds": [800, 600], + "children": [ + { + "bounds": [800, 600], + "contentsOpaque": true, + "drawsContent": true, + "children": [ + { + "position": [8, 8], + "bounds": [202, 202], + "drawsContent": true, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [50, 50, 0, 1] + ] + } + ] + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/multiple-backgrounds-style-change.html b/third_party/WebKit/LayoutTests/fast/repaint/multiple-backgrounds-style-change.html new file mode 100644 index 0000000..ff865ac --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/repaint/multiple-backgrounds-style-change.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<style> + .box { + height: 200px; + width: 200px; + border: 1px solid black; + background-repeat: no-repeat; + background-size: 100px 100px; + background-position: 0 0, 100px 100px; + background-image: url('../images/resources/green-256x256.jpg'), url('../images/resources/dice.png'); + } + + .composited { + transform: translate3d(0, 0, 0); + } + + .composited.changed { + transform: translate3d(50px, 50px, 0); + } +</style> +<script src="resources/text-based-repaint.js"></script> +<script> + function repaintTest() + { + document.getElementById('test').classList.add('changed'); + } + + onload = runRepaintTest; +</script> +<div id="test" class="composited box"> +</div> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/scroll-behavior/resources/subframe-with-scroll.html b/third_party/WebKit/LayoutTests/fast/scroll-behavior/resources/subframe-with-scroll.html new file mode 100644 index 0000000..fa56648 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/scroll-behavior/resources/subframe-with-scroll.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html> +<head> + <style> + #container { + width: 200px; + height: 200px; + overflow: scroll; + } + #content { + width: 750px; + height: 10000px; + background-color: blue; + } + </style> + <div id="container"> + <div id="content"></div> + </div> + <script type="text/javascript"> + if (window.internals) + internals.settings.setScrollAnimatorEnabled(true); + + requestAnimationFrame(() => { + if (container.scrollTo) + container.scrollTo({left: 750, top: 10000, behavior: 'smooth'}); + else + console.log('ERROR: no container.scrollTo'); + }); + </script> +</head> +</html>
diff --git a/third_party/WebKit/LayoutTests/fast/text/textarea-after-stylesheet-link-expected.html b/third_party/WebKit/LayoutTests/fast/text/textarea-after-stylesheet-link-expected.html new file mode 100644 index 0000000..5c06710f --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/text/textarea-after-stylesheet-link-expected.html
@@ -0,0 +1,5 @@ +<!DOCTYPE html> + +<form> +<textarea>Passed</textarea> +</form>
diff --git a/third_party/WebKit/LayoutTests/fast/text/textarea-after-stylesheet-link.html b/third_party/WebKit/LayoutTests/fast/text/textarea-after-stylesheet-link.html new file mode 100644 index 0000000..00770ef --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/text/textarea-after-stylesheet-link.html
@@ -0,0 +1,7 @@ +<!DOCTYPE html> + +<link rel="stylesheet" /> + +<form> +<textarea>Passed</textarea> +</form>
diff --git a/third_party/WebKit/LayoutTests/http/tests/misc/onload-write-during-xframe-deny-expected.txt b/third_party/WebKit/LayoutTests/http/tests/misc/onload-write-during-xframe-deny-expected.txt index 5a523a8..077cc10 100644 --- a/third_party/WebKit/LayoutTests/http/tests/misc/onload-write-during-xframe-deny-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/misc/onload-write-during-xframe-deny-expected.txt
@@ -1,2 +1,2 @@ -CONSOLE ERROR: Refused to display 'http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe-in-body.html' in a frame because it set 'X-Frame-Options' to 'deny'. +CONSOLE ERROR: line 6: Refused to display 'http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe-in-body.html' in a frame because it set 'X-Frame-Options' to 'deny'. PASS
diff --git a/third_party/WebKit/LayoutTests/http/tests/misc/resources/slow-nonexisting-script.php b/third_party/WebKit/LayoutTests/http/tests/misc/resources/slow-nonexisting-script.php new file mode 100644 index 0000000..076b8567 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/misc/resources/slow-nonexisting-script.php
@@ -0,0 +1,6 @@ +<?php +sleep(intval($_GET['timeout'])); +header("HTTP/1.1 404 Not Found"); +header("Content-Type: text/javascript"); +echo("testFailed('script should not run');"); +?>
diff --git a/third_party/WebKit/LayoutTests/http/tests/misc/resources/success.js b/third_party/WebKit/LayoutTests/http/tests/misc/resources/success.js new file mode 100644 index 0000000..3ebcf877 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/misc/resources/success.js
@@ -0,0 +1 @@ +successfullyExecuted = true;
diff --git a/third_party/WebKit/LayoutTests/http/tests/misc/script-sync-slow-scripts-onerror-expected.txt b/third_party/WebKit/LayoutTests/http/tests/misc/script-sync-slow-scripts-onerror-expected.txt new file mode 100644 index 0000000..12463f9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/misc/script-sync-slow-scripts-onerror-expected.txt
@@ -0,0 +1,12 @@ +Slow scripts that fail to load should not dispatch multiple error events + +On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + + +PASS firstOnErrorHandlerHasRun is false +PASS firstOnErrorHandlerHasRun is true +PASS secondOnErrorHandlerHasRun is false +PASS successfullyParsed is true + +TEST COMPLETE +
diff --git a/third_party/WebKit/LayoutTests/http/tests/misc/script-sync-slow-scripts-onerror.html b/third_party/WebKit/LayoutTests/http/tests/misc/script-sync-slow-scripts-onerror.html new file mode 100644 index 0000000..31138b6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/misc/script-sync-slow-scripts-onerror.html
@@ -0,0 +1,56 @@ +<!DOCTYPE html> +<html> +<head> +<script src="/js-test-resources/js-test.js"></script> +<script> +function loadScript(url, async, onload, onerror) { + var script = document.createElement("script"); + script.async = async; + script.onload = onload; + if (onerror) + script.onerror = onerror; + script.src = url; + document.head.appendChild(script); +} +</script> +</head> +<body> +<script> +description("Slow scripts that fail to load should not dispatch multiple error events"); + +window.jsTestIsAsync = true; + +if (window.testRunner) { + testRunner.dumpAsText(); + testRunner.waitUntilDone(); +} + +var firstOnErrorHandlerHasRun = false; +function failedFirst() { + shouldBeFalse("firstOnErrorHandlerHasRun"); + firstOnErrorHandlerHasRun = true; + // Issue another script load so as to have the script runner + // revisit its script queue. This should not result in this + // onerror handler running again. + loadScript("resources/success.js?1", true); +} + +var secondOnErrorHandlerHasRun = false; +function failedSecond() { + shouldBeTrue("firstOnErrorHandlerHasRun"); + shouldBeFalse("secondOnErrorHandlerHasRun"); + secondOnErrorHandlerHasRun = true; + loadScript("resources/success.js?2", true, finishJSTest); +} + +function unexpectedLoad() { + testFailed("Script should not have loaded"); + finishJSTest(); +} + +loadScript("resources/success.js?3", false); +loadScript("resources/slow-nonexisting-script.php?sleep=1", false, unexpectedLoad, failedFirst); +loadScript("resources/slow-nonexisting-script.php?sleep=2", false, unexpectedLoad, failedSecond); +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-expected.txt index 2b47d7a..996557b 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-expected.txt
@@ -1,7 +1,7 @@ http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe.html - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe.html, main document URL http://127.0.0.1:8000/security/XFrameOptions/x-frame-options-deny-meta-tag.html, http method GET> redirectResponse (null) http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe.html - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe.html, http status code 200> http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe.html - didFinishLoading -CONSOLE ERROR: Refused to display 'http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe.html' in a frame because it set 'X-Frame-Options' to 'deny'. +CONSOLE ERROR: line 3: Refused to display 'http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe.html' in a frame because it set 'X-Frame-Options' to 'deny'. data:, - willSendRequest <NSURLRequest URL data:,, main document URL http://127.0.0.1:8000/security/XFrameOptions/x-frame-options-deny-meta-tag.html, http method GET> redirectResponse (null) data:, - didReceiveResponse <NSURLResponse data:,, http status code 200> data:, - didFinishLoading
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-in-body-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-in-body-expected.txt index 1280adc..0ca7a24 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-in-body-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-in-body-expected.txt
@@ -1,7 +1,7 @@ http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe-in-body.html - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe-in-body.html, main document URL http://127.0.0.1:8000/security/XFrameOptions/x-frame-options-deny-meta-tag-in-body.html, http method GET> redirectResponse (null) http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe-in-body.html - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe-in-body.html, http status code 200> http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe-in-body.html - didFinishLoading -CONSOLE ERROR: Refused to display 'http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe-in-body.html' in a frame because it set 'X-Frame-Options' to 'deny'. +CONSOLE ERROR: line 6: Refused to display 'http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe-in-body.html' in a frame because it set 'X-Frame-Options' to 'deny'. data:, - willSendRequest <NSURLRequest URL data:,, main document URL http://127.0.0.1:8000/security/XFrameOptions/x-frame-options-deny-meta-tag-in-body.html, http method GET> redirectResponse (null) data:, - didReceiveResponse <NSURLResponse data:,, http status code 200> data:, - didFinishLoading
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-parent-same-origin-deny-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-parent-same-origin-deny-expected.txt index cec302c..abae37ee 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-parent-same-origin-deny-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-parent-same-origin-deny-expected.txt
@@ -1,7 +1,7 @@ http://localhost:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe-parent-same-origin-deny.html - willSendRequest <NSURLRequest URL http://localhost:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe-parent-same-origin-deny.html, main document URL http://127.0.0.1:8000/security/XFrameOptions/x-frame-options-deny-meta-tag-parent-same-origin-deny.html, http method GET> redirectResponse (null) http://localhost:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe-parent-same-origin-deny.html - didReceiveResponse <NSURLResponse http://localhost:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe-parent-same-origin-deny.html, http status code 200> http://localhost:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe-parent-same-origin-deny.html - didFinishLoading -CONSOLE ERROR: Refused to display 'http://localhost:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe-parent-same-origin-deny.html' in a frame because it set 'X-Frame-Options' to 'sameorigin'. +CONSOLE ERROR: line 3: Refused to display 'http://localhost:8000/security/XFrameOptions/resources/x-frame-options-deny-meta-tag-subframe-parent-same-origin-deny.html' in a frame because it set 'X-Frame-Options' to 'sameorigin'. data:, - willSendRequest <NSURLRequest URL data:,, main document URL http://127.0.0.1:8000/security/XFrameOptions/x-frame-options-deny-meta-tag-parent-same-origin-deny.html, http method GET> redirectResponse (null) data:, - didReceiveResponse <NSURLResponse data:,, http status code 200> data:, - didFinishLoading
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/xssAuditor/meta-tag-http-refresh-x-frame-options-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/xssAuditor/meta-tag-http-refresh-x-frame-options-expected.txt index e8707c39..c2f0d16 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/xssAuditor/meta-tag-http-refresh-x-frame-options-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/security/xssAuditor/meta-tag-http-refresh-x-frame-options-expected.txt
@@ -1,2 +1,2 @@ -CONSOLE ERROR: Refused to display 'http://localhost:8000/security/xssAuditor/resources/echo-head.pl?q=%3Cmeta+http-equiv%3D%22x-frame-options%22+content%3D%22deny%22%3E' in a frame because it set 'X-Frame-Options' to 'deny'. +CONSOLE ERROR: line 4: Refused to display 'http://localhost:8000/security/xssAuditor/resources/echo-head.pl?q=%3Cmeta+http-equiv%3D%22x-frame-options%22+content%3D%22deny%22%3E' in a frame because it set 'X-Frame-Options' to 'deny'.
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/support/ahem.css b/third_party/WebKit/LayoutTests/imported/gecko/variables/support/ahem.css new file mode 100644 index 0000000..539894a1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/support/ahem.css
@@ -0,0 +1,4 @@ +@font-face { + font-family: "Ahem"; + src: url(../../../../../resources/Ahem.ttf); +}
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/support/external-variable-declaration.css b/third_party/WebKit/LayoutTests/imported/gecko/variables/support/external-variable-declaration.css new file mode 100644 index 0000000..9ba1b9d --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/support/external-variable-declaration.css
@@ -0,0 +1,5 @@ +p { + color: red; + --a: green; + color: var(--a); +}
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/support/external-variable-font-face.css b/third_party/WebKit/LayoutTests/imported/gecko/variables/support/external-variable-font-face.css new file mode 100644 index 0000000..f13c9c1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/support/external-variable-font-face.css
@@ -0,0 +1,15 @@ +@font-face { + --a: MyTestFontName; + font-family: var(--a); + src: url(../../resources/Ahem.ttf); +} +@font-face { + font-family: MyTestFontName2; + src: url(../../resources/Ahem.ttf); +} +#a { + font-family: MyTestFontName; +} +#b { + font-family: MyTestFontName2; +}
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/support/external-variable-reference.css b/third_party/WebKit/LayoutTests/imported/gecko/variables/support/external-variable-reference.css new file mode 100644 index 0000000..0c697fd --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/support/external-variable-reference.css
@@ -0,0 +1,6 @@ +:root { + --a: green; +} +p { + color: var(--a); +}
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/support/external-variable-supports.css b/third_party/WebKit/LayoutTests/imported/gecko/variables/support/external-variable-supports.css new file mode 100644 index 0000000..96582bf --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/support/external-variable-supports.css
@@ -0,0 +1,4 @@ +body { color: red; } +@supports (color:var(--a)) { + p { color: green; } +}
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-01-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-01-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-01-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-01.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-01.html new file mode 100644 index 0000000..8c3ff421 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-01.html
@@ -0,0 +1,17 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable consisting of a single token preceded by white space.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: green; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-02-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-02-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-02-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-02.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-02.html new file mode 100644 index 0000000..4ee52b5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-02.html
@@ -0,0 +1,17 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable consisting of a single token with no preceding white space.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a:green; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-03-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-03-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-03-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-03.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-03.html new file mode 100644 index 0000000..50aa2f3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-03.html
@@ -0,0 +1,18 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that references another variable.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: var(--b); + --b: green; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-04-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-04-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-04-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-04.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-04.html new file mode 100644 index 0000000..52d5d314 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-04.html
@@ -0,0 +1,18 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable consisting of a variable reference followed by white space.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: var(--b) ; + --b: green; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-05-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-05-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-05-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-05.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-05.html new file mode 100644 index 0000000..0403bca --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-05.html
@@ -0,0 +1,18 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable consisting of a variable reference that includes white space around the variable name.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: var( --b ) ; + --b: green; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-06-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-06-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-06-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-06.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-06.html new file mode 100644 index 0000000..bccb52da --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-06.html
@@ -0,0 +1,18 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test overriding an existing variable declaration.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: orange; + --a: green; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-07-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-07-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-07-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-07.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-07.html new file mode 100644 index 0000000..ecd74b2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-07.html
@@ -0,0 +1,19 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable with invalid syntax due to a variable reference having no tokens in its fallback.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: green; + --b: crimson; + --a: var(--b,); + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-08-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-08-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-08-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-08.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-08.html new file mode 100644 index 0000000..e3cfd9c --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-08.html
@@ -0,0 +1,19 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that consists of a variable reference whose fallback is white space.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: orange; + --b: green; + --a: var(--b, ); + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-09-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-09-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-09-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-09.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-09.html new file mode 100644 index 0000000..898b973b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-09.html
@@ -0,0 +1,19 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable with invalid syntax due to a variable reference having only a comment in its fallback.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: green; + --b: crimson; + --a: var(--b,/**/); + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-10-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-10-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-10-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-10.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-10.html new file mode 100644 index 0000000..cfcfd32e --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-10.html
@@ -0,0 +1,19 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that consists of a variable reference with a fallback that includes a comment and an identifier.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: orange; + --b: green; + --a: var(--b,/**/a); + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-11-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-11-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-11-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-11.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-11.html new file mode 100644 index 0000000..ed011ad1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-11.html
@@ -0,0 +1,19 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable with invalid syntax due to a variable reference having a '!' token at the top level of its fallback.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: green; + --b: crimson; + --a: var(--b,!); + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-12-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-12-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-12-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-12.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-12.html new file mode 100644 index 0000000..3815754 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-12.html
@@ -0,0 +1,19 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable with invalid syntax due to a variable reference having a ';' token at the top level of its fallback.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: green; + --b: crimson; + --a: var(--b,;); + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-13-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-13-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-13-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-13.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-13.html new file mode 100644 index 0000000..5c262b8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-13.html
@@ -0,0 +1,19 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable with invalid syntax due to a variable reference having "!important" the top level of its fallback.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: green; + --b: crimson; + --a: var(--b,!important); + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-14-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-14-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-14-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-14.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-14.html new file mode 100644 index 0000000..153cfb99 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-14.html
@@ -0,0 +1,21 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that consists of a variable reference and a following identifier with no intervening white space.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: green; +} +span { + color: red; + --a:var(--b)red; + --b:orange; + color: var(--a); +} +</style> +<p><span>This text must be green.</span></p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-15-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-15-expected.html new file mode 100644 index 0000000..a03a89d5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-15-expected.html
@@ -0,0 +1,15 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="stylesheet" href="../support/ahem.css" type="text/css"> +<meta name="flags" content="ahem"> +<style> +p { + font-family: Ahem, sans-serif; +} +</style> +<p>This text must be in Ahem.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-15.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-15.html new file mode 100644 index 0000000..74e0cc9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-15.html
@@ -0,0 +1,22 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that consists of a comma-separated font family list.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="variable-declaration-15-ref.html"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" href="../support/ahem.css" type="text/css"> +<style> +body { + font-family: serif; +} +p { + font-family: monospace; + --a: Ahem, sans-serif; + font-family: var(--a); +} +</style> +<p>This text must be in Ahem.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-16-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-16-expected.html new file mode 100644 index 0000000..a03a89d5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-16-expected.html
@@ -0,0 +1,15 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="stylesheet" href="../support/ahem.css" type="text/css"> +<meta name="flags" content="ahem"> +<style> +p { + font-family: Ahem, sans-serif; +} +</style> +<p>This text must be in Ahem.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-16.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-16.html new file mode 100644 index 0000000..7def121 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-16.html
@@ -0,0 +1,23 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that consists of a comma-separated font family list with the first item being a variable reference.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="variable-declaration-16-ref.html"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" href="../support/ahem.css" type="text/css"> +<style> +body { + font-family: serif; +} +p { + font-family: monospace; + --a: var(--b), sans-serif; + --b: Ahem; + font-family: var(--a); +} +</style> +<p>This text must be in Ahem.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-17-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-17-expected.html new file mode 100644 index 0000000..7b2e465 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-17-expected.html
@@ -0,0 +1,15 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="stylesheet" href="../support/ahem.css" type="text/css"> +<meta name="flags" content="ahem"> +<style> +p { + font-family: SomeUnknownFont, Ahem; +} +</style> +<p>This text must be in Ahem.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-17.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-17.html new file mode 100644 index 0000000..e2629bb --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-17.html
@@ -0,0 +1,23 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that consists of a comma-separated font family list with the last item being a variable reference.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="variable-declaration-17-ref.html"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" href="../support/ahem.css" type="text/css"> +<style> +body { + font-family: serif; +} +p { + font-family: monospace; + --a: SomeUnknownFont, var(--b); + --b: Ahem; + font-family: var(--a); +} +</style> +<p>This text must be in Ahem.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-18-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-18-expected.html new file mode 100644 index 0000000..a03a89d5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-18-expected.html
@@ -0,0 +1,15 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="stylesheet" href="../support/ahem.css" type="text/css"> +<meta name="flags" content="ahem"> +<style> +p { + font-family: Ahem, sans-serif; +} +</style> +<p>This text must be in Ahem.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-18.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-18.html new file mode 100644 index 0000000..0cb06916 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-18.html
@@ -0,0 +1,23 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that consists of a comma-separated font family list with the comma coming from a variable reference.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="variable-declaration-18-ref.html"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" href="../support/ahem.css" type="text/css"> +<style> +body { + font-family: serif; +} +p { + font-family: monospace; + --a: Ahem var(--b) sans-serif; + --b: ,; + font-family: var(--a); +} +</style> +<p>This text must be in Ahem.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-19-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-19-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-19-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-19.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-19.html new file mode 100644 index 0000000..da0a825 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-19.html
@@ -0,0 +1,21 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that consists of a function where one of the arguments is a variable reference.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --a: rgb(0, var(--b), 0); + --b: 128; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-20-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-20-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-20-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-20.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-20.html new file mode 100644 index 0000000..9bffae2d --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-20.html
@@ -0,0 +1,21 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable with "!important".</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --a: var(--b) !important; + --b: green; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-21-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-21-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-21-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-21.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-21.html new file mode 100644 index 0000000..0a91196 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-21.html
@@ -0,0 +1,23 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that consists of a function where all of the arguments and commas are made up of variable references.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --a: rgb(var(--b)var(--c)var(--d)); + --b: 0,; + --c: 128,; + --d: 0; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-22-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-22-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-22-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-22.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-22.html new file mode 100644 index 0000000..a96d9cf --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-22.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that consists of a variable reference with a number of levels of variable reference fallbacks.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --a: var(--b, var(--c, var(--d, green))); + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-23-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-23-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-23-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-23.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-23.html new file mode 100644 index 0000000..b3b1d18 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-23.html
@@ -0,0 +1,22 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable with invalid syntax due to having two "!important" priorities.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --a: green; + --b: crimson; + --a: var(--b) !important !important; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-24-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-24-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-24-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-24.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-24.html new file mode 100644 index 0000000..ead972c2a --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-24.html
@@ -0,0 +1,25 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that contains a CDO token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + color: green; +} +p { + color: red; +} +p { + color: orange; + --a: green; + --b: crimson; + --a: var(--b) <!--; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-25-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-25-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-25-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-25.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-25.html new file mode 100644 index 0000000..64d1997 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-25.html
@@ -0,0 +1,25 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that contains a CDC token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + color: green; +} +p { + color: red; +} +p { + color: orange; + --a: green; + --b: crimson; + --a: --> var(--b); + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-26-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-26-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-26-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-26.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-26.html new file mode 100644 index 0000000..79ff10d --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-26.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that contains only a white space token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --a: ; + color: var(--a) green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-28-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-28-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-28-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-28.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-28.html new file mode 100644 index 0000000..f6f78911 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-28.html
@@ -0,0 +1,21 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable with invalid syntax due to having no tokens.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --a: green; + --a:; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-29-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-29-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-29-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-29.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-29.html new file mode 100644 index 0000000..a8847f5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-29.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable with a valid custom property name "--".</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --: green; + color: var(--,crimson); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-30-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-30-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-30-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-30.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-30.html new file mode 100644 index 0000000..e354abb --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-30.html
@@ -0,0 +1,21 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that contains a variable reference to itself.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#cycles"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --a: crimson; + --a: var(--a); + color: var(--a,green); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-31-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-31-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-31-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-31.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-31.html new file mode 100644 index 0000000..4a24bf2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-31.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable where the variable name begins with a digit.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --0: green; + color: var(--\30); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-32-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-32-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-32-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-32.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-32.html new file mode 100644 index 0000000..d11478e --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-32.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable where the variable name begins with an escaped digit.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --\30: green; + color: var(--\30); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-33-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-33-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-33-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-33.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-33.html new file mode 100644 index 0000000..521db857 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-33.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable where the variable name begins with an escaped letter.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --\61: green; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-34-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-34-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-34-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-34.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-34.html new file mode 100644 index 0000000..c6b4d42d --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-34.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable where the variable name begins with a lone surrogate.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --\d800: green; + color: var(--\fffd); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-35-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-35-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-35-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-35.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-35.html new file mode 100644 index 0000000..f128906 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-35.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable where the variable name begins with U+FFFD.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --\fffd: green; + color: var(--\fffd); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-36-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-36-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-36-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-36.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-36.html new file mode 100644 index 0000000..1f984fe --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-36.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable where the variable name begins with an out-of-range Unicode character escape.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --\ffffff: green; + color: var(--\fffd); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-37-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-37-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-37-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-37.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-37.html new file mode 100644 index 0000000..bd4b1c0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-37.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable consisting of a variable reference where white space surrounds the comma separating the variable name and fallback.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --a: var(--b , ); + color: var(--a) green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-38-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-38-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-38-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-38.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-38.html new file mode 100644 index 0000000..ece8cf8f --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-38.html
@@ -0,0 +1,21 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring two variables in the same declaration block that differ only in case, with lowercase first.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --a: green; + --A: crimson; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-39-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-39-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-39-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-39.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-39.html new file mode 100644 index 0000000..d1caabb --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-39.html
@@ -0,0 +1,21 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring two variables in the same declaration block that differ only in case, with uppercase first.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --A: green; + --a: crimson; + color: var(--A); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-40-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-40-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-40-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-40.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-40.html new file mode 100644 index 0000000..62a4e21 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-40.html
@@ -0,0 +1,21 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable with an invalid custom property name due to it beginning with "VAR-".</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --a: green; + VAR-a: crimson; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-41-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-41-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-41-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-41.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-41.html new file mode 100644 index 0000000..c1c585b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-41.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable where the second '-' in the "--" prefix of the custom property name is escaped.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + -\2d a: green; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-42-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-42-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-42-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-42.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-42.html new file mode 100644 index 0000000..1a60ba2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-42.html
@@ -0,0 +1,21 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable where the custom property name includes an unescaped Chinese character and an escape that is terminated by a space character.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<meta charset=utf-8> +<style> +p { + color: red; +} +p { + color: orange; + --a-é•¿-name-that-might-be-longer-than-you\27 d-normally-use: green; + color: var(--a-é•¿-name-that-might-be-longer-than-you\27 d-normally-use); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-43-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-43-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-43-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-43.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-43.html new file mode 100644 index 0000000..73aaef2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-43.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable whose value is "initial".</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --a: initial; + color: var(--a,green); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-44-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-44-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-44-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-44.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-44.html new file mode 100644 index 0000000..f2a968d2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-44.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable whose value is "inherit" where there is no variable to inherit from.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --a: inherit; + color: var(--a,green); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-45-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-45-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-45-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-45.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-45.html new file mode 100644 index 0000000..a5003d9a --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-45.html
@@ -0,0 +1,24 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable whose value is "inherit" where there is a variable to inherit from.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + --a: green; + color: crimson; +} +p { + color: red; +} +p { + color: orange; + --a: inherit; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-46-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-46-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-46-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-46.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-46.html new file mode 100644 index 0000000..c846b1c --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-46.html
@@ -0,0 +1,23 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable whose value is "initial" where there is a variable to inherit from.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + --a: crimson; +} +p { + color: red; +} +p { + color: orange; + --a: initial; + color: var(--a,green); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-47-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-47-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-47-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-47.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-47.html new file mode 100644 index 0000000..2f06d09 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-47.html
@@ -0,0 +1,25 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable whose value consists of a reference to a variable whose value is "inherit".</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + --b: green; + color: crimson; +} +p { + color: red; +} +p { + color: orange; + --a: var(--b); + --b: inherit; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-48-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-48-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-48-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-48.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-48.html new file mode 100644 index 0000000..9abf328 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-48.html
@@ -0,0 +1,25 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a number of variables in a cycle.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#cycles"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + color: green; +} +p { + color: crimson; + --a: red var(--b); + --b: var(--c); + --c: var(--d); + --d: var(--e); + --e: var(--a); + --f: var(--e); + color: var(--f); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-49-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-49-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-49-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-49.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-49.html new file mode 100644 index 0000000..9a4b984 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-49.html
@@ -0,0 +1,26 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that is a dependent of a variable involved in a cycle but which itself is not involved in a cycle.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#cycles"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + color: orange; +} +p { + color: crimson; + --a: red var(--b) var(--g); + --b: var(--c); + --c: var(--d); + --d: var(--e); + --e: var(--a); + --f: var(--e); + --g: green; + color: var(--g); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-50-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-50-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-50-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-50.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-50.html new file mode 100644 index 0000000..0545b00 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-50.html
@@ -0,0 +1,25 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a number of variables in a chain, where the final element of the chain uses its fallback.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#cycles"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + color: green; +} +p { + color: crimson; + --a: var(--b,red); + --b: var(--c); + --c: var(--d); + --d: var(--e); + --e: var(--a); + --f: var(--e); + color: var(--f); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-51-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-51-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-51-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-51.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-51.html new file mode 100644 index 0000000..eac0207 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-51.html
@@ -0,0 +1,24 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that consists of a reference to an invalid inherited variable.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#invalid-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + color: orange; + --c: var(--a); +} +p { + --a: var(--b); +} +p { + color: red; + --b: var(--c,green); + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-52-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-52-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-52-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-52.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-52.html new file mode 100644 index 0000000..e913e2d --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-52.html
@@ -0,0 +1,24 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that consists of a reference to an inherited variable whose value was a variable reference that used its fallback.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + color: orange; + --c: var(--a,green); +} +p { + --a: var(--b); +} +p { + color: red; + --b: var(--c,crimson); + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-53-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-53-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-53-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-53.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-53.html new file mode 100644 index 0000000..b8b6a8c --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-53.html
@@ -0,0 +1,22 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that consists of two variable references without fallback and with no intervening white space.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: green; +} +span { + color: red; + --a:var(--b)var(--c); + --b:orange; + --c:red; + color: var(--a); +} +</style> +<p><span>This text must be green.</span></p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-54-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-54-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-54-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-54.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-54.html new file mode 100644 index 0000000..8e0b39c4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-54.html
@@ -0,0 +1,21 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that consists of two variable references with the first variable reference using fallback and with no intervening white space.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: green; +} +span { + color: red; + --a:var(--b,orange)var(--c); + --c:red; + color: var(--a); +} +</style> +<p><span>This text must be green.</span></p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-55-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-55-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-55-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-55.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-55.html new file mode 100644 index 0000000..2fb68d5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-55.html
@@ -0,0 +1,21 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that consists of two variable references with the second variable reference using fallback and with no intervening white space.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: green; +} +span { + color: red; + --a:var(--b)var(--c,red); + --b:orange; + color: var(--a); +} +</style> +<p><span>This text must be green.</span></p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-56-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-56-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-56-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-56.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-56.html new file mode 100644 index 0000000..21378f89 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-56.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable whose value is "unset" where there is no variable to inherit from.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; +} +p { + color: orange; + --a: unset; + color: var(--a,green); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-57-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-57-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-57-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-57.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-57.html new file mode 100644 index 0000000..aa8d84c6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-57.html
@@ -0,0 +1,24 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable whose value is "unset" where there is a variable to inherit from.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + --a: green; + color: crimson; +} +p { + color: red; +} +p { + color: orange; + --a: unset; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-58-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-58-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-58-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-58.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-58.html new file mode 100644 index 0000000..b05f967 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-58.html
@@ -0,0 +1,25 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable whose value consists of a reference to a variable whose value is "unset".</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + --b: green; + color: crimson; +} +p { + color: red; +} +p { + color: orange; + --a: var(--b); + --b: unset; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-59-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-59-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-59-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-59.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-59.html new file mode 100644 index 0000000..2032a342 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-59.html
@@ -0,0 +1,17 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable with a trailing invalid token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: var(--a); + --a: green; + --a: red); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-60-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-60-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-60-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-60.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-60.html new file mode 100644 index 0000000..3304eb4a --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-declaration-60.html
@@ -0,0 +1,23 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<meta charset=utf-8> +<title>CSS Test: Test declaring a variable with a value whose name is "initial" but using Turkish dotted/dotless 'i's.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +div { + color: orange; + --a: green; + color: var(--a); +} +p { + --b: İnitial; + --c: ınitial; + color: var(--b,var(--c,red)); +} +</style> +<div><p>This text must be green.</p></div>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-declaration-01-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-declaration-01-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-declaration-01-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-declaration-01.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-declaration-01.html new file mode 100644 index 0000000..bae5abf --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-declaration-01.html
@@ -0,0 +1,12 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable in an external CSS file.</title> +<link rel="author" title="Mihaela Velimiroviciu" href="mailto:mihaela.velimiroviciu@softvisioninc.eu"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<link rel="stylesheet" type="text/css" href="support/external-variable-declaration.css"> + +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-font-face-01-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-font-face-01-expected.html new file mode 100644 index 0000000..3c3ba4be --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-font-face-01-expected.html
@@ -0,0 +1,11 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="stylesheet" href="../support/ahem.css" type="text/css"> +<meta name="flags" content="ahem"> +<p>This text must not be in Ahem.</p> +<p style="font-family: Ahem">But this text must be in Ahem.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-font-face-01.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-font-face-01.html new file mode 100644 index 0000000..f248418 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-font-face-01.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test the invalid declaration and use of a variable in an @font-face rule within an external CSS.</title> +<link rel="author" title="Mihaela Velimiroviciu" href="mailto:mihaela.velimiroviciu@softvisioninc.eu"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="variable-font-face-01-ref.html"> +<link rel="stylesheet" type="text/css" href="support/external-variable-font-face.css"> +<meta name="flags" content="ahem"> +<p id=a>This text must not be in Ahem.</p> +<p id=b>But this text must be in Ahem.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-reference-01-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-reference-01-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-reference-01-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-reference-01.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-reference-01.html new file mode 100644 index 0000000..ee40db762 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-reference-01.html
@@ -0,0 +1,12 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test the use of a variable in a non-custom property where the variable value is inherited within an external CSS.</title> +<link rel="author" title="Mihaela Velimiroviciu" href="mailto:mihaela.velimiroviciu@softvisioninc.eu"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="stylesheet" type="text/css" href="support/external-variable-reference.css"> +<link rel="match" href="support/color-green-ref.html"> + +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-supports-01-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-supports-01-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-supports-01-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-supports-01.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-supports-01.html new file mode 100644 index 0000000..dd3ad17 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-external-supports-01.html
@@ -0,0 +1,12 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule where the property value contains a variable reference within an external stylesheet file.</title> +<link rel="author" title="Mihaela Velimiroviciu" href="mailto:mihaela.velimiroviciu@softvisioninc.eu"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="stylesheet" type="text/css" href="support/external-variable-supports.css"> +<link rel="match" href="support/color-green-ref.html"> + +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-font-face-01-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-font-face-01-expected.html new file mode 100644 index 0000000..3c3ba4be --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-font-face-01-expected.html
@@ -0,0 +1,11 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="stylesheet" href="../support/ahem.css" type="text/css"> +<meta name="flags" content="ahem"> +<p>This text must not be in Ahem.</p> +<p style="font-family: Ahem">But this text must be in Ahem.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-font-face-01.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-font-face-01.html new file mode 100644 index 0000000..3b88b9a --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-font-face-01.html
@@ -0,0 +1,29 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test the invalid declaration and use of a variable in an @font-face rule.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="variable-font-face-01-ref.html"> +<meta name="flags" content="ahem"> +<style> +@font-face { + --a: MyTestFontName; + font-family: var(--a); + src: url(../../../resources/Ahem.ttf); +} +@font-face { + font-family: MyTestFontName2; + src: url(../../../resources/Ahem.ttf); +} +#a { + font-family: MyTestFontName; +} +#b { + font-family: MyTestFontName2; +} +</style> +<p id=a>This text must not be in Ahem.</p> +<p id=b>But this text must be in Ahem.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-font-face-02-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-font-face-02-expected.html new file mode 100644 index 0000000..3c3ba4be --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-font-face-02-expected.html
@@ -0,0 +1,11 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="stylesheet" href="../support/ahem.css" type="text/css"> +<meta name="flags" content="ahem"> +<p>This text must not be in Ahem.</p> +<p style="font-family: Ahem">But this text must be in Ahem.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-font-face-02.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-font-face-02.html new file mode 100644 index 0000000..94bd698b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-font-face-02.html
@@ -0,0 +1,31 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test the invalid use of a variable in an @font-face rule where the variable is defined on the root element.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="variable-font-face-02-ref.html"> +<meta name="flags" content="ahem"> +<style> +:root { + --a: MyTestFontName; +} +@font-face { + font-family: var(--a); + src: url(../../../resources/Ahem.ttf); +} +@font-face { + font-family: MyTestFontName2; + src: url(../../../resources/Ahem.ttf); +} +#a { + font-family: MyTestFontName; +} +#b { + font-family: MyTestFontName2; +} +</style> +<p id=a>This text must not be in Ahem.</p> +<p id=b>But this text must be in Ahem.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-01-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-01-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-01-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-01.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-01.html new file mode 100644 index 0000000..1737b2e --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-01.html
@@ -0,0 +1,18 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test the use of a variable in a non-custom property where the variable value is inherited.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +:root { + --a: green; +} +p { + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-02-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-02-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-02-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-02.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-02.html new file mode 100644 index 0000000..92e4aedc --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-02.html
@@ -0,0 +1,23 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test the use of a variable in a non-custom property where the value is invalid at computed-value time due to referencing a non-existent variable.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#invalid-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +:root { + --a: crimson; + color: red; +} +body { + color: green; +} +p { + color: orange; + color: var(--a) var(--b); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-03-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-03-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-03-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-03.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-03.html new file mode 100644 index 0000000..bd50b9a --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-03.html
@@ -0,0 +1,21 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test the use of two variables in a non-custom property where the variable values are inherited and one of the variable values consists only of white space.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +:root { + --a: green; + --b: ; + color: red; +} +p { + color: crimson; + color: var(--a) var(--b); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-04-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-04-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-04-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-04.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-04.html new file mode 100644 index 0000000..060e55c --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-04.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test the use of two variables in a non-custom property where one variable is inherited and the other references a non-existing variable with fallback that consists only of white space.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +:root { + --a: green; + color: red; +} +p { + color: crimson; + color: var(--a) var(--b, ); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-05-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-05-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-05-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-05.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-05.html new file mode 100644 index 0000000..129e19f --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-05.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test the use of a variable in a non-custom property where the values contains no tokens other than the variable reference.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + --a: green; + color: red; +} +p { + color: crimson; + color:var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-06-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-06-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-06-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-06.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-06.html new file mode 100644 index 0000000..464ce37 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-06.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property with invalid syntax due to having a variable reference whose fallback contains no tokens.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + --a: crimson; + color: red; +} +p { + color: green; + color: var(--a,); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-07-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-07-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-07-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-07.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-07.html new file mode 100644 index 0000000..d557161e --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-07.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property with invalid syntax due to having a variable reference whose fallback contains a top level ';' token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + --a: crimson; + color: red; +} +p { + color: green; + color: var(--a,;); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-08-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-08-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-08-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-08.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-08.html new file mode 100644 index 0000000..d7aa58d --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-08.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property with invalid syntax due to having a variable reference whose fallback contains a top level '!' token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + --a: crimson; + color: red; +} +p { + color: green; + color: var(--a,!); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-09-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-09-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-09-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-09.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-09.html new file mode 100644 index 0000000..f2128cf --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-09.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property with a variable reference that has a non-top level ';' token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + --a: green; + color: crimson; +} +p { + color: red; + color: var(--a,(;)); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-10-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-10-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-10-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-10.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-10.html new file mode 100644 index 0000000..7325115 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-10.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property with a variable reference that has a non-top level '!' token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + --a: green; + color: crimson; +} +p { + color: red; + color: var(--a,(!)); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-11-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-11-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-11-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-11.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-11.html new file mode 100644 index 0000000..81dec5a --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-11.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property with invalid syntax due to having a variable reference whose fallback contains nothing but a comment.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + --a: crimson; + color: red; +} +p { + color: green; + color: var(--a,/**/); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-12-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-12-expected.html new file mode 100644 index 0000000..8fcd177c --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-12-expected.html
@@ -0,0 +1,9 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<p>The words "hello there" must appear below:</p> +<p>hello there</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-12.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-12.html new file mode 100644 index 0000000..968b71e --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-12.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test the use of variable references in the 'content' property.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="variable-reference-12-ref.html"> +<style> +:root { + --a: "hello"; + --b: "there"; +} +#a:before { + content: var(--a) " " var(--b); +} +</style> +<p>The words "hello there" must appear below:</p> +<p id=a></p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-13-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-13-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-13-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-13.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-13.html new file mode 100644 index 0000000..b724998 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-13.html
@@ -0,0 +1,18 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test that important variable declarations are not overwritten by subsequent non-important variable declarations in the one declaration block.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: green !important; + --a: crimson; + color: var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-14-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-14-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-14-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-14.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-14.html new file mode 100644 index 0000000..7196f587 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-14.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test that important variable declarations cascade correctly.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +#a { + --a: green !important; +} +p { + color: red; + --a: crimson; + color: var(--a); +} +</style> +<p id=a>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-15-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-15-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-15-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-15.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-15.html new file mode 100644 index 0000000..01cd29b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-15.html
@@ -0,0 +1,21 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property with two variable references with no intervening white space.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + color: green; +} +p { + color: crimson; + --a: orange; + --b: red; + color: var(--a)var(--b); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-16-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-16-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-16-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-16.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-16.html new file mode 100644 index 0000000..f27108c --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-16.html
@@ -0,0 +1,19 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property that consists of a variable reference with a number of levels of variable reference fallbacks.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + color: red; +} +p { + color: crimson; + color: var(--a, var(--b, var(--c, green))); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-17-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-17-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-17-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-17.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-17.html new file mode 100644 index 0000000..2f677a6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-17.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property that consists of a variable reference whose fallback contains a CDO token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + color: red; +} +p { + color: crimson; + --a: green; + color: var(--a, <!--); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-18-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-18-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-18-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-18.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-18.html new file mode 100644 index 0000000..a858b2b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-18.html
@@ -0,0 +1,19 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property that contains a variable reference and balanced braces and square brackets.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + color: green; +} +p { + color: red; + color: { [ var(--a) ] }; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-19-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-19-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-19-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-19.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-19.html new file mode 100644 index 0000000..c3b0413 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-19.html
@@ -0,0 +1,19 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property that contains a variable reference and a non-top level ';' token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + color: green; +} +p { + color: red; + color: [;] var(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-20-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-20-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-20-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-20.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-20.html new file mode 100644 index 0000000..868a576 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-20.html
@@ -0,0 +1,17 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property that contains a variable reference whose function token is in uppercase.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: green; + color: VAR(--a); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-21-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-21-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-21-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-21.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-21.html new file mode 100644 index 0000000..f1ad08bd --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-21.html
@@ -0,0 +1,17 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property that contains a reference to a variable whose name must be escaped.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --0: green; + color: var(--\30); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-22-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-22-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-22-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-22.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-22.html new file mode 100644 index 0000000..a02f49a --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-22.html
@@ -0,0 +1,17 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property that contains a reference to a variable whose name is U+FFFD but which was declared and referenced using a lone surrogate.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --\d800: green; + color: var(--\d800); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-23-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-23-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-23-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-23.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-23.html new file mode 100644 index 0000000..44afd5a --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-23.html
@@ -0,0 +1,17 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property that contains a reference to a variable whose name is U+FFFD but which was declared using a lone surrogate.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --\d800: green; + color: var(--\fffd); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-24-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-24-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-24-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-24.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-24.html new file mode 100644 index 0000000..25c9c67 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-24.html
@@ -0,0 +1,17 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property that contains a reference to a variable whose name is U+FFFD but which was declared using an out-of-range Unicode character escape.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --\ffffff: green; + color: var(--\fffd); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-25-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-25-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-25-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-25.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-25.html new file mode 100644 index 0000000..4ed514c9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-25.html
@@ -0,0 +1,15 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property that contains a variable reference with no fallback and which is implicitly closed due to EOF.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: green; + color: var(--a</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-26-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-26-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-26-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-26.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-26.html new file mode 100644 index 0000000..ca3b01b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-26.html
@@ -0,0 +1,15 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property that contains a variable reference with white space before its comma and fallback consisting only of white space and which is implicitly closed due to EOF.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: green; + color: var(--a , </style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-27-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-27-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-27-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-27.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-27.html new file mode 100644 index 0000000..efd8418c --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-27.html
@@ -0,0 +1,15 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property that contains a variable reference with fallback consisting only of white space and which is implicitly closed due to EOF.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: green; + color: var(--a, </style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-28-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-28-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-28-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-28.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-28.html new file mode 100644 index 0000000..7796f1b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-28.html
@@ -0,0 +1,15 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property that contains a variable reference whose fallback is a variable reference, both of which are implicitly closed due to EOF.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: green; + color: var(--a, var(--b</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-29-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-29-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-29-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-29.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-29.html new file mode 100644 index 0000000..b01873f --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-29.html
@@ -0,0 +1,15 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property that contains a variable reference with no fallback, and whose variable name is followed by a comment, and where the comment and the variable reference are implicitly closed due to EOF.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: green; + color: var(--a /* unclosed comment</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-30-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-30-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-30-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-30.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-30.html new file mode 100644 index 0000000..9082c30 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-30.html
@@ -0,0 +1,17 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property with invalid syntax due to containing two "!important" priorities.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: green; + --a: red; + color: var(--a) !important !important; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-31-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-31-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-31-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-31.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-31.html new file mode 100644 index 0000000..bfe4677b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-31.html
@@ -0,0 +1,20 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property with a variable reference that has a digit after the "--" prefix.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + color: orange; +} +p { + color: red; + --0: green; + color: var(--0); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-32-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-32-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-32-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-32.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-32.html new file mode 100644 index 0000000..e1f5789c --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-32.html
@@ -0,0 +1,19 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property with invalid syntax due to containing a variable reference with fallback that contains a bad string.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + color: orange; +} +p { + color: green; + --a: red; + color: var(--a, " +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-33-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-33-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-33-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-33.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-33.html new file mode 100644 index 0000000..c527bcdd --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-33.html
@@ -0,0 +1,18 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property containing a variable reference with fallback is an implicitly closed string due to EOF.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + color: orange; +} +p { + color: red; + --a: green; + color: var(--a, "</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-34-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-34-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-34-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-34.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-34.html new file mode 100644 index 0000000..8cb14db --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-34.html
@@ -0,0 +1,19 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property with invalid syntax due to containing a variable reference with fallback that contains a bad URL.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + color: orange; +} +p { + color: green; + --a: red; + color: var(--a, url(" +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-35-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-35-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-35-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-35.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-35.html new file mode 100644 index 0000000..cddc466 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-35.html
@@ -0,0 +1,18 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom property containing a variable reference with fallback is an implicitly closed URL due to EOF.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { + color: orange; +} +p { + color: red; + --a: green; + color: var(--a, url("</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-36-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-36-expected.html new file mode 100644 index 0000000..3af79f7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-36-expected.html
@@ -0,0 +1,14 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + background-color: green; + color: white; +} +</style> +<p>This text must have a green background color.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-36.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-36.html new file mode 100644 index 0000000..e4f4d50 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-36.html
@@ -0,0 +1,18 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom shorthand property containing a variable reference.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#variables-in-shorthands"> +<link rel="match" href="variable-reference-36-ref.html"> +<style> +p { + background-color: red; + --a: url(nothing) green; + background: var(--a); + color: white; +} +</style> +<p>This text must have a green background color.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-37-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-37-expected.html new file mode 100644 index 0000000..3af79f7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-37-expected.html
@@ -0,0 +1,14 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + background-color: green; + color: white; +} +</style> +<p>This text must have a green background color.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-37.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-37.html new file mode 100644 index 0000000..391c553 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-37.html
@@ -0,0 +1,18 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a non-custom shorthand property containing a variable reference, with a subsequent property in the declaration block that overrides one of the shorthand's components.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#variables-in-shorthands"> +<link rel="match" href="variable-reference-37-ref.html"> +<style> +p { + --a: url(nothing) red; + background: var(--a); + background-color: green; + color: white; +} +</style> +<p>This text must have a green background color.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-38-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-38-expected.html new file mode 100644 index 0000000..8b4e262c --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-38-expected.html
@@ -0,0 +1,14 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { padding-left: 1em; } +#a { border-left: black dotted; } +#b { border-left: black solid; } +</style> +<p id=a>The left border must be dotted.</p> +<p id=b>The left border must be solid.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-38.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-38.html new file mode 100644 index 0000000..420246b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-38.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test using variables in overlapping shorthands.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#variables-in-shorthands"> +<link rel="match" href="variable-declaration-59-ref.html"> +<style> +p { padding-left: 1em; } +#a { --style: solid; --left: black dotted; border-style: var(--style); border-left: var(--left); border-top: none; border-right: none; border-bottom: none; } +#b { --style: solid; --left: black dotted; border-left: var(--left); border-style: var(--style); border-top: none; border-right: none; border-bottom: none; } +</style> +<p id=a>The left border must be dotted.</p> +<p id=b>The left border must be solid.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-39-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-39-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-39-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-39.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-39.html new file mode 100644 index 0000000..21b7fd8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-reference-39.html
@@ -0,0 +1,17 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test declaring a variable that references itself but uses fallback.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#cycles"> +<link rel="match" href="support/color-green-ref.html"> +<style> +p { + color: red; + --a: var(--a, red); + color: var(--a, green); +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-01-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-01-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-01-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-01.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-01.html new file mode 100644 index 0000000..1b78726 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-01.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule where the property value contains a variable reference and no white space tokens.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color:var(--a)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-02-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-02-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-02-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-02.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-02.html new file mode 100644 index 0000000..2b74a468 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-02.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule where the property value contains a white space token followed by a variable reference.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-03-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-03-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-03-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-03.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-03.html new file mode 100644 index 0000000..8d19666 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-03.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule where the property value contains a variable reference surrounded by white space tokens.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a) ) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-04-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-04-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-04-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-04.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-04.html new file mode 100644 index 0000000..f8b0458e --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-04.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule where the property value contains a variable reference surrounded by white space tokens and with white space surrounding the variable name.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var( --a ) ) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-05-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-05-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-05-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-05.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-05.html new file mode 100644 index 0000000..08a7e749 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-05.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a failing non-custom property declaration in an @supports rule where the property value contains a syntactically invalid variable reference due to having no fallback tokens.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a)) and (not (color: var(--a,))) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-06-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-06-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-06-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-06.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-06.html new file mode 100644 index 0000000..d83f60055 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-06.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule where the property value contains a variable reference with fallback that is only white space.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a, )) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-07-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-07-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-07-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-07.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-07.html new file mode 100644 index 0000000..d3bcc22 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-07.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a failing non-custom property declaration in an @supports rule where the property value contains a syntactically invalid variable reference due to having no fallback tokens, just a comment.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a)) and (not (color: var(--a,/**/))) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-08-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-08-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-08-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-08.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-08.html new file mode 100644 index 0000000..637bfb8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-08.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule where the property value contains a comment and an identifier.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a,/**/a)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-09-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-09-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-09-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-09.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-09.html new file mode 100644 index 0000000..f82e860 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-09.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a failing non-custom property declaration in an @supports rule where the property value contains a syntactically invalid variable reference due to having a '!' token at the top level of its fallback.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a)) and (not (color: var(--a,!))) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-10-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-10-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-10-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-10.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-10.html new file mode 100644 index 0000000..c8d7747 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-10.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a failing non-custom property declaration in an @supports rule where the property value contains a syntactically invalid variable reference due to having "!important" at the top level of its fallback.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a)) and (not (color: var(--a,!important))) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-11-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-11-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-11-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-11.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-11.html new file mode 100644 index 0000000..835d06b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-11.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing 'color' property declaration in an @supports rule with a variable reference that comes after a non-color value.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: 1px var(--a)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-12-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-12-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-12-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-12.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-12.html new file mode 100644 index 0000000..594e78e --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-12.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing 'color' property declaration in an @supports rule with a variable reference that comes before a non-color value.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a) 1px) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-13-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-13-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-13-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-13.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-13.html new file mode 100644 index 0000000..d6e8a68 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-13.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing 'color' property declaration in an @supports rule with a range of different tokens and a variable reference not at the top level.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: something 3px url(whereever) calc(var(--a) + 1px)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-14-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-14-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-14-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-14.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-14.html new file mode 100644 index 0000000..831ee1b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-14.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule with a variable reference and an "!important" priority.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a) !important) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-15-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-15-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-15-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-15.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-15.html new file mode 100644 index 0000000..205c86d --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-15.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule with two adjacent variable references with no intervening white space.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a)var(--b)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-16-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-16-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-16-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-16.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-16.html new file mode 100644 index 0000000..102d2c1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-16.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule with a variable reference that has a number of levels of variable reference fallbacks.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a, var(--b, var(--c, black)))) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-17-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-17-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-17-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-17.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-17.html new file mode 100644 index 0000000..88f7d4c --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-17.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a failing non-custom property declaration in an @supports rule with two "!important" priorities.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a)) and (not (color: var(--a) !important !important)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-18-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-18-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-18-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-18.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-18.html new file mode 100644 index 0000000..81423b4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-18.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule whose value contains a variable reference and a CDO token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a) <!--) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-19-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-19-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-19-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-19.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-19.html new file mode 100644 index 0000000..df90399 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-19.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule whose value contains a variable reference and a CDC token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: --> var(--a)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-20-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-20-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-20-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-20.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-20.html new file mode 100644 index 0000000..2673b380 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-20.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule whose value contains a variable reference and balanced braces and square brackets.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: { [ var(--a) ] }) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-21-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-21-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-21-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-21.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-21.html new file mode 100644 index 0000000..67010c2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-21.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a failing non-custom property declaration in an @supports rule where the property value contains a syntactically invalid variable reference due to having a ';' token at the top level of its fallback.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a)) and (not (color: var(--a,;))) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-22-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-22-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-22-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-22.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-22.html new file mode 100644 index 0000000..38d1edc --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-22.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule whose value contains a variable reference and a non-top level ';' token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: [;] var(--a)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-23-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-23-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-23-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-23.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-23.html new file mode 100644 index 0000000..6ab9421 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-23.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a failing non-custom property declaration in an @supports rule whose value contains a variable reference with a top level ';' token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a)) and (not (color: var(--a);)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-24-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-24-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-24-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-24.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-24.html new file mode 100644 index 0000000..18488cd --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-24.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule whose value contains a variable reference with a non-top level ';' token in its fallback.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a,(;))) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-25-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-25-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-25-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-25.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-25.html new file mode 100644 index 0000000..7ba0aaf --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-25.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule whose value contains a variable reference whose function token is in uppercase.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: VAR(--a)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-26-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-26-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-26-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-26.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-26.html new file mode 100644 index 0000000..b49df519 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-26.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule whose value contains a variable reference with a digit after the "--" variable name prefix.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--0)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-27-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-27-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-27-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-27.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-27.html new file mode 100644 index 0000000..be67b4d --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-27.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule whose value contains a variable reference with a variable name beginning with an escaped digit.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--\30)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-28-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-28-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-28-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-28.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-28.html new file mode 100644 index 0000000..2ccd2b3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-28.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule whose value contains a variable reference with a U+FFFD variable name specified by an escaped lone surrogate.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--\d800)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-29-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-29-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-29-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-29.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-29.html new file mode 100644 index 0000000..193cb55 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-29.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule whose value contains a variable reference with a U+FFFD variable name specified by an out-of-range Unicode character escape.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--\ffffff)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-30-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-30-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-30-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-30.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-30.html new file mode 100644 index 0000000..937b761 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-30.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule whose value contains a variable reference with a dimension token as the variable name.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a)) and (not (color: var(1px))) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-31-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-31-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-31-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-31.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-31.html new file mode 100644 index 0000000..d6dec7b8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-31.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom property declaration in an @supports rule whose value contains a variable reference with white space surrounding the fallback comma.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (color: var(--a , )) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-32-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-32-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-32-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-32.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-32.html new file mode 100644 index 0000000..1cc391d --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-32.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing non-custom shorthand property declaration in an @supports rule whose value contains a variable reference.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (background: var(--a)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-33-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-33-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-33-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-33.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-33.html new file mode 100644 index 0000000..f26eec23 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-33.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains a variable reference.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a:var(--b)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-34-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-34-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-34-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-34.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-34.html new file mode 100644 index 0000000..aac50bf --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-34.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains white space and a variable reference.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: var(--b)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-35-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-35-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-35-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-35.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-35.html new file mode 100644 index 0000000..5966803 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-35.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains a variable reference surrounded by white space.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: var(--b) ) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-36-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-36-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-36-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-36.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-36.html new file mode 100644 index 0000000..14d5bc9e --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-36.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains a variable reference surrounded by white space with the variable name also surrounded by white space.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: var( --b ) ) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-37-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-37-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-37-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-37.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-37.html new file mode 100644 index 0000000..828fb2f --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-37.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a failing custom property declaration in an @supports rule whose value contains a variable reference with no fallback tokens.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: a) and (not (--a: var(--b,))) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-38-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-38-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-38-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-38.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-38.html new file mode 100644 index 0000000..97e019e --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-38.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains a variable reference with fallback consisting only of white space.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: var(--b, )) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-39-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-39-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-39-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-39.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-39.html new file mode 100644 index 0000000..d67ac48 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-39.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a failing custom property declaration in an @supports rule whose value contains a variable reference with no fallback tokens, just a comment.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: a) and (not (--a: var(--b,/**/))) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-40-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-40-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-40-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-40.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-40.html new file mode 100644 index 0000000..91fd83c --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-40.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains a variable reference with fallback consisting of a comment and an identifier.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: var(--b,/**/a)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-41-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-41-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-41-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-41.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-41.html new file mode 100644 index 0000000..aff08cd2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-41.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a failing custom property declaration in an @supports rule whose value contains a variable reference with fallback containing a top level '!' token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: a) and (not (--a: var(--b,!))) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-42-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-42-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-42-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-42.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-42.html new file mode 100644 index 0000000..ae90e57 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-42.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a failing custom property declaration in an @supports rule whose value contains a variable reference with fallback containing a top level "!important".</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: a) and (not (--a: var(--b,!important))) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-43-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-43-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-43-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-43.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-43.html new file mode 100644 index 0000000..b5f176d0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-43.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains a dimension followed by a variable reference.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: 1px var(--b)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-44-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-44-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-44-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-44.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-44.html new file mode 100644 index 0000000..4c18960 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-44.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains a variable reference followed bya dimension.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: var(--b) 1px) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-45-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-45-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-45-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-45.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-45.html new file mode 100644 index 0000000..24b1eec --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-45.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains a selection of tokens and a non-top level variable reference.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: something 3px url(whereever) calc(var(--b) + 1px)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-46-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-46-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-46-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-46.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-46.html new file mode 100644 index 0000000..c9d3f5b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-46.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains a variable reference and an "!important" priority.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: var(--b) !important) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-47-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-47-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-47-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-47.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-47.html new file mode 100644 index 0000000..946963f --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-47.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains two adjacent variable references with no intervening white space.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: var(--b)var(--b)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-48-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-48-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-48-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-48.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-48.html new file mode 100644 index 0000000..7ab0c84 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-48.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains a variable reference with a number of levels of variable reference fallbacks.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: var(--b, var(--c, var(--d, black)))) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-49-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-49-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-49-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-49.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-49.html new file mode 100644 index 0000000..aa500b9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-49.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a failing custom property declaration in an @supports rule whose value contains two "!important" priorities.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: a) and (not (--a: var(--b) !important !important)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-50-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-50-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-50-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-50.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-50.html new file mode 100644 index 0000000..c2185c9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-50.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains a variable reference and a CDO token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: var(--b) <!--) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-51-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-51-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-51-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-51.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-51.html new file mode 100644 index 0000000..0aa6d43 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-51.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains a variable reference and a CDC token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: --> var(--b)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-52-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-52-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-52-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-52.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-52.html new file mode 100644 index 0000000..9cc7d214 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-52.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains a variable reference and balanced braces and square brackets.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: { [ var(--b) ] }) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-53-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-53-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-53-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-53.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-53.html new file mode 100644 index 0000000..a40c2ff --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-53.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a failing custom property declaration in an @supports rule whose value contains a variable reference with a top level ';' token in its fallback.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: a) and (not (--a: var(--b,;))) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-54-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-54-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-54-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-54.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-54.html new file mode 100644 index 0000000..b6009e1f --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-54.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains a variable reference and a non-top level ';' token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: [;] var(--b)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-55-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-55-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-55-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-55.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-55.html new file mode 100644 index 0000000..f4b92a2f --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-55.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a failing custom property declaration in an @supports rule whose value contains a variable reference and a top level ';' token in its fallback.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: a) and (not (--a: var(--b);)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-56-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-56-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-56-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-56.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-56.html new file mode 100644 index 0000000..07b188f7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-56.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains only a white space token.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: ) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-57-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-57-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-57-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-57.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-57.html new file mode 100644 index 0000000..5cb8b336 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-57.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a failing custom property declaration in an @supports rule whose value contains no tokens.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: a) and (not (--a:)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-58-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-58-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-58-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-58.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-58.html new file mode 100644 index 0000000..5eb41b4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-58.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing property declaration in an @supports rule with property name "--".</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--: a) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-59-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-59-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-59-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-59.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-59.html new file mode 100644 index 0000000..16669e6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-59.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value contains a variable reference to itself.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#cycles"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a:var(--a)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-60-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-60-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-60-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-60.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-60.html new file mode 100644 index 0000000..438d23f --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-60.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule for a variable whose name is a digit.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--0: a) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-61-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-61-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-61-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-61.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-61.html new file mode 100644 index 0000000..62f9683d4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-61.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule for a variable whose name is a digit which is specified with an escape.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--\61: a) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-62-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-62-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-62-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-62.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-62.html new file mode 100644 index 0000000..39c55b2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-62.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule for a variable whose name is U+FFFD which is specified with an escaped lone surrogate.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--\d800: a) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-63-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-63-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-63-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-63.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-63.html new file mode 100644 index 0000000..7423583 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-63.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule for a variable whose name is U+FFFD which is specified with an out-of-range Unicode character escape.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--\ffffff: a) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-64-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-64-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-64-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-64.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-64.html new file mode 100644 index 0000000..2b3eadf --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-64.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a failing custom property declaration in an @supports rule whose value is a variable reference with a dimension token as the variable name.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: a) and (not (--a: var(1px))) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-65-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-65-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-65-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-65.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-65.html new file mode 100644 index 0000000..4bc9c4e --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-65.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a passing custom property declaration in an @supports rule whose value is a variable reference with white space surrounding the fallback comma.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#syntax"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: var(--b , )) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-66-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-66-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-66-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-66.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-66.html new file mode 100644 index 0000000..a38b044 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-66.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a failing custom property declaration in an @supports rule where the property name begins with "VAR-".</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: a) and (not (VAR-a: a)) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-67-expected.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-67-expected.html new file mode 100644 index 0000000..0eabe58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-67-expected.html
@@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Reftest Reference</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<style> +p { + color: green; +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-67.html b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-67.html new file mode 100644 index 0000000..9425e21 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/gecko/variables/variable-supports-67.html
@@ -0,0 +1,16 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE html> +<title>CSS Test: Test a declaration for a custom property has an invalid value does not cause the @supports rule to fail to parse.</title> +<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"> +<link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables"> +<link rel="match" href="support/color-green-ref.html"> +<style> +body { color: red; } +@supports (--a: !) or (--a: a) { + p { color: green; } +} +</style> +<p>This text must be green.</p>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-aggregated-details-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-aggregated-details-expected.txt new file mode 100644 index 0000000..5f39859 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-aggregated-details-expected.txt
@@ -0,0 +1,321 @@ + +CallTree Group by: None + a: 0.000 8.380 + b: 7.125 8.380 + c: 0.351 0.351 + e: 0.000 0.905 + g: 0.905 0.905 + x: 0.000 1.513 + y: 1.113 1.513 + z: 0.000 0.200 + w: 0.200 0.200 + w: 0.200 0.200 + f: 0.000 0.833 + l: 0.000 0.833 + a: 0.733 0.833 + Layout: 0.100 0.100 + recursive_a: 0.101 0.215 + recursive_b: 0.102 0.114 + recursive_a: 0.004 0.012 + recursive_b: 0.008 0.008 + +BottomUp Group by: None + b: 7.125 8.380 + a: 7.125 8.380 + y: 1.113 1.513 + x: 1.113 1.513 + g: 0.905 0.905 + e: 0.905 0.905 + b: 0.905 0.905 + a: 0.905 0.905 + a: 0.733 9.213 + l: 0.733 0.833 + f: 0.733 0.833 + w: 0.400 0.400 + z: 0.200 0.200 + y: 0.200 0.200 + x: 0.200 0.200 + y: 0.200 0.200 + x: 0.200 0.200 + c: 0.351 0.351 + b: 0.351 0.351 + a: 0.351 0.351 + recursive_b: 0.110 0.114 + recursive_a: 0.110 0.114 + recursive_b: 0.008 0.008 + recursive_a: 0.008 0.008 + recursive_a: 0.105 0.215 + recursive_b: 0.004 0.012 + recursive_a: 0.004 0.012 + Layout: 0.100 0.100 + a: 0.100 0.100 + l: 0.100 0.100 + f: 0.100 0.100 + +CallTree Group by: Category + Scripting: 0.101 10.941 + a: 0.000 8.380 + b: 7.125 8.380 + c: 0.351 0.351 + e: 0.000 0.905 + g: 0.905 0.905 + f: 0.000 0.833 + l: 0.000 0.833 + a: 0.733 0.833 + Layout: 0.100 0.100 + x: 0.000 1.513 + y: 1.113 1.513 + z: 0.000 0.200 + w: 0.200 0.200 + w: 0.200 0.200 + recursive_a: 0.101 0.215 + recursive_b: 0.102 0.114 + recursive_a: 0.004 0.012 + recursive_b: 0.008 0.008 + +BottomUp Group by: Category + Scripting: 10.841 10.841 + a: 0.733 9.213 + l: 0.733 0.833 + f: 0.733 0.833 + b: 7.125 8.380 + a: 7.125 8.380 + c: 0.351 0.351 + b: 0.351 0.351 + a: 0.351 0.351 + e: 0.000 0.905 + b: 0.000 0.905 + a: 0.000 0.905 + g: 0.905 0.905 + e: 0.905 0.905 + b: 0.905 0.905 + a: 0.905 0.905 + f: 0.000 0.833 + l: 0.000 0.833 + f: 0.000 0.833 + x: 0.000 1.513 + y: 1.113 1.513 + x: 1.113 1.513 + z: 0.000 0.200 + y: 0.000 0.200 + x: 0.000 0.200 + w: 0.400 0.400 + z: 0.200 0.200 + y: 0.200 0.200 + x: 0.200 0.200 + y: 0.200 0.200 + x: 0.200 0.200 + recursive_a: 0.105 0.215 + recursive_b: 0.004 0.012 + recursive_a: 0.004 0.012 + recursive_b: 0.110 0.114 + recursive_a: 0.110 0.114 + recursive_b: 0.008 0.008 + recursive_a: 0.008 0.008 + Rendering: 0.100 0.100 + Layout: 0.100 0.100 + a: 0.100 0.100 + l: 0.100 0.100 + f: 0.100 0.100 + +CallTree Group by: Domain + unattributed: 0.000 10.726 + a: 0.000 8.380 + b: 7.125 8.380 + c: 0.351 0.351 + e: 0.000 0.905 + g: 0.905 0.905 + f: 0.000 0.833 + l: 0.000 0.833 + a: 0.733 0.833 + Layout: 0.100 0.100 + x: 0.000 1.513 + y: 1.113 1.513 + z: 0.000 0.200 + w: 0.200 0.200 + w: 0.200 0.200 + abc.com: 0.101 0.215 + recursive_a: 0.101 0.215 + recursive_b: 0.102 0.114 + recursive_a: 0.004 0.012 + recursive_b: 0.008 0.008 + +BottomUp Group by: Domain + unattributed: 10.726 10.726 + a: 0.733 9.213 + l: 0.733 0.833 + f: 0.733 0.833 + b: 7.125 8.380 + a: 7.125 8.380 + c: 0.351 0.351 + b: 0.351 0.351 + a: 0.351 0.351 + e: 0.000 0.905 + b: 0.000 0.905 + a: 0.000 0.905 + g: 0.905 0.905 + e: 0.905 0.905 + b: 0.905 0.905 + a: 0.905 0.905 + f: 0.000 0.833 + l: 0.000 0.833 + f: 0.000 0.833 + Layout: 0.100 0.100 + a: 0.100 0.100 + l: 0.100 0.100 + f: 0.100 0.100 + x: 0.000 1.513 + y: 1.113 1.513 + x: 1.113 1.513 + z: 0.000 0.200 + y: 0.000 0.200 + x: 0.000 0.200 + w: 0.400 0.400 + z: 0.200 0.200 + y: 0.200 0.200 + x: 0.200 0.200 + y: 0.200 0.200 + x: 0.200 0.200 + abc.com: 0.215 0.215 + recursive_a: 0.105 0.215 + recursive_b: 0.004 0.012 + recursive_a: 0.004 0.012 + recursive_b: 0.110 0.114 + recursive_a: 0.110 0.114 + recursive_b: 0.008 0.008 + recursive_a: 0.008 0.008 + +CallTree Group by: Subdomain + unattributed: 0.000 10.726 + a: 0.000 8.380 + b: 7.125 8.380 + c: 0.351 0.351 + e: 0.000 0.905 + g: 0.905 0.905 + f: 0.000 0.833 + l: 0.000 0.833 + a: 0.733 0.833 + Layout: 0.100 0.100 + x: 0.000 1.513 + y: 1.113 1.513 + z: 0.000 0.200 + w: 0.200 0.200 + w: 0.200 0.200 + xyz.abc.com: 0.101 0.215 + recursive_a: 0.101 0.215 + recursive_b: 0.102 0.114 + recursive_a: 0.004 0.012 + recursive_b: 0.008 0.008 + +BottomUp Group by: Subdomain + unattributed: 10.726 10.726 + a: 0.733 9.213 + l: 0.733 0.833 + f: 0.733 0.833 + b: 7.125 8.380 + a: 7.125 8.380 + c: 0.351 0.351 + b: 0.351 0.351 + a: 0.351 0.351 + e: 0.000 0.905 + b: 0.000 0.905 + a: 0.000 0.905 + g: 0.905 0.905 + e: 0.905 0.905 + b: 0.905 0.905 + a: 0.905 0.905 + f: 0.000 0.833 + l: 0.000 0.833 + f: 0.000 0.833 + Layout: 0.100 0.100 + a: 0.100 0.100 + l: 0.100 0.100 + f: 0.100 0.100 + x: 0.000 1.513 + y: 1.113 1.513 + x: 1.113 1.513 + z: 0.000 0.200 + y: 0.000 0.200 + x: 0.000 0.200 + w: 0.400 0.400 + z: 0.200 0.200 + y: 0.200 0.200 + x: 0.200 0.200 + y: 0.200 0.200 + x: 0.200 0.200 + xyz.abc.com: 0.215 0.215 + recursive_a: 0.105 0.215 + recursive_b: 0.004 0.012 + recursive_a: 0.004 0.012 + recursive_b: 0.110 0.114 + recursive_a: 0.110 0.114 + recursive_b: 0.008 0.008 + recursive_a: 0.008 0.008 + +CallTree Group by: URL + unattributed: 0.000 10.726 + a: 0.000 8.380 + b: 7.125 8.380 + c: 0.351 0.351 + e: 0.000 0.905 + g: 0.905 0.905 + f: 0.000 0.833 + l: 0.000 0.833 + a: 0.733 0.833 + Layout: 0.100 0.100 + x: 0.000 1.513 + y: 1.113 1.513 + z: 0.000 0.200 + w: 0.200 0.200 + w: 0.200 0.200 + http://xyz.abc.com/rec.js: 0.101 0.215 + recursive_a: 0.101 0.215 + recursive_b: 0.102 0.114 + recursive_a: 0.004 0.012 + recursive_b: 0.008 0.008 + +BottomUp Group by: URL + unattributed: 10.726 10.726 + a: 0.733 9.213 + l: 0.733 0.833 + f: 0.733 0.833 + b: 7.125 8.380 + a: 7.125 8.380 + c: 0.351 0.351 + b: 0.351 0.351 + a: 0.351 0.351 + e: 0.000 0.905 + b: 0.000 0.905 + a: 0.000 0.905 + g: 0.905 0.905 + e: 0.905 0.905 + b: 0.905 0.905 + a: 0.905 0.905 + f: 0.000 0.833 + l: 0.000 0.833 + f: 0.000 0.833 + Layout: 0.100 0.100 + a: 0.100 0.100 + l: 0.100 0.100 + f: 0.100 0.100 + x: 0.000 1.513 + y: 1.113 1.513 + x: 1.113 1.513 + z: 0.000 0.200 + y: 0.000 0.200 + x: 0.000 0.200 + w: 0.400 0.400 + z: 0.200 0.200 + y: 0.200 0.200 + x: 0.200 0.200 + y: 0.200 0.200 + x: 0.200 0.200 + http://xyz.abc.com/rec.js: 0.215 0.215 + recursive_a: 0.105 0.215 + recursive_b: 0.004 0.012 + recursive_a: 0.004 0.012 + recursive_b: 0.110 0.114 + recursive_a: 0.110 0.114 + recursive_b: 0.008 0.008 + recursive_a: 0.008 0.008 +
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-aggregated-details.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-aggregated-details.html new file mode 100644 index 0000000..7a5e537 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-aggregated-details.html
@@ -0,0 +1,596 @@ +<html> +<head> +<script src="../../http/tests/inspector/inspector-test.js"></script> +<script src="../tracing-test.js"></script> +<script> + +function test() +{ + var sessionId = "6.23"; + var rawTraceEvents = [ + { + "args": { + "name": "Renderer" + }, + "cat": "__metadata", + "name": "process_name", + "ph": "M", + "pid": 17851, + "tid": 23, + "ts": 0 + }, + { + "args": { + "name": "CrRendererMain" + }, + "cat": "__metadata", + "name": "thread_name", + "ph": "M", + "pid": 17851, + "tid": 23, + "ts": 0 + }, + { + "args": { + "sessionId": sessionId + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "TracingStartedInPage", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 100000, + "tts": 606543 + }, + { + "args": {}, + "cat": "disabled-by-default-devtools.timeline", + "name": "Program", + "ph": "B", + "pid": 17851, + "tid": 23, + "ts": 200000, + "tts": 5612442 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "c", "callUID": "c", "scriptId": 1 }, + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 208000, + "tts": 1758056 + }, + { + "args": {}, + "cat": "disabled-by-default-devtools.timeline", + "name": "FunctionCall", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 210000, + "dur": 30000, + "tts": 5612442 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "c", "callUID": "c", "scriptId": 1 }, + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 211000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 212000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "c", "callUID": "c", "scriptId": 1 }, + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 219875, + "tts": 1758056 + }, + { + "args": { + "frame": "0x2f7b63884000", + "data": { + "stackTrace": [ + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "InvalidateLayout", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 220000, + "dur": 7000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "c", "callUID": "c", "scriptId": 1 }, + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 220125, + "tts": 1758056 + }, + { + "args": { + "frame": "0x2f7b63884000", + "data": { + "stackTrace": [ + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "InvalidateLayout", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 221000, + "dur": 3000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "g", "scriptId": 1 }, + { "functionName": "f", "scriptId": 1 }, + { "functionName": "b", "scriptId": 1 }, + { "functionName": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 222000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "g", "scriptId": 1 }, + { "functionName": "e", "scriptId": 1 }, + { "functionName": "b", "scriptId": 1 }, + { "functionName": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 227125, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "g", "scriptId": 1 }, + { "functionName": "e", "scriptId": 1 }, + { "functionName": "b", "scriptId": 1 }, + { "functionName": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 227250, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "a", "callUID": "a", "scriptId": 1 }, + { "functionName": "l", "callUID": "l", "scriptId": 1 }, + { "functionName": "f", "callUID": "f", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 230000, + "tts": 1758056 + }, + { + "args": { + "beginData": { + "stackTrace": [ + { "functionName": "a", "callUID": "a", "scriptId": 1 }, + { "functionName": "l", "callUID": "l", "scriptId": 1 }, + { "functionName": "f", "callUID": "f", "scriptId": 1 }, + { "functionName": "sin", "callUID": "sin", "scriptId": 2, "url": "native math.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "Layout", + "ph": "X", + "dur": 100, + "pid": 17851, + "tid": 23, + "ts": 230010, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "a", "callUID": "a", "scriptId": 1 }, + { "functionName": "l", "callUID": "l", "scriptId": 1 }, + { "functionName": "f", "callUID": "f", "scriptId": 1 }, + { "functionName": "sin", "callUID": "sin", "scriptId": 2, "url": "native math.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 230125, + "tts": 1758056 + }, + { + "args": {}, + "cat": "disabled-by-default-devtools.timeline", + "name": "FunctionCall", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 250000, + "dur": 10000 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "FunctionCall", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 251000, + "dur": 1000 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "w", "callUID": "w", "scriptId": 1 }, + { "functionName": "z", "callUID": "z", "scriptId": 1 }, + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 251000 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "w", "callUID": "w", "scriptId": 1 }, + { "functionName": "z", "callUID": "z", "scriptId": 1 }, + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 251100 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "w", "scriptId": 1 }, + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 251200 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "w", "scriptId": 1 }, + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 251300 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 251400 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_b", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, + { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, + { "functionName": "recursive_b", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, + { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253000 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, + { "functionName": "recursive_b", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, + { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253008 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_b", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, + { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253012 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253014 + }, + { + "args": { + "data": { + "stackTrace": [ + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253015 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_b", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, + { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253100 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253200 + }, + { + "args": { + "data": { + "stackTrace": [ + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253300 + }, + { + "args": {}, + "cat": "disabled-by-default-devtools.timeline", + "name": "Program", + "ph": "E", + "pid": 17851, + "tid": 23, + "ts": 500000, + "tts": 5612506 + } + ]; + + var timeline = WebInspector.panels.timeline; + timeline._model.addEventListener(WebInspector.TimelineModel.Events.RecordingStopped, timelineRecorded, this); + timeline._model.setEventsForTest(rawTraceEvents); + + function timelineRecorded() + { + timeline.requestWindowTimes(0, Infinity); + for (var grouping in WebInspector.AggregatedTimelineTreeView.GroupBy) { + var groupingValue = WebInspector.AggregatedTimelineTreeView.GroupBy[grouping]; + testProfileTree(WebInspector.TimelinePanel.DetailsTab.CallTree, groupingValue); + testProfileTree(WebInspector.TimelinePanel.DetailsTab.BottomUp, groupingValue); + } + InspectorTest.completeTest(); + } + + function testProfileTree(type, grouping) + { + InspectorTest.addResult(""); + InspectorTest.addResult(type + " Group by: " + grouping); + timeline._detailsView.selectTab(type, true); + var callTree = timeline._detailsView._rangeDetailViews.get(type); + callTree._groupByCombobox.select(callTree._groupByCombobox.options().find((x) => x.value === grouping)); + callTree._onGroupByChanged(); + var rootNode = callTree.dataGrid.rootNode(); + for (var node of rootNode.children) + printProfileTree(1, node._profileNode); + } + + function printProfileTree(padding, node) + { + var name = node.name || (node.event.name === WebInspector.TimelineModel.RecordType.JSFrame + ? WebInspector.beautifyFunctionName(node.event.args["data"]["functionName"]) + : WebInspector.TimelineUIUtils.eventTitle(node.event)); + InspectorTest.addResult(" ".repeat(padding) + name + ": " + [node.selfTime, node.totalTime].map(function (t) { return t.toFixed(3); }).join(" ")); + (node.children || new Map()).forEach(printProfileTree.bind(null, padding + 1)); + } +} + +</script> +</head> +<body onload="runTest()"> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks-expected.txt index 4fa38a05..fb9ee85 100644 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks-expected.txt
@@ -35,107 +35,3 @@ JSFrame: 253.100 / 0.200 recursive_a JSFrame: 253.100 / 0.100 recursive_b -Top-Down Chart: 0.000 40.000 - Function Call: 29.059 40.000 - a: 0.000 8.380 - b: 0.316 8.380 - c: 0.351 0.351 - a: 0.000 7.713 - b: 6.809 7.713 - e: 0.000 0.905 - g: 0.905 0.905 - f: 0.000 0.833 - l: 0.000 0.833 - a: 0.025 0.833 - f: 0.000 0.808 - l: 0.000 0.808 - a: 0.708 0.808 - Layout: 0.100 0.100 - x: 0.000 1.513 - y: 0.032 1.513 - x: 0.000 1.482 - y: 0.482 1.482 - Function Call: 0.600 1.000 - z: 0.000 0.200 - w: 0.200 0.200 - w: 0.200 0.200 - recursive_a: 0.101 0.215 - recursive_b: 0.102 0.114 - recursive_a: 0.004 0.012 - recursive_b: 0.008 0.008 -Bottom-Up Chart: 40.000 40.000 - Function Call: 29.659 40.000 - y: 0.600 1.000 - x: 0.600 1.000 - y: 0.600 1.000 - x: 0.600 1.000 - Function Call: 0.600 1.000 - a: 0.733 9.213 - Function Call: 0.000 8.380 - b: 0.000 7.713 - a: 0.000 7.713 - Function Call: 0.000 7.713 - l: 0.733 0.833 - f: 0.733 0.833 - Function Call: 0.025 0.833 - a: 0.708 0.808 - l: 0.708 0.808 - f: 0.708 0.808 - Function Call: 0.708 0.808 - b: 7.125 8.380 - a: 7.125 8.380 - Function Call: 0.316 8.380 - b: 6.809 7.713 - a: 6.809 7.713 - Function Call: 6.809 7.713 - c: 0.351 0.351 - b: 0.351 0.351 - a: 0.351 0.351 - Function Call: 0.351 0.351 - g: 0.905 0.905 - e: 0.905 0.905 - b: 0.905 0.905 - a: 0.905 0.905 - b: 0.905 0.905 - a: 0.905 0.905 - Function Call: 0.905 0.905 - Layout: 0.100 0.100 - a: 0.100 0.100 - l: 0.100 0.100 - f: 0.100 0.100 - a: 0.100 0.100 - l: 0.100 0.100 - f: 0.100 0.100 - Function Call: 0.100 0.100 - y: 0.513 1.513 - x: 0.513 1.513 - Function Call: 0.032 1.513 - y: 0.482 1.482 - x: 0.482 1.482 - Function Call: 0.482 1.482 - w: 0.400 0.400 - z: 0.200 0.200 - Function Call: 0.200 0.200 - y: 0.200 0.200 - x: 0.200 0.200 - y: 0.200 0.200 - x: 0.200 0.200 - Function Call: 0.200 0.200 - Function Call: 0.200 0.200 - y: 0.200 0.200 - x: 0.200 0.200 - y: 0.200 0.200 - x: 0.200 0.200 - Function Call: 0.200 0.200 - recursive_a: 0.105 0.215 - Function Call: 0.101 0.215 - recursive_b: 0.004 0.012 - recursive_a: 0.004 0.012 - Function Call: 0.004 0.012 - recursive_b: 0.110 0.114 - recursive_a: 0.110 0.114 - Function Call: 0.102 0.114 - recursive_b: 0.008 0.008 - recursive_a: 0.008 0.008 - Function Call: 0.008 0.008 -
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks.html index 62b3ad9..864e914 100644 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks.html +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks.html
@@ -558,26 +558,6 @@ InspectorTest.addResult(e.name + ": " + e.startTime.toFixed(3) + " / " + (e.duration.toFixed(3) || 0) + " " + (e.args.data && e.args.data.functionName || "")); }); - InspectorTest.addResult(""); - tracingTimelineModel._setMainThreadEvents(events); - var filters = [ - WebInspector.TimelineUIUtils.visibleEventsFilter(), - new WebInspector.ExcludeTopLevelFilter() - ]; - var treeTopDown = WebInspector.TimelineModel.buildTopDownTree(events, 0, Infinity, filters, WebInspector.TimelineTreeView.eventId); - printProfileTree(0, treeTopDown); - var treeBottomUp = WebInspector.TimelineModel.buildBottomUpTree(treeTopDown); - printProfileTree(0, treeBottomUp); - - function printProfileTree(padding, node) - { - var name = node.name || (node.event.name === WebInspector.TimelineModel.RecordType.JSFrame - ? WebInspector.beautifyFunctionName(node.event.args["data"]["functionName"]) - : WebInspector.TimelineUIUtils.eventTitle(node.event)); - InspectorTest.addResult(" ".repeat(padding) + name + ": " + [node.selfTime, node.totalTime].map(function (t) { return t.toFixed(3); }).join(" ")); - (node.children || new Map()).forEach(printProfileTree.bind(null, padding + 1)); - } - InspectorTest.completeTest(); }
diff --git a/third_party/WebKit/LayoutTests/media/controls-repaint-for-network-change.html b/third_party/WebKit/LayoutTests/media/controls-repaint-for-network-change.html index 6c1356c..2b31e71d 100644 --- a/third_party/WebKit/LayoutTests/media/controls-repaint-for-network-change.html +++ b/third_party/WebKit/LayoutTests/media/controls-repaint-for-network-change.html
@@ -18,12 +18,8 @@ testRunner.waitUntilDone(); var audios = document.querySelectorAll("audio"); -var src = findMediaFile("audio", "content/empty"); runAfterLayoutAndPaint(function() { - window.internals.setMediaElementNetworkState(audios[0], 0); - window.internals.setMediaElementNetworkState(audios[1], 0); - // These will cause the play buttons to become enabled, and should // also cause a repaint. window.internals.setMediaElementNetworkState(audios[1], 2);
diff --git a/third_party/WebKit/LayoutTests/mhtml/.gitattributes b/third_party/WebKit/LayoutTests/mhtml/.gitattributes new file mode 100644 index 0000000..6cefc2a --- /dev/null +++ b/third_party/WebKit/LayoutTests/mhtml/.gitattributes
@@ -0,0 +1,17 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Let's preserve original files (i.e. page_with_css_and_js.html_original +# that uses CRLF line endings), by asking git to treat them as binary. +*original* binary + +# MHTML files in general should only have CRLF line endings +# (see RFC2557, section 10). +*.mht text eol=crlf + +# While the overall structure of MHTML always uses CRLF, the MHTML parts +# that use binary encoding will preserve their original line endings +# (i.e. LF in case of the file below). We tell git to treat this file +# as "binary" to preserve this weird mixture of CRLF and LF line endings. +multi_frames_binary.mht binary +
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.png new file mode 100644 index 0000000..4bdc20d --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.txt new file mode 100644 index 0000000..89b88030 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.txt
@@ -0,0 +1,29 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x160 + LayoutBlockFlow {HTML} at (0,0) size 800x160.19 + LayoutBlockFlow (anonymous) at (0,0) size 800x20 + LayoutText {#text} at (0,0) size 37x19 + text run at (0,0) width 37: "PASS" + LayoutBlockFlow {BODY} at (8,28) size 784x116.19 + LayoutBlockFlow (anonymous) at (0,0) size 784x20 + LayoutInline {OBJECT} at (0,0) size 37x19 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 37x19 + text run at (0,0) width 37: "PASS" + LayoutText {#text} at (0,0) size 0x0 + LayoutBlockFlow (anonymous) at (0,20) size 784x40.19 + LayoutBlockFlow {OPTION} at (0,0) size 784x20.19 + LayoutBlockFlow (anonymous) at (0,20.19) size 784x20 + LayoutText {#text} at (0,0) size 37x19 + text run at (0,0) width 37: "PASS" + LayoutTable {TABLE} at (0,40.19) size 0x0 + LayoutBlockFlow (anonymous) at (0,60.19) size 784x20 + LayoutInline {OBJECT} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 37x19 + text run at (0,0) width 37: "PASS" + LayoutText {#text} at (0,0) size 0x0 + LayoutBlockFlow {P} at (0,96.19) size 784x20 + LayoutText {#text} at (0,0) size 693x19 + text run at (0,0) width 693: "crbug.com/549544: Don't clean up anonymous wrappers when the element's branch or sub-tree is being destroyed."
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.png new file mode 100644 index 0000000..4b12d004 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.txt new file mode 100644 index 0000000..080947c1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.txt
@@ -0,0 +1,29 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x150 + LayoutBlockFlow {HTML} at (0,0) size 800x150.19 + LayoutBlockFlow (anonymous) at (0,0) size 800x18 + LayoutText {#text} at (0,0) size 37x18 + text run at (0,0) width 37: "PASS" + LayoutBlockFlow {BODY} at (8,26) size 784x108.19 + LayoutBlockFlow (anonymous) at (0,0) size 784x18 + LayoutInline {OBJECT} at (0,0) size 37x18 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 37x18 + text run at (0,0) width 37: "PASS" + LayoutText {#text} at (0,0) size 0x0 + LayoutBlockFlow (anonymous) at (0,18) size 784x38.19 + LayoutBlockFlow {OPTION} at (0,0) size 784x20.19 + LayoutBlockFlow (anonymous) at (0,20.19) size 784x18 + LayoutText {#text} at (0,0) size 37x18 + text run at (0,0) width 37: "PASS" + LayoutTable {TABLE} at (0,38.19) size 0x0 + LayoutBlockFlow (anonymous) at (0,56.19) size 784x18 + LayoutInline {OBJECT} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 37x18 + text run at (0,0) width 37: "PASS" + LayoutText {#text} at (0,0) size 0x0 + LayoutBlockFlow {P} at (0,90.19) size 784x18 + LayoutText {#text} at (0,0) size 733x18 + text run at (0,0) width 733: "crbug.com/549544: Don't clean up anonymous wrappers when the element's branch or sub-tree is being destroyed."
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.png new file mode 100644 index 0000000..c5e560fb --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win-xp/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.txt new file mode 100644 index 0000000..6fa13e08 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win-xp/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.txt
@@ -0,0 +1,29 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x160 + LayoutBlockFlow {HTML} at (0,0) size 800x160.19 + LayoutBlockFlow (anonymous) at (0,0) size 800x20 + LayoutText {#text} at (0,0) size 38x19 + text run at (0,0) width 38: "PASS" + LayoutBlockFlow {BODY} at (8,28) size 784x116.19 + LayoutBlockFlow (anonymous) at (0,0) size 784x20 + LayoutInline {OBJECT} at (0,0) size 38x19 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 38x19 + text run at (0,0) width 38: "PASS" + LayoutText {#text} at (0,0) size 0x0 + LayoutBlockFlow (anonymous) at (0,20) size 784x40.19 + LayoutBlockFlow {OPTION} at (0,0) size 784x20.19 + LayoutBlockFlow (anonymous) at (0,20.19) size 784x20 + LayoutText {#text} at (0,0) size 38x19 + text run at (0,0) width 38: "PASS" + LayoutTable {TABLE} at (0,40.19) size 0x0 + LayoutBlockFlow (anonymous) at (0,60.19) size 784x20 + LayoutInline {OBJECT} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 38x19 + text run at (0,0) width 38: "PASS" + LayoutText {#text} at (0,0) size 0x0 + LayoutBlockFlow {P} at (0,96.19) size 784x20 + LayoutText {#text} at (0,0) size 693x19 + text run at (0,0) width 693: "crbug.com/549544: Don't clean up anonymous wrappers when the element's branch or sub-tree is being destroyed."
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.png new file mode 100644 index 0000000..67508fe --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.txt new file mode 100644 index 0000000..c074780cd1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/fast/block/skip-cleaning-up-anonymous-wrappers-when-subtree-being-destroyed-expected.txt
@@ -0,0 +1,29 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x150 + LayoutBlockFlow {HTML} at (0,0) size 800x150.19 + LayoutBlockFlow (anonymous) at (0,0) size 800x18 + LayoutText {#text} at (0,0) size 37x17 + text run at (0,0) width 37: "PASS" + LayoutBlockFlow {BODY} at (8,26) size 784x108.19 + LayoutBlockFlow (anonymous) at (0,0) size 784x18 + LayoutInline {OBJECT} at (0,0) size 37x17 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 37x17 + text run at (0,0) width 37: "PASS" + LayoutText {#text} at (0,0) size 0x0 + LayoutBlockFlow (anonymous) at (0,18) size 784x38.19 + LayoutBlockFlow {OPTION} at (0,0) size 784x20.19 + LayoutBlockFlow (anonymous) at (0,20.19) size 784x18 + LayoutText {#text} at (0,0) size 37x17 + text run at (0,0) width 37: "PASS" + LayoutTable {TABLE} at (0,38.19) size 0x0 + LayoutBlockFlow (anonymous) at (0,56.19) size 784x18 + LayoutInline {OBJECT} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 37x17 + text run at (0,0) width 37: "PASS" + LayoutText {#text} at (0,0) size 0x0 + LayoutBlockFlow {P} at (0,90.19) size 784x18 + LayoutText {#text} at (0,0) size 733x17 + text run at (0,0) width 733: "crbug.com/549544: Don't clean up anonymous wrappers when the element's branch or sub-tree is being destroyed."
diff --git a/third_party/WebKit/LayoutTests/virtual/threaded/fast/scroll-behavior/subframe-scrollTo-close.html b/third_party/WebKit/LayoutTests/virtual/threaded/fast/scroll-behavior/subframe-scrollTo-close.html new file mode 100644 index 0000000..450581d --- /dev/null +++ b/third_party/WebKit/LayoutTests/virtual/threaded/fast/scroll-behavior/subframe-scrollTo-close.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> +<head> +<style> + #subframe { + width: 600px; + height: 600px; + } +</style> +<script src="../../../../resources/testharness.js"></script> +<script src="../../../../resources/testharnessreport.js"></script> +<script type="text/javascript"> +var asyncHandle = async_test("Test that closing window with ongoing scrollTo animation doesn't crash"); + +if (window.testRunner) + testRunner.setCanOpenWindows(); + +var wnd = window.open("../../../../fast/scroll-behavior/resources/subframe-with-scroll.html"); + +function frameLoaded() { + window.requestAnimationFrame(() => { + wnd.close(); + window.requestAnimationFrame(() => { + asyncHandle.done(); + }); + }); +} + +wnd.addEventListener('load', frameLoaded, false); +</script> +</head> +</html>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-timeline-detached-no-crash.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-timeline-detached-no-crash.html deleted file mode 100644 index 46e569e3..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/animation-timeline-detached-no-crash.html +++ /dev/null
@@ -1,14 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> - -<script> -test(function() { - var doc = document.implementation.createDocument("", "", null); - doc.createElement("div").animate([], 1000); - var anim = doc.timeline.getAnimations()[0]; - doc = null; - gc(); - anim.cancel(); -}, 'Calling cancel() on an animation detached from its timeline should not crash.'); -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/time-consistent-across-frames.html b/third_party/WebKit/LayoutTests/web-animations-api/time-consistent-across-frames.html new file mode 100644 index 0000000..f72f6656 --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/time-consistent-across-frames.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> + +<iframe id=frame></iframe> + +<script> +var handle = async_test('Animation time should tick consistently across frames'); +var baseTime = document.timeline.currentTime; +var frameBaseTime = frame.contentDocument.timeline.currentTime; +setTimeout(function() { + var start = performance.now(); + while (performance.now() - start < 30); + var delta = document.timeline.currentTime - baseTime; + + var start = performance.now(); + while (performance.now() - start < 30); + var frameDelta = frame.contentDocument.timeline.currentTime - frameBaseTime; + + handle.step(() => assert_equals(Math.round(delta), Math.round(frameDelta))); + handle.done(); +}); +</script>
diff --git a/third_party/WebKit/ManualTests/svg-animateTransform-calcMode-discrete.svg b/third_party/WebKit/ManualTests/svg-animateTransform-calcMode-discrete.svg deleted file mode 100644 index f9abef8..0000000 --- a/third_party/WebKit/ManualTests/svg-animateTransform-calcMode-discrete.svg +++ /dev/null
@@ -1,6 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg"> -<text x="10" y="20">Testing calcMode="discrete" for <animateTransform>. The rect should jump by 100px at 2s.</text> -<rect y="30" width="100px" height="100px" fill="green"> - <animateTransform attributeName="transform" type="translate" from="0,0" to="100,0" calcMode="discrete" fill="freeze" dur="4s"/> -</rect> -</svg>
diff --git a/third_party/WebKit/ManualTests/textarea-after-stylesheet-link.html b/third_party/WebKit/ManualTests/textarea-after-stylesheet-link.html deleted file mode 100644 index 1b886266..0000000 --- a/third_party/WebKit/ManualTests/textarea-after-stylesheet-link.html +++ /dev/null
@@ -1,18 +0,0 @@ -<html> -<head> -<script> -if (window.layoutTestController) { - window.layoutTestController.dumpAsText(); -} -</script> -<link rel="stylesheet" /> -</head> -<body> -<p>Tests: whether <link rel="stylesheet"/> disturbs the display of text in textareas</p> -<p>Related bug: <a href = "http://bugs.webkit.org/show_bug.cgi?id=3751">3751: REGRESSION: affects Blogger, GMail & Wikipedia: empty textarea's which should have content</a></p> -<p>Success: You will see "passed" inside the texarea below</p> -<hr> -<textarea>passed</textarea> -</form> -</body> -</html> \ No newline at end of file
diff --git a/third_party/WebKit/Source/bindings/core/core.gni b/third_party/WebKit/Source/bindings/core/core.gni index b8f49cf..c7a9490 100644 --- a/third_party/WebKit/Source/bindings/core/core.gni +++ b/third_party/WebKit/Source/bindings/core/core.gni
@@ -16,8 +16,7 @@ ] core_global_constructors_generated_idl_files = [] -foreach (interface, core_global_constructors_original_interfaces) { - core_global_constructors_generated_idl_files += [ - "$blink_core_output_dir/${interface}CoreConstructors.idl" - ] +foreach(interface, core_global_constructors_original_interfaces) { + core_global_constructors_generated_idl_files += + [ "$blink_core_output_dir/${interface}CoreConstructors.idl" ] }
diff --git a/third_party/WebKit/Source/bindings/core/v8/generated.gni b/third_party/WebKit/Source/bindings/core/v8/generated.gni index d3780d46..30b30211 100644 --- a/third_party/WebKit/Source/bindings/core/v8/generated.gni +++ b/third_party/WebKit/Source/bindings/core/v8/generated.gni
@@ -8,9 +8,8 @@ bindings_core_v8_output_dir = "$bindings_output_dir/core/v8" if (is_win && is_official_build) { - bindings_core_generated_aggregate_files = [ - "$bindings_core_v8_output_dir/V8GeneratedCoreBindings.cpp", - ] + bindings_core_generated_aggregate_files = + [ "$bindings_core_v8_output_dir/V8GeneratedCoreBindings.cpp" ] } else { bindings_core_generated_aggregate_files = [ "$bindings_core_v8_output_dir/V8GeneratedCoreBindings01.cpp",
diff --git a/third_party/WebKit/Source/bindings/modules/idl.gni b/third_party/WebKit/Source/bindings/modules/idl.gni index 7a1f1ff..82308313 100644 --- a/third_party/WebKit/Source/bindings/modules/idl.gni +++ b/third_party/WebKit/Source/bindings/modules/idl.gni
@@ -8,16 +8,12 @@ # IDL file lists; see: http://www.chromium.org/developers/web-idl-interfaces -modules_definition_idl_files = - modules_dictionary_idl_files + - modules_idl_files +modules_definition_idl_files = modules_dictionary_idl_files + modules_idl_files # Static IDL files -modules_static_interface_idl_files = - modules_definition_idl_files +modules_static_interface_idl_files = modules_definition_idl_files modules_static_dependency_idl_files = - modules_dependency_idl_files + - modules_testing_dependency_idl_files + modules_dependency_idl_files + modules_testing_dependency_idl_files # Static IDL files / Generated IDL files # @@ -31,21 +27,18 @@ # Currently we keep the GYP/GN builds in sync for simplicity, but this can be # cleaned up once GYP is not used. modules_static_idl_files = - modules_static_interface_idl_files + - modules_static_dependency_idl_files + modules_static_interface_idl_files + modules_static_dependency_idl_files modules_generated_dependency_idl_files = - modules_core_global_constructors_generated_idl_files + - modules_global_constructors_generated_idl_files + modules_core_global_constructors_generated_idl_files + + modules_global_constructors_generated_idl_files # 'modules_dependency_idl_files' is already used in Source/modules, so avoid # collision modules_all_dependency_idl_files = - modules_static_dependency_idl_files + - modules_generated_dependency_idl_files + modules_static_dependency_idl_files + modules_generated_dependency_idl_files # Dependency IDL files: don't generate individual bindings, but do process # in IDL dependency computation, and count as build dependencies all_dependency_idl_files = - core_all_dependency_idl_files + - modules_all_dependency_idl_files + core_all_dependency_idl_files + modules_all_dependency_idl_files
diff --git a/third_party/WebKit/Source/bindings/modules/modules.gni b/third_party/WebKit/Source/bindings/modules/modules.gni index d4d75ca..19ea7d3 100644 --- a/third_party/WebKit/Source/bindings/modules/modules.gni +++ b/third_party/WebKit/Source/bindings/modules/modules.gni
@@ -22,16 +22,13 @@ ] modules_core_global_constructors_generated_idl_files = [] -foreach (interface, modules_core_global_constructors_original_interfaces) { - modules_core_global_constructors_generated_idl_files += [ - "$blink_modules_output_dir/${interface}CoreConstructors.idl" - ] +foreach(interface, modules_core_global_constructors_original_interfaces) { + modules_core_global_constructors_generated_idl_files += + [ "$blink_modules_output_dir/${interface}CoreConstructors.idl" ] } modules_global_constructors_generated_idl_files = [] -foreach (interface, modules_global_constructors_original_interfaces) { - modules_global_constructors_generated_idl_files += [ - "$blink_modules_output_dir/${interface}ModulesConstructors.idl" - ] +foreach(interface, modules_global_constructors_original_interfaces) { + modules_global_constructors_generated_idl_files += + [ "$blink_modules_output_dir/${interface}ModulesConstructors.idl" ] } -
diff --git a/third_party/WebKit/Source/bindings/modules/v8/custom/custom.gni b/third_party/WebKit/Source/bindings/modules/v8/custom/custom.gni index 07cece0b..1c7cc60 100644 --- a/third_party/WebKit/Source/bindings/modules/v8/custom/custom.gni +++ b/third_party/WebKit/Source/bindings/modules/v8/custom/custom.gni
@@ -3,10 +3,10 @@ # found in the LICENSE file. # Make the files absolute so they can be imported to anywhere. -bindings_modules_v8_custom_files = get_path_info( - [ - "V8CustomSQLStatementErrorCallback.cpp", - "V8DeviceMotionEventCustom.cpp", - "V8ServiceWorkerMessageEventCustom.cpp", - ], - "abspath") +bindings_modules_v8_custom_files = + get_path_info([ + "V8CustomSQLStatementErrorCallback.cpp", + "V8DeviceMotionEventCustom.cpp", + "V8ServiceWorkerMessageEventCustom.cpp", + ], + "abspath")
diff --git a/third_party/WebKit/Source/bindings/modules/v8/generated.gni b/third_party/WebKit/Source/bindings/modules/v8/generated.gni index 4b754cc8..4c6b667 100644 --- a/third_party/WebKit/Source/bindings/modules/v8/generated.gni +++ b/third_party/WebKit/Source/bindings/modules/v8/generated.gni
@@ -8,9 +8,8 @@ bindings_modules_v8_output_dir = "$bindings_output_dir/modules/v8" if (is_win && is_official_build) { - bindings_modules_generated_aggregate_files = [ - "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings.cpp", - ] + bindings_modules_generated_aggregate_files = + [ "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings.cpp" ] } else { bindings_modules_generated_aggregate_files = [ "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings01.cpp", @@ -35,12 +34,11 @@ ] } -bindings_modules_generated_partial_aggregate_files = [ - "$bindings_modules_v8_output_dir/V8GeneratedModulesBindingsPartial.cpp", -] +bindings_modules_generated_partial_aggregate_files = + [ "$bindings_modules_v8_output_dir/V8GeneratedModulesBindingsPartial.cpp" ] bindings_modules_generated_init_partial_interfaces_file = - "$bindings_modules_v8_output_dir/initPartialInterfacesInModules.cpp" + "$bindings_modules_v8_output_dir/initPartialInterfacesInModules.cpp" bindings_modules_generated_union_type_files = [ "$bindings_modules_v8_output_dir/UnionTypesModules.cpp",
diff --git a/third_party/WebKit/Source/bindings/modules/v8/v8.gni b/third_party/WebKit/Source/bindings/modules/v8/v8.gni index 7df3325..1d8f7df 100644 --- a/third_party/WebKit/Source/bindings/modules/v8/v8.gni +++ b/third_party/WebKit/Source/bindings/modules/v8/v8.gni
@@ -5,25 +5,22 @@ import("custom/custom.gni") # Make the files absolute so they can be imported to anywhere. -bindings_modules_v8_files = get_path_info( - [ - "DictionaryHelperForModules.cpp", - "ModuleBindingsInitializer.cpp", - "ModuleBindingsInitializer.h", - "ScriptValueSerializerForModules.cpp", - "ScriptValueSerializerForModules.h", - "SerializedScriptValueForModulesFactory.cpp", - "SerializedScriptValueForModulesFactory.h", - "ToV8ForModules.h", - "V8BindingForModules.cpp", - "V8BindingForModules.h", - "WebGLAny.cpp", - "WebGLAny.h", - ], - "abspath") + bindings_modules_v8_custom_files +bindings_modules_v8_files = + get_path_info([ + "DictionaryHelperForModules.cpp", + "ModuleBindingsInitializer.cpp", + "ModuleBindingsInitializer.h", + "ScriptValueSerializerForModules.cpp", + "ScriptValueSerializerForModules.h", + "SerializedScriptValueForModulesFactory.cpp", + "SerializedScriptValueForModulesFactory.h", + "ToV8ForModules.h", + "V8BindingForModules.cpp", + "V8BindingForModules.h", + "WebGLAny.cpp", + "WebGLAny.h", + ], + "abspath") + bindings_modules_v8_custom_files -bindings_modules_v8_unittest_files = get_path_info( - [ - "V8BindingForModulesTest.cpp", - ], - "abspath") +bindings_modules_v8_unittest_files = + get_path_info([ "V8BindingForModulesTest.cpp" ], "abspath")
diff --git a/third_party/WebKit/Source/bindings/scripts/scripts.gni b/third_party/WebKit/Source/bindings/scripts/scripts.gni index ab5b6127..7022af29 100644 --- a/third_party/WebKit/Source/bindings/scripts/scripts.gni +++ b/third_party/WebKit/Source/bindings/scripts/scripts.gni
@@ -10,12 +10,13 @@ bindings_scripts_output_dir = "$root_gen_dir/blink/bindings/scripts" # Replacing <(DEPTH) with "/" makes paths like "<(DEPTH)/foo" absolute. -_gypi = exec_script( - "//build/gypi_to_gn.py", - [ rebase_path("scripts.gypi"), - "--replace=<(DEPTH)=/" ], - "scope", - [ "scripts.gypi" ]) +_gypi = exec_script("//build/gypi_to_gn.py", + [ + rebase_path("scripts.gypi"), + "--replace=<(DEPTH)=/", + ], + "scope", + [ "scripts.gypi" ]) jinja_module_files = get_path_info(_gypi.jinja_module_files, "abspath") idl_lexer_parser_files = get_path_info(_gypi.idl_lexer_parser_files, "abspath") @@ -47,9 +48,9 @@ write_file(file_list, rebase_path(invoker.sources_static, root_build_dir)) inputs = [ - "$bindings_scripts_dir/utilities.py", - file_list, - ] + invoker.sources_static + invoker.sources_generated + "$bindings_scripts_dir/utilities.py", + file_list, + ] + invoker.sources_static + invoker.sources_generated outputs = [ invoker.interfaces_info_file, @@ -57,20 +58,19 @@ ] args = [ - "--cache-directory", - rebase_path(bindings_scripts_output_dir, root_build_dir), - "--idl-files-list", rebase_path(file_list, root_build_dir), - "--interfaces-info-file", - rebase_path(invoker.interfaces_info_file, root_build_dir), - "--component-info-file", - rebase_path(invoker.component_info_file, root_build_dir), - "--write-file-only-if-changed=1", - "--", - ] + rebase_path(invoker.sources_generated, root_build_dir) + "--cache-directory", + rebase_path(bindings_scripts_output_dir, root_build_dir), + "--idl-files-list", + rebase_path(file_list, root_build_dir), + "--interfaces-info-file", + rebase_path(invoker.interfaces_info_file, root_build_dir), + "--component-info-file", + rebase_path(invoker.component_info_file, root_build_dir), + "--write-file-only-if-changed=1", + "--", + ] + rebase_path(invoker.sources_generated, root_build_dir) - deps = [ - "//third_party/WebKit/Source/bindings/scripts:cached_lex_yacc_tables", - ] + invoker.deps + deps = [ "//third_party/WebKit/Source/bindings/scripts:cached_lex_yacc_tables" ] + invoker.deps } } @@ -85,16 +85,17 @@ # Write the file list to a unique temp file to avoid blowing out the # command line length limit. idl_files_list = "$target_gen_dir/${target_name}_file_list.tmp" - write_file(idl_files_list, - rebase_path(invoker.sources, root_build_dir)) + write_file(idl_files_list, rebase_path(invoker.sources, root_build_dir)) inputs = [ - "//third_party/WebKit/Source/bindings/scripts/utilities.py", - idl_files_list, - ] + invoker.sources + "//third_party/WebKit/Source/bindings/scripts/utilities.py", + idl_files_list, + ] + invoker.sources output_file = "$root_gen_dir/blink/" + invoker.output_file - outputs = [ output_file ] + outputs = [ + output_file, + ] script = "//third_party/WebKit/Source/bindings/scripts/generate_event_interfaces.py" args = [ @@ -106,7 +107,10 @@ ] if (defined(invoker.suffix)) { - args += [ "--suffix", invoker.suffix ] + args += [ + "--suffix", + invoker.suffix, + ] } } } @@ -128,20 +132,20 @@ # really expressible in GN now). script = "//third_party/WebKit/Source/bindings/scripts/idl_compiler.py" - inputs = - idl_lexer_parser_files + # to be explicit (covered by parsetab) - idl_compiler_files + inputs = idl_lexer_parser_files + idl_compiler_files # to be explicit (covered by parsetab) inputs += [ "$bindings_scripts_output_dir/lextab.py", "$bindings_scripts_output_dir/parsetab.pickle", "$bindings_scripts_output_dir/cached_jinja_templates.stamp", "$bindings_dir/IDLExtendedAttributes.txt", + # If the dependency structure or public interface info (e.g., # [ImplementedAs]) changes, we rebuild all files, since we're not # computing dependencies file-by-file in the build. # This data is generally stable. "$bindings_modules_output_dir/InterfacesInfoOverall.pickle", ] + # Further, if any dependency (partial interface or implemented # interface) changes, rebuild everything, since every IDL potentially # depends on them, because we're not computing dependencies @@ -172,6 +176,7 @@ public_deps = [ "//third_party/WebKit/Source/bindings/core:core_global_constructors_idls", + # FIXME: should be interfaces_info_core (w/o modules) # http://crbug.com/358074 "//third_party/WebKit/Source/bindings/modules:interfaces_info", @@ -200,9 +205,7 @@ idl_files_list = "$target_gen_dir/${target_name}_file_list.tmp" write_file(idl_files_list, rebase_path(invoker.sources, root_build_dir)) - inputs = - idl_lexer_parser_files + # to be explicit (covered by parsetab) - idl_compiler_files + inputs = idl_lexer_parser_files + idl_compiler_files # to be explicit (covered by parsetab) inputs += [ "$bindings_scripts_output_dir/lextab.py", "$bindings_scripts_output_dir/parsetab.pickle", @@ -276,20 +279,22 @@ # template("compute_global_objects") { action(target_name) { - script = "//third_party/WebKit/Source/bindings/scripts/compute_global_objects.py" + script = + "//third_party/WebKit/Source/bindings/scripts/compute_global_objects.py" # Write the file list to a unique temp file to avoid blowing out the # command line length limit. idl_files_list = "$target_gen_dir/${target_name}_file_list.tmp" - write_file(idl_files_list, - rebase_path(invoker.sources, root_build_dir)) + write_file(idl_files_list, rebase_path(invoker.sources, root_build_dir)) inputs = [ - "//third_party/WebKit/Source/bindings/scripts/utilities.py", - idl_files_list, - ] + invoker.sources_generated + invoker.sources + "//third_party/WebKit/Source/bindings/scripts/utilities.py", + idl_files_list, + ] + invoker.sources_generated + invoker.sources - outputs = [ invoker.output_file ] + outputs = [ + invoker.output_file, + ] args = [ "--idl-files-list", @@ -321,14 +326,13 @@ # Write the file list to a unique temp file to avoid blowing out the # command line length limit. idl_files_list = "$target_gen_dir/${target_name}_file_list.tmp" - write_file(idl_files_list, - rebase_path(invoker.sources, root_build_dir)) + write_file(idl_files_list, rebase_path(invoker.sources, root_build_dir)) inputs = [ - "//third_party/WebKit/Source/bindings/scripts/utilities.py", - idl_files_list, - invoker.global_objects_file, - ] + invoker.sources + "//third_party/WebKit/Source/bindings/scripts/utilities.py", + idl_files_list, + invoker.global_objects_file, + ] + invoker.sources args = [ "--idl-files-list", @@ -350,13 +354,11 @@ output_idl_file = "$output_dir/${interface}${component}Constructors.idl" args += [ rebase_path(output_idl_file, root_build_dir) ] output_idl_files += [ output_idl_file ] - output_header_files += [ - "$output_dir/${interface}${component}Constructors.h" - ] + output_header_files += + [ "$output_dir/${interface}${component}Constructors.h" ] } outputs = output_idl_files + output_header_files deps = invoker.deps } } -
diff --git a/third_party/WebKit/Source/bindings/templates/templates.gni b/third_party/WebKit/Source/bindings/templates/templates.gni index 2914bb7..b5a336c 100644 --- a/third_party/WebKit/Source/bindings/templates/templates.gni +++ b/third_party/WebKit/Source/bindings/templates/templates.gni
@@ -3,26 +3,24 @@ # found in the LICENSE file. # Paths should be absolute so this file can be imported from anywhere. -code_generator_template_files = - get_path_info( - [ - "attributes.cpp", - "callback_interface.cpp", - "callback_interface.h", - "constants.cpp", - "conversions.cpp", - "copyright_block.txt", - "dictionary_impl.cpp", - "dictionary_impl.h", - "dictionary_v8.cpp", - "dictionary_v8.h", - "interface_base.cpp", - "interface.cpp", - "interface.h", - "methods.cpp", - "partial_interface.cpp", - "partial_interface.h", - "union.cpp", - "union.h", - ], - "abspath") +code_generator_template_files = get_path_info([ + "attributes.cpp", + "callback_interface.cpp", + "callback_interface.h", + "constants.cpp", + "conversions.cpp", + "copyright_block.txt", + "dictionary_impl.cpp", + "dictionary_impl.h", + "dictionary_v8.cpp", + "dictionary_v8.h", + "interface_base.cpp", + "interface.cpp", + "interface.h", + "methods.cpp", + "partial_interface.cpp", + "partial_interface.h", + "union.cpp", + "union.h", + ], + "abspath")
diff --git a/third_party/WebKit/Source/build/scripts/css_properties.py b/third_party/WebKit/Source/build/scripts/css_properties.py index 2f4ae99..a79fa7016 100755 --- a/third_party/WebKit/Source/build/scripts/css_properties.py +++ b/third_party/WebKit/Source/build/scripts/css_properties.py
@@ -52,8 +52,8 @@ self._aliases = [property for property in properties if property['alias_for']] properties = [property for property in properties if not property['alias_for']] - # We currently assign 0 to CSSPropertyInvalid - self._first_enum_value = 1 + # We currently assign 0 to CSSPropertyInvalid, and 1 to CSSPropertyVariable + self._first_enum_value = 2 # StylePropertyMetadata additionally assumes there are under 1024 properties. assert self._first_enum_value + len(properties) < 512, 'Property aliasing expects there are under 512 properties.'
diff --git a/third_party/WebKit/Source/build/scripts/make_css_property_names.py b/third_party/WebKit/Source/build/scripts/make_css_property_names.py index e733c25dd..5049e092 100755 --- a/third_party/WebKit/Source/build/scripts/make_css_property_names.py +++ b/third_party/WebKit/Source/build/scripts/make_css_property_names.py
@@ -28,6 +28,7 @@ enum CSSPropertyID { CSSPropertyInvalid = 0, + CSSPropertyVariable = 1, %(property_enums)s }; @@ -44,7 +45,7 @@ inline CSSPropertyID convertToCSSPropertyID(int value) { - ASSERT((value >= firstCSSProperty && value <= lastCSSProperty) || value == CSSPropertyInvalid); + ASSERT((value >= firstCSSProperty && value <= lastCSSProperty) || value == CSSPropertyInvalid || value == CSSPropertyVariable); return static_cast<CSSPropertyID>(value); }
diff --git a/third_party/WebKit/Source/build/scripts/scripts.gni b/third_party/WebKit/Source/build/scripts/scripts.gni index 8712ca83..3b55d14 100644 --- a/third_party/WebKit/Source/build/scripts/scripts.gni +++ b/third_party/WebKit/Source/build/scripts/scripts.gni
@@ -22,37 +22,39 @@ "$_scripts_dir/templates/macros.tmpl", ] -css_properties_files = scripts_for_in_files + [ - "$_scripts_dir/css_properties.py", -] +css_properties_files = + scripts_for_in_files + [ "$_scripts_dir/css_properties.py" ] make_event_factory_files = scripts_for_in_files + [ - "$_scripts_dir/make_event_factory.py", - "$_scripts_dir/templates/EventFactory.cpp.tmpl", -] + "$_scripts_dir/make_event_factory.py", + "$_scripts_dir/templates/EventFactory.cpp.tmpl", + ] make_names_files = scripts_for_in_files + [ - "$_scripts_dir/make_names.py", - "$_scripts_dir/templates/MakeNames.cpp.tmpl", - "$_scripts_dir/templates/MakeNames.h.tmpl", -] + "$_scripts_dir/make_names.py", + "$_scripts_dir/templates/MakeNames.cpp.tmpl", + "$_scripts_dir/templates/MakeNames.h.tmpl", + ] -make_qualified_names_files = scripts_for_in_files + [ - "$_scripts_dir/make_qualified_names.py", - "$_scripts_dir/templates/MakeQualifiedNames.cpp.tmpl", - "$_scripts_dir/templates/MakeQualifiedNames.h.tmpl", -] +make_qualified_names_files = + scripts_for_in_files + [ + "$_scripts_dir/make_qualified_names.py", + "$_scripts_dir/templates/MakeQualifiedNames.cpp.tmpl", + "$_scripts_dir/templates/MakeQualifiedNames.h.tmpl", + ] -make_element_factory_files = make_qualified_names_files + [ - "$_scripts_dir/make_element_factory.py", - "$_scripts_dir/templates/ElementFactory.cpp.tmpl", - "$_scripts_dir/templates/ElementFactory.h.tmpl", -] +make_element_factory_files = + make_qualified_names_files + [ + "$_scripts_dir/make_element_factory.py", + "$_scripts_dir/templates/ElementFactory.cpp.tmpl", + "$_scripts_dir/templates/ElementFactory.h.tmpl", + ] -make_element_type_helpers_files = make_qualified_names_files + [ - "$_scripts_dir/make_element_type_helpers.py", - "$_scripts_dir/templates/ElementTypeHelpers.h.tmpl", -] +make_element_type_helpers_files = + make_qualified_names_files + [ + "$_scripts_dir/make_element_type_helpers.py", + "$_scripts_dir/templates/ElementTypeHelpers.h.tmpl", + ] # The executables are relative to the build directory. Don't rebase it because # on Posix we want to run the system one on the path. @@ -106,8 +108,9 @@ output_dir = get_path_info(outputs[0], "dir") args = rebase_path(invoker.in_files, root_build_dir) + [ - "--output_dir", rebase_path(output_dir, root_build_dir), - ] + "--output_dir", + rebase_path(output_dir, root_build_dir), + ] if (defined(invoker.other_args)) { args += invoker.other_args } @@ -125,13 +128,14 @@ template("css_properties") { process_in_files(target_name) { script = invoker.script - in_files = ["css/CSSProperties.in"] + in_files = [ "css/CSSProperties.in" ] other_inputs = css_properties_files if (defined(invoker.other_inputs)) { other_inputs += invoker.other_inputs } other_args = [ - "--gperf", gperf_exe, + "--gperf", + gperf_exe, ] outputs = invoker.outputs } @@ -192,7 +196,9 @@ script = "//third_party/WebKit/Source/build/scripts/make_token_matcher.py" inputs = scripts_for_in_files + [ invoker.input_file ] - outputs = [ invoker.output_file ] + outputs = [ + invoker.output_file, + ] args = [ rebase_path(invoker.input_file, root_build_dir),
diff --git a/third_party/WebKit/Source/build/scripts/templates/StyleBuilder.cpp.tmpl b/third_party/WebKit/Source/build/scripts/templates/StyleBuilder.cpp.tmpl index 537baf0..6e7582a 100644 --- a/third_party/WebKit/Source/build/scripts/templates/StyleBuilder.cpp.tmpl +++ b/third_party/WebKit/Source/build/scripts/templates/StyleBuilder.cpp.tmpl
@@ -29,6 +29,10 @@ return; {% endfor %} + case CSSPropertyVariable: + ASSERT(!isInitial && !isInherit); + StyleBuilderFunctions::applyValueCSSPropertyVariable(state, value); + return; {% for property_id, property in properties.items() if property.direction_aware %} case {{property_id}}: {% endfor %}
diff --git a/third_party/WebKit/Source/build/scripts/templates/StyleBuilderFunctions.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/StyleBuilderFunctions.h.tmpl index 2d94fd0..9a26b55 100644 --- a/third_party/WebKit/Source/build/scripts/templates/StyleBuilderFunctions.h.tmpl +++ b/third_party/WebKit/Source/build/scripts/templates/StyleBuilderFunctions.h.tmpl
@@ -21,6 +21,8 @@ static void applyValue{{property_id}}(StyleResolverState&, CSSValue*); {% endfor %} + + static void applyValueCSSPropertyVariable(StyleResolverState&, CSSValue*); }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/Init.cpp b/third_party/WebKit/Source/core/Init.cpp index 02fe099..187002f 100644 --- a/third_party/WebKit/Source/core/Init.cpp +++ b/third_party/WebKit/Source/core/Init.cpp
@@ -101,6 +101,7 @@ StringImpl::reserveStaticStringsCapacityForSize(coreStaticStringsCount + StringImpl::allStaticStrings().size()); QualifiedName::initAndReserveCapacityForSize(qualifiedNamesCount); + AtomicString::reserveTableCapacity(coreStaticStringsCount); HTMLNames::init(); SVGNames::init();
diff --git a/third_party/WebKit/Source/core/animation/AngleSVGInterpolation.h b/third_party/WebKit/Source/core/animation/AngleSVGInterpolation.h deleted file mode 100644 index f55fd05f..0000000 --- a/third_party/WebKit/Source/core/animation/AngleSVGInterpolation.h +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2015 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 AngleSVGInterpolation_h -#define AngleSVGInterpolation_h - -#include "core/animation/SVGInterpolation.h" -#include "core/svg/SVGAngle.h" - -namespace blink { - -class SVGInteger; - -class AngleSVGInterpolation : public SVGInterpolation { -public: - static PassRefPtr<AngleSVGInterpolation> create(SVGPropertyBase* start, SVGPropertyBase* end, PassRefPtrWillBeRawPtr<SVGAnimatedPropertyBase> attribute) - { - return adoptRef(new AngleSVGInterpolation(toInterpolableValue(start), toInterpolableValue(end), attribute)); - } - - static bool canCreateFrom(SVGPropertyBase* value) - { - return toSVGAngle(value)->orientType()->enumValue() == SVGMarkerOrientAngle; - } - - PassRefPtrWillBeRawPtr<SVGPropertyBase> interpolatedValue(SVGElement&) const final - { - return fromInterpolableValue(m_cachedValue.get()); - } - -private: - AngleSVGInterpolation(PassOwnPtr<InterpolableValue> start, PassOwnPtr<InterpolableValue> end, PassRefPtrWillBeRawPtr<SVGAnimatedPropertyBase> attribute) - : SVGInterpolation(start, end, attribute) - { - } - - static PassOwnPtr<InterpolableValue> toInterpolableValue(SVGPropertyBase* value) - { - return InterpolableNumber::create(toSVGAngle(value)->value()); - } - - static PassRefPtrWillBeRawPtr<SVGAngle> fromInterpolableValue(InterpolableValue* value) - { - double doubleValue = toInterpolableNumber(value)->value(); - RefPtrWillBeRawPtr<SVGAngle> result = SVGAngle::create(); - result->newValueSpecifiedUnits(SVGAngle::SVG_ANGLETYPE_DEG, doubleValue); - return result.release(); - } -}; - -} - -#endif // AngleSVGInterpolation_h
diff --git a/third_party/WebKit/Source/core/animation/AnimationStackTest.cpp b/third_party/WebKit/Source/core/animation/AnimationStackTest.cpp index 791b440d..bb2bb9e 100644 --- a/third_party/WebKit/Source/core/animation/AnimationStackTest.cpp +++ b/third_party/WebKit/Source/core/animation/AnimationStackTest.cpp
@@ -11,6 +11,7 @@ #include "core/animation/KeyframeEffectModel.h" #include "core/animation/LegacyStyleInterpolation.h" #include "core/animation/animatable/AnimatableDouble.h" +#include "core/testing/DummyPageHolder.h" #include <gtest/gtest.h> namespace blink { @@ -19,7 +20,8 @@ protected: virtual void SetUp() { - document = Document::create(); + pageHolder = DummyPageHolder::create(); + document = &pageHolder->document(); document->animationClock().resetTimeForTesting(); timeline = AnimationTimeline::create(document.get()); element = document->createElement("foo", ASSERT_NO_EXCEPTION); @@ -35,7 +37,7 @@ void updateTimeline(double time) { - document->animationClock().updateTime(time); + document->animationClock().updateTime(document->timeline().zeroTime() + time); timeline->serviceAnimations(TimingUpdateForAnimationFrame); } @@ -77,6 +79,7 @@ return toLegacyStyleInterpolation(interpolation).currentValue().get(); } + OwnPtr<DummyPageHolder> pageHolder; RefPtrWillBePersistent<Document> document; Persistent<AnimationTimeline> timeline; RefPtrWillBePersistent<Element> element;
diff --git a/third_party/WebKit/Source/core/animation/AnimationTest.cpp b/third_party/WebKit/Source/core/animation/AnimationTest.cpp index 61beaff..78db28e 100644 --- a/third_party/WebKit/Source/core/animation/AnimationTest.cpp +++ b/third_party/WebKit/Source/core/animation/AnimationTest.cpp
@@ -38,6 +38,7 @@ #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" #include "core/dom/QualifiedName.h" +#include "core/testing/DummyPageHolder.h" #include "platform/weborigin/KURL.h" #include <gtest/gtest.h> @@ -53,9 +54,11 @@ void setUpWithoutStartingTimeline() { - document = Document::create(); + pageHolder = DummyPageHolder::create(); + document = &pageHolder->document(); document->animationClock().resetTimeForTesting(); timeline = AnimationTimeline::create(document.get()); + timeline->resetForTesting(); animation = timeline->play(0); animation->setStartTime(0); animation->setEffect(makeAnimation()); @@ -86,6 +89,7 @@ Persistent<AnimationTimeline> timeline; Persistent<Animation> animation; TrackExceptionState exceptionState; + OwnPtr<DummyPageHolder> pageHolder; }; TEST_F(AnimationAnimationTest, InitialState) @@ -183,26 +187,6 @@ EXPECT_EQ(10, animation->currentTimeInternal()); } -TEST_F(AnimationAnimationTest, SetCurrentTimeBeforeTimelineStarted) -{ - setUpWithoutStartingTimeline(); - animation->setCurrentTimeInternal(5); - EXPECT_EQ(5, animation->currentTimeInternal()); - startTimeline(); - simulateFrame(10); - EXPECT_EQ(15, animation->currentTimeInternal()); -} - -TEST_F(AnimationAnimationTest, SetCurrentTimePastContentEndBeforeTimelineStarted) -{ - setUpWithoutStartingTimeline(); - animation->setCurrentTime(250 * 1000); - EXPECT_EQ(250, animation->currentTimeInternal()); - startTimeline(); - simulateFrame(10); - EXPECT_EQ(250, animation->currentTimeInternal()); -} - TEST_F(AnimationAnimationTest, SetCurrentTimeMax) { animation->setCurrentTimeInternal(std::numeric_limits<double>::max()); @@ -320,21 +304,6 @@ EXPECT_EQ(20, animation->currentTimeInternal()); } -TEST_F(AnimationAnimationTest, PauseBeforeTimelineStarted) -{ - setUpWithoutStartingTimeline(); - animation->pause(); - EXPECT_TRUE(animation->paused()); - animation->play(); - EXPECT_FALSE(animation->paused()); - - animation->pause(); - startTimeline(); - simulateFrame(100); - EXPECT_TRUE(animation->paused()); - EXPECT_EQ(0, animation->currentTimeInternal()); -} - TEST_F(AnimationAnimationTest, PlayRewindsToStart) { animation->setCurrentTimeInternal(30); @@ -555,17 +524,6 @@ EXPECT_EQ(20, animation->currentTimeInternal()); } -TEST_F(AnimationAnimationTest, SetPlaybackRateBeforeTimelineStarted) -{ - setUpWithoutStartingTimeline(); - animation->setPlaybackRate(2); - EXPECT_EQ(2, animation->playbackRate()); - EXPECT_EQ(0, animation->currentTimeInternal()); - startTimeline(); - simulateFrame(10); - EXPECT_EQ(20, animation->currentTimeInternal()); -} - TEST_F(AnimationAnimationTest, SetPlaybackRateWhilePaused) { simulateFrame(10);
diff --git a/third_party/WebKit/Source/core/animation/AnimationTimeline.cpp b/third_party/WebKit/Source/core/animation/AnimationTimeline.cpp index eace5445..14882ee5 100644 --- a/third_party/WebKit/Source/core/animation/AnimationTimeline.cpp +++ b/third_party/WebKit/Source/core/animation/AnimationTimeline.cpp
@@ -89,6 +89,11 @@ { } +bool AnimationTimeline::isActive() +{ + return m_document && m_document->page(); +} + void AnimationTimeline::animationAttached(Animation& animation) { ASSERT(animation.timeline() == this); @@ -145,7 +150,7 @@ } ASSERT(m_outdatedAnimationCount == 0); - ASSERT(m_lastCurrentTimeInternal == currentTimeInternal()); + ASSERT(m_lastCurrentTimeInternal == currentTimeInternal() || (std::isnan(currentTimeInternal()) && std::isnan(m_lastCurrentTimeInternal))); #if ENABLE(ASSERT) for (const auto& animation : m_animationsNeedingUpdate) @@ -176,11 +181,6 @@ m_timer.startOneShot(duration, BLINK_FROM_HERE); } -void AnimationTimeline::AnimationTimelineTiming::cancelWake() -{ - m_timer.stop(); -} - void AnimationTimeline::AnimationTimelineTiming::serviceOnNextFrame() { if (m_timeline->m_document && m_timeline->m_document->view()) @@ -202,6 +202,14 @@ return m_zeroTime; } +void AnimationTimeline::resetForTesting() +{ + m_zeroTime = 0; + m_zeroTimeInitialized = true; + m_playbackRate = 1; + m_lastCurrentTimeInternal = 0; +} + double AnimationTimeline::currentTime(bool& isNull) { return currentTimeInternal(isNull) * 1000; @@ -209,7 +217,7 @@ double AnimationTimeline::currentTimeInternal(bool& isNull) { - if (!m_document) { + if (!isActive()) { isNull = true; return std::numeric_limits<double>::quiet_NaN(); } @@ -238,7 +246,7 @@ void AnimationTimeline::setCurrentTimeInternal(double currentTime) { - if (!document()) + if (!isActive()) return; m_zeroTime = m_playbackRate == 0 ? currentTime @@ -273,6 +281,9 @@ if (currentTimeInternal() == m_lastCurrentTimeInternal) return false; + if (std::isnan(currentTimeInternal()) && std::isnan(m_lastCurrentTimeInternal)) + return false; + // We allow m_lastCurrentTimeInternal to advance here when there // are no animations to allow animations spawned during style // recalc to not invalidate this flag. @@ -293,13 +304,13 @@ ASSERT(animation->outdated()); m_outdatedAnimationCount++; m_animationsNeedingUpdate.add(animation); - if (m_document && m_document->page() && !m_document->page()->animator().isServicingAnimations()) + if (isActive() && !m_document->page()->animator().isServicingAnimations()) m_timing->serviceOnNextFrame(); } void AnimationTimeline::setPlaybackRate(double playbackRate) { - if (!document()) + if (!isActive()) return; double currentTime = currentTimeInternal(); m_playbackRate = playbackRate;
diff --git a/third_party/WebKit/Source/core/animation/AnimationTimeline.h b/third_party/WebKit/Source/core/animation/AnimationTimeline.h index b88901f..ef6cb95 100644 --- a/third_party/WebKit/Source/core/animation/AnimationTimeline.h +++ b/third_party/WebKit/Source/core/animation/AnimationTimeline.h
@@ -55,7 +55,6 @@ public: // Calls AnimationTimeline's wake() method after duration seconds. virtual void wakeAfter(double duration) = 0; - virtual void cancelWake() = 0; virtual void serviceOnNextFrame() = 0; virtual ~PlatformTiming() { } DEFINE_INLINE_VIRTUAL_TRACE() { } @@ -72,6 +71,7 @@ void animationAttached(Animation&); + bool isActive(); bool hasPendingUpdates() const { return !m_animationsNeedingUpdate.isEmpty(); } double zeroTime(); double currentTime(bool& isNull); @@ -99,6 +99,7 @@ void detachFromDocument(); #endif void wake(); + void resetForTesting(); DECLARE_TRACE(); @@ -135,7 +136,6 @@ } void wakeAfter(double duration) override; - void cancelWake() override; void serviceOnNextFrame() override; void timerFired(Timer<AnimationTimelineTiming>*) { m_timeline->wake(); }
diff --git a/third_party/WebKit/Source/core/animation/AnimationTimelineTest.cpp b/third_party/WebKit/Source/core/animation/AnimationTimelineTest.cpp index 03cb2ee7..79447c5 100644 --- a/third_party/WebKit/Source/core/animation/AnimationTimelineTest.cpp +++ b/third_party/WebKit/Source/core/animation/AnimationTimelineTest.cpp
@@ -38,6 +38,7 @@ #include "core/dom/Document.h" #include "core/dom/Element.h" #include "core/dom/QualifiedName.h" +#include "core/testing/DummyPageHolder.h" #include "platform/weborigin/KURL.h" #include <gmock/gmock.h> @@ -49,21 +50,8 @@ public: MOCK_METHOD1(wakeAfter, void(double)); - MOCK_METHOD0(cancelWake, void()); MOCK_METHOD0(serviceOnNextFrame, void()); - /** - * AnimationTimelines should do one of the following things after servicing animations: - * - cancel the timer and not request to be woken again (expectNoMoreActions) - * - cancel the timer and request to be woken on the next frame (expectNextFrameAction) - * - cancel the timer and request to be woken at some point in the future (expectDelayedAction) - */ - - void expectNoMoreActions() - { - EXPECT_CALL(*this, cancelWake()); - } - DEFINE_INLINE_TRACE() { AnimationTimeline::PlatformTiming::trace(visitor); @@ -74,11 +62,13 @@ protected: virtual void SetUp() { - document = Document::create(); + pageHolder = DummyPageHolder::create(); + document = &pageHolder->document(); document->animationClock().resetTimeForTesting(); element = Element::create(QualifiedName::null() , document.get()); platformTiming = new MockPlatformTiming; timeline = AnimationTimeline::create(document.get(), platformTiming); + timeline->resetForTesting(); ASSERT_EQ(0, timeline->currentTimeInternal()); } @@ -100,6 +90,7 @@ timeline->scheduleNextService(); } + OwnPtr<DummyPageHolder> pageHolder; RefPtrWillBePersistent<Document> document; RefPtrWillBePersistent<Element> element; Persistent<AnimationTimeline> timeline; @@ -117,11 +108,6 @@ } }; -TEST_F(AnimationAnimationTimelineTest, HasStarted) -{ - timeline = AnimationTimeline::create(document.get()); -} - TEST_F(AnimationAnimationTimelineTest, EmptyKeyframeAnimation) { AnimatableValueKeyframeEffectModel* effect = AnimatableValueKeyframeEffectModel::create(AnimatableValueKeyframeVector()); @@ -129,12 +115,10 @@ timeline->play(keyframeEffect); - platformTiming->expectNoMoreActions(); updateClockAndService(0); EXPECT_FLOAT_EQ(0, timeline->currentTimeInternal()); EXPECT_FALSE(keyframeEffect->isInEffect()); - platformTiming->expectNoMoreActions(); updateClockAndService(100); EXPECT_FLOAT_EQ(100, timeline->currentTimeInternal()); } @@ -147,19 +131,16 @@ timeline->play(keyframeEffect); - platformTiming->expectNoMoreActions(); updateClockAndService(0); EXPECT_FLOAT_EQ(0, timeline->currentTimeInternal()); EXPECT_TRUE(keyframeEffect->isInEffect()); - platformTiming->expectNoMoreActions(); updateClockAndService(100); EXPECT_FLOAT_EQ(100, timeline->currentTimeInternal()); } TEST_F(AnimationAnimationTimelineTest, ZeroTime) { - timeline = AnimationTimeline::create(document.get()); bool isNull; document->animationClock().updateTime(100); @@ -175,7 +156,6 @@ TEST_F(AnimationAnimationTimelineTest, PlaybackRateNormal) { - timeline = AnimationTimeline::create(document.get()); double zeroTime = timeline->zeroTime(); bool isNull; @@ -196,7 +176,6 @@ TEST_F(AnimationAnimationTimelineTest, PlaybackRatePause) { - timeline = AnimationTimeline::create(document.get()); bool isNull; document->animationClock().updateTime(100); @@ -224,7 +203,6 @@ TEST_F(AnimationAnimationTimelineTest, PlaybackRateSlow) { - timeline = AnimationTimeline::create(document.get()); bool isNull; document->animationClock().updateTime(100); @@ -252,7 +230,6 @@ TEST_F(AnimationAnimationTimelineTest, PlaybackRateFast) { - timeline = AnimationTimeline::create(document.get()); bool isNull; document->animationClock().updateTime(100); @@ -280,7 +257,6 @@ TEST_F(AnimationAnimationTimelineTest, SetCurrentTime) { - timeline = AnimationTimeline::create(document.get()); double zeroTime = timeline->zeroTime(); document->animationClock().updateTime(100);
diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp b/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp index adfb395..11f0af7 100644 --- a/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp +++ b/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp
@@ -44,6 +44,7 @@ #include "core/animation/animatable/AnimatableValueTestHelper.h" #include "core/dom/Document.h" #include "core/layout/LayoutObject.h" +#include "core/testing/DummyPageHolder.h" #include "platform/geometry/FloatBox.h" #include "platform/geometry/IntSize.h" #include "platform/graphics/filters/FilterOperations.h" @@ -83,6 +84,7 @@ RefPtrWillBePersistent<Document> m_document; RefPtrWillBePersistent<Element> m_element; Persistent<AnimationTimeline> m_timeline; + OwnPtr<DummyPageHolder> m_pageHolder; virtual void SetUp() { @@ -105,9 +107,11 @@ m_keyframeVector5 = createCompositableFloatKeyframeVector(5); m_keyframeAnimationEffect5 = AnimatableValueKeyframeEffectModel::create(*m_keyframeVector5); - m_document = Document::create(); + m_pageHolder = DummyPageHolder::create(); + m_document = &m_pageHolder->document(); m_document->animationClock().resetTimeForTesting(); m_timeline = AnimationTimeline::create(m_document.get()); + m_timeline->resetForTesting(); m_element = m_document->createElement("test", ASSERT_NO_EXCEPTION); }
diff --git a/third_party/WebKit/Source/core/animation/CompositorPendingAnimations.cpp b/third_party/WebKit/Source/core/animation/CompositorPendingAnimations.cpp index 376fb93d..19eb9a5 100644 --- a/third_party/WebKit/Source/core/animation/CompositorPendingAnimations.cpp +++ b/third_party/WebKit/Source/core/animation/CompositorPendingAnimations.cpp
@@ -80,7 +80,7 @@ startedSynchronizedOnCompositor = true; } - if (animation->playing() && !animation->hasStartTime()) { + if (animation->playing() && !animation->hasStartTime() && animation->timeline() && animation->timeline()->isActive()) { waitingForStartTime.append(animation.get()); } } else { @@ -142,7 +142,7 @@ animations.swap(m_waitingForCompositorAnimationStart); for (auto animation : animations) { - if (animation->hasStartTime() || animation->playStateInternal() != Animation::Pending) { + if (animation->hasStartTime() || animation->playStateInternal() != Animation::Pending || !animation->timeline() || !animation->timeline()->isActive()) { // Already started or no longer relevant. continue; }
diff --git a/third_party/WebKit/Source/core/animation/DocumentAnimations.cpp b/third_party/WebKit/Source/core/animation/DocumentAnimations.cpp index 69007fa..4ea9d74 100644 --- a/third_party/WebKit/Source/core/animation/DocumentAnimations.cpp +++ b/third_party/WebKit/Source/core/animation/DocumentAnimations.cpp
@@ -52,9 +52,8 @@ } // namespace -void DocumentAnimations::updateAnimationTimingForAnimationFrame(Document& document, double monotonicAnimationStartTime) +void DocumentAnimations::updateAnimationTimingForAnimationFrame(Document& document) { - document.animationClock().updateTime(monotonicAnimationStartTime); updateAnimationTiming(document, TimingUpdateForAnimationFrame); }
diff --git a/third_party/WebKit/Source/core/animation/DocumentAnimations.h b/third_party/WebKit/Source/core/animation/DocumentAnimations.h index 844eab3..e9da4fca 100644 --- a/third_party/WebKit/Source/core/animation/DocumentAnimations.h +++ b/third_party/WebKit/Source/core/animation/DocumentAnimations.h
@@ -40,7 +40,7 @@ class DocumentAnimations { public: - static void updateAnimationTimingForAnimationFrame(Document&, double monotonicAnimationStartTime); + static void updateAnimationTimingForAnimationFrame(Document&); static bool needsAnimationTimingUpdate(const Document&); static void updateAnimationTimingIfNeeded(Document&); static void updateCompositorAnimations(Document&);
diff --git a/third_party/WebKit/Source/core/animation/LengthSVGInterpolation.cpp b/third_party/WebKit/Source/core/animation/LengthSVGInterpolation.cpp index f5d6bd6..f051dfa0 100644 --- a/third_party/WebKit/Source/core/animation/LengthSVGInterpolation.cpp +++ b/third_party/WebKit/Source/core/animation/LengthSVGInterpolation.cpp
@@ -24,8 +24,8 @@ PassRefPtr<LengthSVGInterpolation> LengthSVGInterpolation::create(SVGPropertyBase* start, SVGPropertyBase* end, PassRefPtrWillBeRawPtr<SVGAnimatedPropertyBase> attribute) { NonInterpolableType modeData; - OwnPtr<InterpolableValue> startValue = toInterpolableValue(toSVGLength(start).get(), attribute.get(), &modeData); - OwnPtr<InterpolableValue> endValue = toInterpolableValue(toSVGLength(end).get(), attribute.get(), nullptr); + OwnPtr<InterpolableValue> startValue = toInterpolableValue(toSVGLength(start), attribute.get(), &modeData); + OwnPtr<InterpolableValue> endValue = toInterpolableValue(toSVGLength(end), attribute.get(), nullptr); return adoptRef(new LengthSVGInterpolation(startValue.release(), endValue.release(), attribute, modeData)); }
diff --git a/third_party/WebKit/Source/core/animation/StringKeyframe.cpp b/third_party/WebKit/Source/core/animation/StringKeyframe.cpp index 10d3bb3c..5e10c382 100644 --- a/third_party/WebKit/Source/core/animation/StringKeyframe.cpp +++ b/third_party/WebKit/Source/core/animation/StringKeyframe.cpp
@@ -6,7 +6,6 @@ #include "core/animation/StringKeyframe.h" #include "core/XLinkNames.h" -#include "core/animation/AngleSVGInterpolation.h" #include "core/animation/CSSColorInterpolationType.h" #include "core/animation/CSSImageInterpolationType.h" #include "core/animation/CSSImageListInterpolationType.h" @@ -319,7 +318,6 @@ || attribute == SVGNames::yChannelSelectorAttr || attribute == XLinkNames::hrefAttr) { // Use default SVGValueInterpolationType. - applicableTypes->append(new SVGValueInterpolationType(attribute)); } else if (attribute == SVGNames::orientAttr) { applicableTypes->append(new SVGAngleInterpolationType(attribute)); } else {
diff --git a/third_party/WebKit/Source/core/core.gni b/third_party/WebKit/Source/core/core.gni index d4aab00..00e40b3 100644 --- a/third_party/WebKit/Source/core/core.gni +++ b/third_party/WebKit/Source/core/core.gni
@@ -7,54 +7,57 @@ # This file is the GN version of core.gypi. We rebase most paths to be absolute # so these lists can be used by BUILD files in different directories without # worrying about the base directory. -_gypi = exec_script( - "//build/gypi_to_gn.py", - [ rebase_path("core.gypi"), - "--replace=<(SHARED_INTERMEDIATE_DIR)=$root_gen_dir", - "--replace=<(blink_core_output_dir)=$blink_core_output_dir"], - "scope", - [ "core.gypi" ]) +_gypi = + exec_script("//build/gypi_to_gn.py", + [ + rebase_path("core.gypi"), + "--replace=<(SHARED_INTERMEDIATE_DIR)=$root_gen_dir", + "--replace=<(blink_core_output_dir)=$blink_core_output_dir", + ], + "scope", + [ "core.gypi" ]) # Files for which bindings (.cpp and .h files) will be generated. core_idl_files = get_path_info(_gypi.core_idl_files, "abspath") core_idl_with_modules_dependency_files = - get_path_info(_gypi.core_idl_with_modules_dependency_files, "abspath") + get_path_info(_gypi.core_idl_with_modules_dependency_files, "abspath") core_dictionary_idl_files = - get_path_info(_gypi.core_dictionary_idl_files, "abspath") + get_path_info(_gypi.core_dictionary_idl_files, "abspath") core_testing_dictionary_idl_files = - get_path_info(_gypi.core_testing_dictionary_idl_files, "abspath") + get_path_info(_gypi.core_testing_dictionary_idl_files, "abspath") # 'partial interface', target (right side of) 'implements', and # interfaces with static bindings (in bindings/core/v8/) core_dependency_idl_files = - get_path_info(_gypi.core_dependency_idl_files, "abspath") + get_path_info(_gypi.core_dependency_idl_files, "abspath") # Interfaces that inherit from Event, including Event itself. core_event_idl_files = get_path_info(_gypi.core_event_idl_files, "abspath") # IDL files that only have typedefs/enums. core_typedefs_enums_only_idl_files = - get_path_info(_gypi.core_typedefs_enums_only_idl_files, "abspath") + get_path_info(_gypi.core_typedefs_enums_only_idl_files, "abspath") webcore_non_rendering_files = - get_path_info(_gypi.webcore_non_rendering_files, "abspath") + get_path_info(_gypi.webcore_non_rendering_files, "abspath") webcore_rendering_files = - get_path_info(_gypi.webcore_rendering_files, "abspath") + get_path_info(_gypi.webcore_rendering_files, "abspath") webcore_dom_files = get_path_info(_gypi.webcore_dom_files, "abspath") webcore_html_files = get_path_info(_gypi.webcore_html_files, "abspath") webcore_svg_files = get_path_info(_gypi.webcore_svg_files, "abspath") webcore_testing_idl_files = - get_path_info(_gypi.webcore_testing_idl_files, "abspath") + get_path_info(_gypi.webcore_testing_idl_files, "abspath") webcore_testing_idl_with_modules_dependency_files = - get_path_info(_gypi.webcore_testing_idl_with_modules_dependency_files, "abspath") + get_path_info(_gypi.webcore_testing_idl_with_modules_dependency_files, + "abspath") webcore_testing_dependency_idl_files = - get_path_info(_gypi.webcore_testing_dependency_idl_files, "abspath") + get_path_info(_gypi.webcore_testing_dependency_idl_files, "abspath") generated_core_dictionary_files = - get_path_info(_gypi.generated_core_dictionary_files, "abspath") + get_path_info(_gypi.generated_core_dictionary_files, "abspath") generated_core_testing_dictionary_files = - get_path_info(_gypi.generated_core_testing_dictionary_files, "abspath") + get_path_info(_gypi.generated_core_testing_dictionary_files, "abspath") generated_webcore_testing_idl_files = - get_path_info(_gypi.generated_webcore_testing_idl_files, "abspath") + get_path_info(_gypi.generated_webcore_testing_idl_files, "abspath") webcore_testing_files = get_path_info(_gypi.webcore_testing_files, "abspath") core_unittest_files = get_path_info(_gypi.core_unittest_files, "abspath")
diff --git a/third_party/WebKit/Source/core/core.gypi b/third_party/WebKit/Source/core/core.gypi index 63a0b8e..54e7782 100644 --- a/third_party/WebKit/Source/core/core.gypi +++ b/third_party/WebKit/Source/core/core.gypi
@@ -801,7 +801,6 @@ 'webcore_non_rendering_files': [ 'Init.cpp', 'Init.h', - 'animation/AngleSVGInterpolation.h', 'animation/KeyframeEffect.cpp', 'animation/KeyframeEffect.h', 'animation/AnimationClock.cpp', @@ -1037,6 +1036,8 @@ 'css/CSSCustomFontData.h', 'css/CSSCustomIdentValue.cpp', 'css/CSSCustomIdentValue.h', + 'css/CSSCustomPropertyDeclaration.cpp', + 'css/CSSCustomPropertyDeclaration.h', 'css/CSSDefaultStyleSheets.cpp', 'css/CSSDefaultStyleSheets.h', 'css/CSSFontFace.cpp', @@ -1132,6 +1133,10 @@ 'css/CSSValuePair.h', 'css/CSSValuePool.cpp', 'css/CSSValuePool.h', + 'css/CSSVariableData.cpp', + 'css/CSSVariableData.h', + 'css/CSSVariableReferenceValue.cpp', + 'css/CSSVariableReferenceValue.h', 'css/CSSViewportRule.cpp', 'css/CSSViewportRule.h', 'css/DOMWindowCSS.cpp', @@ -1251,6 +1256,8 @@ 'css/parser/CSSSupportsParser.h', 'css/parser/CSSTokenizer.cpp', 'css/parser/CSSTokenizerInputStream.cpp', + 'css/parser/CSSVariableParser.cpp', + 'css/parser/CSSVariableParser.h', 'css/parser/LegacyCSSPropertyParser.cpp', 'css/parser/MediaQueryBlockWatcher.cpp', 'css/parser/MediaQueryParser.cpp', @@ -1260,6 +1267,8 @@ 'css/resolver/AnimatedStyleBuilder.h', 'css/resolver/CSSToStyleMap.cpp', 'css/resolver/CSSToStyleMap.h', + 'css/resolver/CSSVariableResolver.cpp', + 'css/resolver/CSSVariableResolver.h', 'css/resolver/ElementResolveContext.cpp', 'css/resolver/ElementResolveContext.h', 'css/resolver/ElementStyleResources.cpp',
diff --git a/third_party/WebKit/Source/core/css/CSSColorValue.h b/third_party/WebKit/Source/core/css/CSSColorValue.h index e8e532f..6b7ce222f 100644 --- a/third_party/WebKit/Source/core/css/CSSColorValue.h +++ b/third_party/WebKit/Source/core/css/CSSColorValue.h
@@ -24,8 +24,7 @@ return m_color.serializedAsCSSComponentValue(); } - // TODO(sashab): Make this return a Color. - RGBA32 value() const { return m_color.rgb(); } + Color value() const { return m_color; } bool equals(const CSSColorValue& other) const {
diff --git a/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.cpp b/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.cpp new file mode 100644 index 0000000..be7770eb --- /dev/null +++ b/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.cpp
@@ -0,0 +1,15 @@ +// Copyright 2015 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 "config.h" +#include "core/css/CSSCustomPropertyDeclaration.h" + +namespace blink { + +DEFINE_TRACE_AFTER_DISPATCH(CSSCustomPropertyDeclaration) +{ + CSSValue::traceAfterDispatch(visitor); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.h b/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.h new file mode 100644 index 0000000..01c959bd --- /dev/null +++ b/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.h
@@ -0,0 +1,61 @@ +// Copyright 2015 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 CSSCustomPropertyDeclaration_h +#define CSSCustomPropertyDeclaration_h + +#include "core/css/CSSValue.h" +#include "core/css/CSSVariableData.h" +#include "wtf/RefPtr.h" +#include "wtf/text/AtomicString.h" + +namespace blink { + +class CSSCustomPropertyDeclaration : public CSSValue { +public: + static PassRefPtrWillBeRawPtr<CSSCustomPropertyDeclaration> create(const AtomicString& name, PassRefPtr<CSSVariableData> value) + { + return adoptRefWillBeNoop(new CSSCustomPropertyDeclaration(name, value)); + } + + static PassRefPtrWillBeRawPtr<CSSCustomPropertyDeclaration> create(const AtomicString& name, CSSValueID id) + { + return adoptRefWillBeNoop(new CSSCustomPropertyDeclaration(name, id)); + } + + const AtomicString& name() const { return m_name; } + CSSVariableData* value() const { return m_value.get(); } + CSSValueID id() const { return m_valueId; } + + bool equals(const CSSCustomPropertyDeclaration& other) const { return this == &other; } + + DECLARE_TRACE_AFTER_DISPATCH(); +private: + CSSCustomPropertyDeclaration(const AtomicString& name, CSSValueID id) + : CSSValue(CustomPropertyDeclarationClass) + , m_name(name) + , m_value(nullptr) + , m_valueId(id) + { + ASSERT(id == CSSValueInherit || id == CSSValueInitial || id == CSSValueUnset); + } + + CSSCustomPropertyDeclaration(const AtomicString& name, PassRefPtr<CSSVariableData> value) + : CSSValue(CustomPropertyDeclarationClass) + , m_name(name) + , m_value(value) + , m_valueId(CSSValueInternalVariableValue) + { + } + + const AtomicString m_name; + RefPtr<CSSVariableData> m_value; + CSSValueID m_valueId; +}; + +DEFINE_CSS_VALUE_TYPE_CASTS(CSSCustomPropertyDeclaration, isCustomPropertyDeclaration()); + +} // namespace blink + +#endif // CSSCustomPropertyDeclaration_h
diff --git a/third_party/WebKit/Source/core/css/CSSProperty.cpp b/third_party/WebKit/Source/core/css/CSSProperty.cpp index 4bab1ff..e64f93a 100644 --- a/third_party/WebKit/Source/core/css/CSSProperty.cpp +++ b/third_party/WebKit/Source/core/css/CSSProperty.cpp
@@ -228,6 +228,9 @@ if (!CSSPropertyMetadata::isEnabledProperty(propertyID)) return false; + if (propertyID == CSSPropertyVariable) + return false; + // all shorthand spec says: // The all property is a shorthand that resets all CSS properties except // direction and unicode-bidi. It only accepts the CSS-wide keywords.
diff --git a/third_party/WebKit/Source/core/css/CSSSelector.h b/third_party/WebKit/Source/core/css/CSSSelector.h index 4a6a5eb..596d81f 100644 --- a/third_party/WebKit/Source/core/css/CSSSelector.h +++ b/third_party/WebKit/Source/core/css/CSSSelector.h
@@ -252,7 +252,6 @@ bool isSiblingSelector() const; bool isAttributeSelector() const { return m_match >= FirstAttributeSelectorMatch; } bool isHostPseudoClass() const { return m_pseudoType == PseudoHost || m_pseudoType == PseudoHostContext; } - bool isTreeBoundaryCrossing() const { return m_pseudoType == PseudoHost || m_pseudoType == PseudoHostContext; } bool isInsertionPointCrossing() const { return m_pseudoType == PseudoHostContext || m_pseudoType == PseudoContent; } Relation relation() const { return static_cast<Relation>(m_relation); }
diff --git a/third_party/WebKit/Source/core/css/CSSValue.cpp b/third_party/WebKit/Source/core/css/CSSValue.cpp index a66b20b..dcc6bd1 100644 --- a/third_party/WebKit/Source/core/css/CSSValue.cpp +++ b/third_party/WebKit/Source/core/css/CSSValue.cpp
@@ -35,6 +35,7 @@ #include "core/css/CSSCrossfadeValue.h" #include "core/css/CSSCursorImageValue.h" #include "core/css/CSSCustomIdentValue.h" +#include "core/css/CSSCustomPropertyDeclaration.h" #include "core/css/CSSFontFaceSrcValue.h" #include "core/css/CSSFontFeatureValue.h" #include "core/css/CSSFunctionValue.h" @@ -58,6 +59,7 @@ #include "core/css/CSSUnsetValue.h" #include "core/css/CSSValueList.h" #include "core/css/CSSValuePair.h" +#include "core/css/CSSVariableReferenceValue.h" namespace blink { @@ -170,6 +172,10 @@ return compareCSSValues<CSSSVGDocumentValue>(*this, other); case CSSContentDistributionClass: return compareCSSValues<CSSContentDistributionValue>(*this, other); + case CustomPropertyDeclarationClass: + return compareCSSValues<CSSCustomPropertyDeclaration>(*this, other); + case VariableReferenceClass: + return compareCSSValues<CSSVariableReferenceValue>(*this, other); } ASSERT_NOT_REACHED(); return false; @@ -252,6 +258,11 @@ return toCSSSVGDocumentValue(this)->customCSSText(); case CSSContentDistributionClass: return toCSSContentDistributionValue(this)->customCSSText(); + case VariableReferenceClass: + return toCSSVariableReferenceValue(this)->customCSSText(); + case CustomPropertyDeclarationClass: + // TODO(leviw): We don't allow custom properties in CSSOM yet + ASSERT_NOT_REACHED(); } ASSERT_NOT_REACHED(); return String(); @@ -368,6 +379,12 @@ case CSSContentDistributionClass: delete toCSSContentDistributionValue(this); return; + case VariableReferenceClass: + delete toCSSVariableReferenceValue(this); + return; + case CustomPropertyDeclarationClass: + delete toCSSCustomPropertyDeclaration(this); + return; } ASSERT_NOT_REACHED(); } @@ -483,6 +500,12 @@ case CSSContentDistributionClass: toCSSContentDistributionValue(this)->~CSSContentDistributionValue(); return; + case VariableReferenceClass: + toCSSVariableReferenceValue(this)->~CSSVariableReferenceValue(); + return; + case CustomPropertyDeclarationClass: + toCSSCustomPropertyDeclaration(this)->~CSSCustomPropertyDeclaration(); + return; } ASSERT_NOT_REACHED(); } @@ -598,6 +621,12 @@ case CSSContentDistributionClass: toCSSContentDistributionValue(this)->traceAfterDispatch(visitor); return; + case VariableReferenceClass: + toCSSVariableReferenceValue(this)->traceAfterDispatch(visitor); + return; + case CustomPropertyDeclarationClass: + toCSSCustomPropertyDeclaration(this)->traceAfterDispatch(visitor); + return; } ASSERT_NOT_REACHED(); }
diff --git a/third_party/WebKit/Source/core/css/CSSValue.h b/third_party/WebKit/Source/core/css/CSSValue.h index b157f57..5b2e09bb 100644 --- a/third_party/WebKit/Source/core/css/CSSValue.h +++ b/third_party/WebKit/Source/core/css/CSSValue.h
@@ -103,6 +103,8 @@ bool isContentDistributionValue() const { return m_classType == CSSContentDistributionClass; } bool isUnicodeRangeValue() const { return m_classType == UnicodeRangeClass; } bool isGridLineNamesValue() const { return m_classType == GridLineNamesClass; } + bool isCustomPropertyDeclaration() const { return m_classType == CustomPropertyDeclarationClass; } + bool isVariableReferenceValue() const { return m_classType == VariableReferenceClass; } bool hasFailedOrCanceledSubresources() const; @@ -164,6 +166,8 @@ UnicodeRangeClass, GridTemplateAreasClass, PathClass, + VariableReferenceClass, + CustomPropertyDeclarationClass, // SVG classes. CSSSVGDocumentClass,
diff --git a/third_party/WebKit/Source/core/css/CSSValueKeywords.in b/third_party/WebKit/Source/core/css/CSSValueKeywords.in index b950c1d..8d673ee 100644 --- a/third_party/WebKit/Source/core/css/CSSValueKeywords.in +++ b/third_party/WebKit/Source/core/css/CSSValueKeywords.in
@@ -1043,3 +1043,6 @@ mandatory proximity from-image + +var +-internal-variable-value
diff --git a/third_party/WebKit/Source/core/css/CSSVariableData.cpp b/third_party/WebKit/Source/core/css/CSSVariableData.cpp new file mode 100644 index 0000000..d5208cb --- /dev/null +++ b/third_party/WebKit/Source/core/css/CSSVariableData.cpp
@@ -0,0 +1,59 @@ +// Copyright 2015 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 "config.h" +#include "core/css/CSSVariableData.h" + +#include "core/css/parser/CSSParserTokenRange.h" +#include "wtf/text/StringBuilder.h" + +namespace blink { + +template<typename CharacterType> void CSSVariableData::updateTokens(const CSSParserTokenRange& range) +{ + const CharacterType* currentOffset = m_backingString.getCharacters<CharacterType>(); + for (const CSSParserToken& token : range) { + if (token.hasStringBacking()) { + unsigned length = token.value().length(); + CSSParserString parserString; + parserString.init(currentOffset, length); + m_tokens.append(token.copyWithUpdatedString(parserString)); + currentOffset += length; + } else { + m_tokens.append(token); + } + } + ASSERT(currentOffset == m_backingString.getCharacters<CharacterType>() + m_backingString.length()); +} + +void CSSVariableData::consumeAndUpdateTokens(const CSSParserTokenRange& range) +{ + StringBuilder stringBuilder; + CSSParserTokenRange localRange = range; + + while (!localRange.atEnd()) { + CSSParserToken token = localRange.consume(); + if (token.hasStringBacking()) { + CSSParserString value = token.value(); + if (value.is8Bit()) + stringBuilder.append(value.characters8(), value.length()); + else + stringBuilder.append(value.characters16(), value.length()); + } + } + m_backingString = stringBuilder.toString(); + if (m_backingString.is8Bit()) + updateTokens<LChar>(range); + else + updateTokens<UChar>(range); +} + +CSSVariableData::CSSVariableData(const CSSParserTokenRange& range, bool needsVariableResolution) + : m_needsVariableResolution(needsVariableResolution) +{ + ASSERT(!range.atEnd()); + consumeAndUpdateTokens(range); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/css/CSSVariableData.h b/third_party/WebKit/Source/core/css/CSSVariableData.h new file mode 100644 index 0000000..9b35033 --- /dev/null +++ b/third_party/WebKit/Source/core/css/CSSVariableData.h
@@ -0,0 +1,58 @@ +// Copyright 2015 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 CSSVariableData_h +#define CSSVariableData_h + +#include "core/css/parser/CSSParserToken.h" +#include "core/css/parser/CSSParserTokenRange.h" +#include "wtf/RefCounted.h" +#include "wtf/text/WTFString.h" + +namespace blink { + +class CSSParserTokenRange; + +class CSSVariableData : public RefCounted<CSSVariableData> { + WTF_MAKE_NONCOPYABLE(CSSVariableData); + USING_FAST_MALLOC(CSSVariableData); +public: + static PassRefPtr<CSSVariableData> create(const CSSParserTokenRange& range, bool needsVariableResolution = true) + { + return adoptRef(new CSSVariableData(range, needsVariableResolution)); + } + + static PassRefPtr<CSSVariableData> createResolved(const Vector<CSSParserToken>& resolvedTokens) + { + return adoptRef(new CSSVariableData(resolvedTokens)); + } + + CSSParserTokenRange tokenRange() { return m_tokens; } + + const Vector<CSSParserToken>& tokens() { return m_tokens; } + + bool needsVariableResolution() const { return m_needsVariableResolution; } +private: + CSSVariableData(const CSSParserTokenRange&, bool needsVariableResolution); + + // We can safely copy the tokens (which have raw pointers to substrings) because + // StylePropertySets contain references to CSSCustomPropertyDeclarations, which + // point to the unresolved CSSVariableData values that own the backing strings + // this will potentially reference. + CSSVariableData(const Vector<CSSParserToken>& resolvedTokens) + : m_tokens(resolvedTokens) + , m_needsVariableResolution(false) + { } + + void consumeAndUpdateTokens(const CSSParserTokenRange&); + template<typename CharacterType> void updateTokens(const CSSParserTokenRange&); + + String m_backingString; + Vector<CSSParserToken> m_tokens; + const bool m_needsVariableResolution; +}; + +} // namespace blink + +#endif // CSSVariableData_h
diff --git a/third_party/WebKit/Source/core/css/CSSVariableReferenceValue.cpp b/third_party/WebKit/Source/core/css/CSSVariableReferenceValue.cpp new file mode 100644 index 0000000..76a9565 --- /dev/null +++ b/third_party/WebKit/Source/core/css/CSSVariableReferenceValue.cpp
@@ -0,0 +1,21 @@ +// Copyright 2015 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 "config.h" +#include "core/css/CSSVariableReferenceValue.h" + +namespace blink { + +DEFINE_TRACE_AFTER_DISPATCH(CSSVariableReferenceValue) +{ + CSSValue::traceAfterDispatch(visitor); +} + +String CSSVariableReferenceValue::customCSSText() const +{ + // We may want to consider caching this value. + return m_data->tokenRange().serialize(); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/css/CSSVariableReferenceValue.h b/third_party/WebKit/Source/core/css/CSSVariableReferenceValue.h new file mode 100644 index 0000000..187c8fb --- /dev/null +++ b/third_party/WebKit/Source/core/css/CSSVariableReferenceValue.h
@@ -0,0 +1,44 @@ +// Copyright 2015 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 CSSVariableReferenceValue_h +#define CSSVariableReferenceValue_h + +#include "core/css/CSSValue.h" +#include "core/css/CSSVariableData.h" +#include "wtf/RefPtr.h" + +namespace blink { + +class CSSVariableReferenceValue : public CSSValue { +public: + static PassRefPtrWillBeRawPtr<CSSVariableReferenceValue> create(PassRefPtr<CSSVariableData> data) + { + return adoptRefWillBeNoop(new CSSVariableReferenceValue(data)); + } + + CSSVariableData* variableDataValue() const + { + return m_data.get(); + } + + bool equals(const CSSVariableReferenceValue& other) const { return m_data == other.m_data; } + String customCSSText() const; + + DECLARE_TRACE_AFTER_DISPATCH(); +private: + CSSVariableReferenceValue(PassRefPtr<CSSVariableData> data) + : CSSValue(VariableReferenceClass) + , m_data(data) + { + } + + RefPtr<CSSVariableData> m_data; +}; + +DEFINE_CSS_VALUE_TYPE_CASTS(CSSVariableReferenceValue, isVariableReferenceValue()); + +} // namespace blink + +#endif // CSSVariableReferenceValue_h
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp index af0cb90..93ce3b2 100644 --- a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp +++ b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
@@ -2683,6 +2683,10 @@ list->append(cssValuePool().createValue(style.scale()->z(), CSSPrimitiveValue::UnitType::Number)); return list.release(); } + case CSSPropertyVariable: + // TODO(leviw): We should have a way to retrive variables here. + ASSERT_NOT_REACHED(); + return nullptr; case CSSPropertyAll: return nullptr; default:
diff --git a/third_party/WebKit/Source/core/css/ElementRuleCollector.cpp b/third_party/WebKit/Source/core/css/ElementRuleCollector.cpp index adb7c062..0797d01b 100644 --- a/third_party/WebKit/Source/core/css/ElementRuleCollector.cpp +++ b/third_party/WebKit/Source/core/css/ElementRuleCollector.cpp
@@ -113,19 +113,10 @@ m_result.setIsCacheable(false); } -static bool rulesApplicableInCurrentTreeScope(const Element* element, const ContainerNode* scopingNode, bool matchingTreeBoundaryRules) +static bool rulesApplicableInCurrentTreeScope(const Element* element, const ContainerNode* scopingNode) { - // [skipped, because already checked] a) it's a UA rule - // b) We're mathcing tree boundary rules. - if (matchingTreeBoundaryRules) - return true; - // c) the rules comes from a scoped style sheet within the same tree scope - if (!scopingNode || element->treeScope() == scopingNode->treeScope()) - return true; - // d) the rules comes from a scoped style sheet within an active shadow root whose host is the given element - if (element == scopingNode->shadowHost()) - return true; - return false; + // Check if the rules come from a shadow style sheet in the same tree scope. + return !scopingNode || element->treeScope() == scopingNode->treeScope(); } template<typename RuleDataListType> @@ -201,12 +192,11 @@ if (element.isVTTElement()) collectMatchingRulesForList(matchRequest.ruleSet->cuePseudoRules(), cascadeOrder, matchRequest); // Check whether other types of rules are applicable in the current tree scope. Criteria for this: - // a) it's a UA rule - // b) the rules comes from a scoped style sheet within the same tree scope - // c) the rules comes from a scoped style sheet within an active shadow root whose host is the given element - // d) the rules can cross boundaries - // b)-e) is checked in rulesApplicableInCurrentTreeScope. - if (!m_matchingUARules && !rulesApplicableInCurrentTreeScope(&element, matchRequest.scope, matchingTreeBoundaryRules)) + // a) the rules are UA rules. + // b) matching tree boundary crossing rules. + // c) the rules come from a shadow style sheet in the same tree scope as the given element. + // c) is checked in rulesApplicableInCurrentTreeScope. + if (!m_matchingUARules && !matchingTreeBoundaryRules && !rulesApplicableInCurrentTreeScope(&element, matchRequest.scope)) return; // We need to collect the rules for id, class, tag, and everything else into a buffer and
diff --git a/third_party/WebKit/Source/core/css/RuleFeature.cpp b/third_party/WebKit/Source/core/css/RuleFeature.cpp index ad28c411..0deb51645 100644 --- a/third_party/WebKit/Source/core/css/RuleFeature.cpp +++ b/third_party/WebKit/Source/core/css/RuleFeature.cpp
@@ -464,7 +464,7 @@ addFeaturesToInvalidationSet(*invalidationSet, descendantFeatures); } } else { - if (current->isTreeBoundaryCrossing()) + if (current->isHostPseudoClass()) descendantFeatures.treeBoundaryCrossing = true; if (current->isInsertionPointCrossing()) descendantFeatures.insertionPointCrossing = true;
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSParser.cpp index 9fc5d92..4e84fa1a 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParser.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParser.cpp
@@ -109,7 +109,7 @@ return CSSSupportsParser::supportsCondition(scope.tokenRange(), parser) == CSSSupportsParser::Supported; } -bool CSSParser::parseColor(RGBA32& color, const String& string, bool strict) +bool CSSParser::parseColor(Color& color, const String& string, bool strict) { if (string.isEmpty()) return false; @@ -118,7 +118,7 @@ // handle these first. Color namedColor; if (namedColor.setNamedColor(string)) { - color = namedColor.rgb(); + color = namedColor; return true; } @@ -133,7 +133,7 @@ return true; } -bool CSSParser::parseSystemColor(RGBA32& color, const String& colorString) +bool CSSParser::parseSystemColor(Color& color, const String& colorString) { CSSParserString cssColor; cssColor.init(colorString); @@ -141,8 +141,7 @@ if (!CSSPropertyParser::isSystemColor(id)) return false; - Color parsedColor = LayoutTheme::theme().systemColor(id); - color = parsedColor.rgb(); + color = LayoutTheme::theme().systemColor(id); return true; }
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParser.h b/third_party/WebKit/Source/core/css/parser/CSSParser.h index 53b0509..0c5bc6ec 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParser.h +++ b/third_party/WebKit/Source/core/css/parser/CSSParser.h
@@ -49,8 +49,8 @@ // The color will only be changed when string contains a valid CSS color, so callers // can set it to a default color and ignore the boolean result. - static bool parseColor(RGBA32& color, const String&, bool strict = false); - static bool parseSystemColor(RGBA32& color, const String&); + static bool parseColor(Color&, const String&, bool strict = false); + static bool parseSystemColor(Color&, const String&); static void parseSheetForInspector(const CSSParserContext&, StyleSheetContents*, const String&, CSSParserObserver&); static void parseDeclarationListForInspector(const CSSParserContext&, const String&, CSSParserObserver&);
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp index a9c2c3fd..47752a0 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
@@ -5,6 +5,7 @@ #include "config.h" #include "core/css/parser/CSSParserImpl.h" +#include "core/css/CSSCustomPropertyDeclaration.h" #include "core/css/CSSKeyframesRule.h" #include "core/css/CSSStyleSheet.h" #include "core/css/StylePropertySet.h" @@ -20,6 +21,7 @@ #include "core/css/parser/CSSSelectorParser.h" #include "core/css/parser/CSSSupportsParser.h" #include "core/css/parser/CSSTokenizer.h" +#include "core/css/parser/CSSVariableParser.h" #include "core/css/parser/MediaQueryParser.h" #include "core/dom/Document.h" #include "core/dom/Element.h" @@ -56,10 +58,13 @@ const CSSProperty& property = input[i]; if (property.isImportant() != important) continue; - const unsigned propertyIDIndex = property.id() - firstCSSProperty; - if (seenProperties.get(propertyIDIndex)) - continue; - seenProperties.set(propertyIDIndex); + const unsigned propertyIDIndex = property.id(); + // All custom properties use the same CSSPropertyID so we can't remove repeated definitions + if (property.id() != CSSPropertyVariable) { + if (seenProperties.get(propertyIDIndex)) + continue; + seenProperties.set(propertyIDIndex); + } output[--unusedEntries] = property; } } @@ -672,7 +677,8 @@ CSSParserTokenRange rangeCopy = range; // For inspector callbacks ASSERT(range.peek().type() == IdentToken); - CSSPropertyID unresolvedProperty = range.consumeIncludingWhitespace().parseAsUnresolvedCSSPropertyID(); + const CSSParserToken& token = range.consumeIncludingWhitespace(); + CSSPropertyID unresolvedProperty = token.parseAsUnresolvedCSSPropertyID(); if (range.consume().type() != ColonToken) return; // Parse error @@ -690,6 +696,11 @@ declarationValueEnd = last; } } + if (RuntimeEnabledFeatures::cssVariablesEnabled() && unresolvedProperty == CSSPropertyInvalid && CSSVariableParser::isValidVariableName(token)) { + AtomicString variableName = token.value(); + consumeVariableDeclarationValue(range.makeSubRange(&range.peek(), declarationValueEnd), variableName, important); + return; + } if (important && (ruleType == StyleRule::FontFace || ruleType == StyleRule::Keyframes)) return; @@ -710,6 +721,12 @@ consumeDeclarationValue(range.makeSubRange(&range.peek(), declarationValueEnd), unresolvedProperty, important, ruleType); } +void CSSParserImpl::consumeVariableDeclarationValue(CSSParserTokenRange range, const AtomicString& variableName, bool important) +{ + if (RefPtrWillBeRawPtr<CSSCustomPropertyDeclaration> value = CSSVariableParser::parseDeclarationValue(variableName, range)) + m_parsedProperties.append(CSSProperty(CSSPropertyVariable, value.release(), important)); +} + void CSSParserImpl::consumeDeclarationValue(CSSParserTokenRange range, CSSPropertyID unresolvedProperty, bool important, StyleRule::Type ruleType) { CSSPropertyParser::parseValue(unresolvedProperty, important, range, m_context, m_parsedProperties, ruleType);
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h index 6bab11e..a06caeeb 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h +++ b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h
@@ -98,6 +98,7 @@ void consumeDeclarationList(CSSParserTokenRange, StyleRule::Type); void consumeDeclaration(CSSParserTokenRange, StyleRule::Type); void consumeDeclarationValue(CSSParserTokenRange, CSSPropertyID, bool important, StyleRule::Type); + void consumeVariableDeclarationValue(CSSParserTokenRange, const AtomicString& variableName, bool important); static PassOwnPtr<Vector<double>> consumeKeyframeKeyList(CSSParserTokenRange);
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserToken.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserToken.cpp index e383267..b131a94 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserToken.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParserToken.cpp
@@ -129,6 +129,25 @@ return static_cast<CSSValueID>(m_id); } +bool CSSParserToken::hasStringBacking() const +{ + CSSParserTokenType tokenType = type(); + return tokenType == IdentToken + || tokenType == FunctionToken + || tokenType == AtKeywordToken + || tokenType == HashToken + || tokenType == UrlToken + || tokenType == DimensionToken + || tokenType == StringToken; +} + +CSSParserToken CSSParserToken::copyWithUpdatedString(const CSSParserString& parserString) const +{ + CSSParserToken copy(*this); + copy.initValueFromCSSParserString(parserString); + return copy; +} + void CSSParserToken::serialize(StringBuilder& builder) const { // This is currently only used for @supports CSSOM. To keep our implementation
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserToken.h b/third_party/WebKit/Source/core/css/parser/CSSParserToken.h index 0d7756c3..e4a12c3f 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserToken.h +++ b/third_party/WebKit/Source/core/css/parser/CSSParserToken.h
@@ -109,10 +109,14 @@ CSSValueID id() const; CSSValueID functionId() const; + bool hasStringBacking() const; + CSSPropertyID parseAsUnresolvedCSSPropertyID() const; void serialize(StringBuilder&) const; + CSSParserToken copyWithUpdatedString(const CSSParserString&) const; + private: void initValueFromCSSParserString(const CSSParserString& value) {
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserTokenRange.h b/third_party/WebKit/Source/core/css/parser/CSSParserTokenRange.h index c8cf20b3..c4f875d8 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserTokenRange.h +++ b/third_party/WebKit/Source/core/css/parser/CSSParserTokenRange.h
@@ -66,7 +66,6 @@ String serialize() const; - // This is only for the inspector integration const CSSParserToken* begin() const { return m_first; } static void initStaticEOFToken();
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserValues.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserValues.cpp index 160a254..6bd6957 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserValues.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParserValues.cpp
@@ -22,9 +22,11 @@ #include "core/css/parser/CSSParserValues.h" #include "core/css/CSSFunctionValue.h" +#include "core/css/CSSVariableData.h" #include "core/css/parser/CSSParserToken.h" #include "core/css/parser/CSSParserTokenRange.h" #include "core/css/parser/CSSPropertyParser.h" +#include "core/css/parser/CSSVariableParser.h" #include "core/html/parser/HTMLParserIdioms.h" namespace blink { @@ -34,6 +36,8 @@ CSSParserValueList::CSSParserValueList(CSSParserTokenRange range) : m_current(0) { + CSSParserTokenRange originalRangeForVariables = range; + Vector<CSSParserValueList*> stack; Vector<int> bracketCounts; stack.append(this); @@ -51,7 +55,7 @@ range.consume(); const CSSParserToken& next = range.consumeIncludingWhitespace(); if (next.type() == BadStringToken || range.consume().type() != RightParenthesisToken) { - destroyAndClear(); + checkForVariableReferencesOrDestroyAndClear(originalRangeForVariables); return; } ASSERT(next.type() == StringToken); @@ -60,6 +64,9 @@ value.m_unit = CSSParserValue::URI; value.string = next.value(); break; + } else if (token.valueEqualsIgnoringCase("var")) { + checkForVariableReferencesOrDestroyAndClear(originalRangeForVariables); + return; } value.id = CSSValueInvalid; @@ -98,7 +105,7 @@ stack.removeLast(); bracketCounts.removeLast(); if (bracketCounts.isEmpty()) { - destroyAndClear(); + checkForVariableReferencesOrDestroyAndClear(originalRangeForVariables); return; } continue; @@ -202,10 +209,12 @@ case SuffixMatchToken: case SubstringMatchToken: case ColumnToken: - case BadStringToken: - case BadUrlToken: case ColonToken: case SemicolonToken: + checkForVariableReferencesOrDestroyAndClear(originalRangeForVariables); + return; + case BadStringToken: + case BadUrlToken: destroyAndClear(); return; } @@ -235,9 +244,30 @@ else if (values[i].m_unit == CSSParserValue::ValueList || values[i].m_unit == CSSParserValue::DimensionList) delete values[i].valueList; + else if (values[i].m_unit == CSSParserValue::VariableReference) + values[i].variableData->deref(); } } +void CSSParserValueList::checkForVariableReferencesOrDestroyAndClear(const CSSParserTokenRange& originalRange) +{ + // We have to clear any state that may have been previously loaded + destroyAndClear(); + if (RuntimeEnabledFeatures::cssVariablesEnabled() && CSSVariableParser::containsValidVariableReferences(originalRange)) + consumeVariableValue(originalRange); +} + +void CSSParserValueList::consumeVariableValue(const CSSParserTokenRange& originalRange) +{ + ASSERT(m_values.isEmpty()); + CSSParserValue variableValue; + variableValue.id = CSSValueInternalVariableValue; + variableValue.m_unit = CSSParserValue::VariableReference; + variableValue.isInt = false; + variableValue.variableData = CSSVariableData::create(originalRange).leakRef(); + addValue(variableValue); +} + void CSSParserValueList::destroyAndClear() { destroy(m_values);
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserValues.h b/third_party/WebKit/Source/core/css/parser/CSSParserValues.h index 2b95061..f3c95d6 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserValues.h +++ b/third_party/WebKit/Source/core/css/parser/CSSParserValues.h
@@ -35,6 +35,7 @@ struct CSSParserFunction; struct CSSParserCalcFunction; class CSSParserValueList; +class CSSVariableData; struct CSSParserValue { DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); @@ -51,6 +52,7 @@ UChar32 start; UChar32 end; } m_unicodeRange; + CSSVariableData* variableData; }; enum { Operator = 0x100000, @@ -65,6 +67,7 @@ UnicodeRange = 0x100007, String = 0x100008, URI = 0x100009, + VariableReference = 0x100010, }; int m_unit; CSSPrimitiveValue::UnitType unit() const { return static_cast<CSSPrimitiveValue::UnitType>(m_unit); } @@ -111,6 +114,9 @@ void destroyAndClear(); private: + void checkForVariableReferencesOrDestroyAndClear(const CSSParserTokenRange& originalRange); + void consumeVariableValue(const CSSParserTokenRange&); + unsigned m_current; Vector<CSSParserValue, 4> m_values; };
diff --git a/third_party/WebKit/Source/core/css/parser/CSSTokenizerTest.cpp b/third_party/WebKit/Source/core/css/parser/CSSTokenizerTest.cpp index 671955c..4481a6f 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSTokenizerTest.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSTokenizerTest.cpp
@@ -125,7 +125,7 @@ static CSSParserToken& name() \ { \ WTF::Partitions::initialize(nullptr); \ - DEFINE_STATIC_LOCAL_NOASSERT(CSSParserToken, name, (argument)); \ + DEFINE_STATIC_LOCAL(CSSParserToken, name, (argument)); \ return name; \ }
diff --git a/third_party/WebKit/Source/core/css/parser/CSSVariableParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSVariableParser.cpp new file mode 100644 index 0000000..94463b1 --- /dev/null +++ b/third_party/WebKit/Source/core/css/parser/CSSVariableParser.cpp
@@ -0,0 +1,123 @@ +// Copyright 2015 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 "config.h" +#include "core/css/parser/CSSVariableParser.h" + +#include "core/css/CSSCustomPropertyDeclaration.h" +#include "core/css/parser/CSSParserTokenRange.h" +#include "core/css/parser/CSSParserValues.h" + +namespace blink { + +bool CSSVariableParser::isValidVariableName(const CSSParserToken& token) +{ + if (token.type() != IdentToken) + return false; + + CSSParserString value = token.value(); + return value.length() >= 2 && value[0] == '-' && value[1] == '-'; +} + +bool isValidVariableReference(CSSParserTokenRange); + +bool classifyBlock(CSSParserTokenRange range, bool& hasReferences, bool isTopLevelBlock = true) +{ + while (!range.atEnd()) { + if (range.peek().blockType() == CSSParserToken::BlockStart) { + const CSSParserToken& token = range.peek(); + CSSParserTokenRange block = range.consumeBlock(); + if (token.functionId() == CSSValueVar) { + if (!isValidVariableReference(block)) + return false; // Bail if any references are invalid + hasReferences = true; + continue; + } + if (!classifyBlock(block, hasReferences, false)) + return false; + continue; + } + + ASSERT(range.peek().blockType() != CSSParserToken::BlockEnd); + + const CSSParserToken& token = range.consume(); + switch (token.type()) { + case DelimiterToken: { + if (token.delimiter() == '!' && isTopLevelBlock) + return false; + break; + } + case RightParenthesisToken: + case RightBraceToken: + case RightBracketToken: + case BadStringToken: + case BadUrlToken: + return false; + case SemicolonToken: + if (isTopLevelBlock) + return false; + break; + default: + break; + } + } + return true; +} + +bool isValidVariableReference(CSSParserTokenRange range) +{ + range.consumeWhitespace(); + if (!CSSVariableParser::isValidVariableName(range.consumeIncludingWhitespace())) + return false; + if (range.atEnd()) + return true; + + if (range.consume().type() != CommaToken) + return false; + if (range.atEnd()) + return false; + + bool hasReferences = false; + return classifyBlock(range, hasReferences); +} + +static CSSValueID classifyVariableRange(CSSParserTokenRange range, bool& hasReferences) +{ + hasReferences = false; + + range.consumeWhitespace(); + if (range.peek().type() == IdentToken) { + CSSValueID id = range.consumeIncludingWhitespace().id(); + if (range.atEnd() && (id == CSSValueInherit || id == CSSValueInitial || id == CSSValueUnset)) + return id; + } + + if (classifyBlock(range, hasReferences)) + return CSSValueInternalVariableValue; + return CSSValueInvalid; +} + +bool CSSVariableParser::containsValidVariableReferences(CSSParserTokenRange range) +{ + bool hasReferences; + CSSValueID type = classifyVariableRange(range, hasReferences); + return type == CSSValueInternalVariableValue && hasReferences; +} + +PassRefPtrWillBeRawPtr<CSSCustomPropertyDeclaration> CSSVariableParser::parseDeclarationValue(const AtomicString& variableName, CSSParserTokenRange range) +{ + if (range.atEnd()) + return nullptr; + + bool hasReferences; + CSSValueID type = classifyVariableRange(range, hasReferences); + + if (type == CSSValueInvalid) + return nullptr; + if (type == CSSValueInternalVariableValue) + return CSSCustomPropertyDeclaration::create(variableName, CSSVariableData::create(range, hasReferences)); + return CSSCustomPropertyDeclaration::create(variableName, type); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/css/parser/CSSVariableParser.h b/third_party/WebKit/Source/core/css/parser/CSSVariableParser.h new file mode 100644 index 0000000..7af43e1 --- /dev/null +++ b/third_party/WebKit/Source/core/css/parser/CSSVariableParser.h
@@ -0,0 +1,28 @@ +// Copyright 2015 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 CSSVariableParser_h +#define CSSVariableParser_h + +#include "core/css/parser/CSSParserTokenRange.h" +#include "platform/heap/Handle.h" +#include "wtf/RefPtr.h" +#include "wtf/text/AtomicString.h" + +namespace blink { + +class CSSCustomPropertyDeclaration; + +class CSSVariableParser { +public: + static bool containsValidVariableReferences(CSSParserTokenRange); + + static PassRefPtrWillBeRawPtr<CSSCustomPropertyDeclaration> parseDeclarationValue(const AtomicString&, CSSParserTokenRange); + + static bool isValidVariableName(const CSSParserToken&); +}; + +} // namespace blink + +#endif // CSSVariableParser_h
diff --git a/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp index 5e0c902d..e9c3543 100644 --- a/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp +++ b/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp
@@ -51,6 +51,7 @@ #include "core/css/CSSURIValue.h" #include "core/css/CSSValuePair.h" #include "core/css/CSSValuePool.h" +#include "core/css/CSSVariableReferenceValue.h" #include "core/css/HashTools.h" #include "core/css/parser/CSSParserFastPaths.h" #include "core/css/parser/CSSParserValues.h" @@ -371,6 +372,13 @@ return true; } + if (RuntimeEnabledFeatures::cssVariablesEnabled() && value->id == CSSValueInternalVariableValue) { + // We don't expand the shorthand here because crazypants. + m_parsedProperties.append(CSSProperty(propId, CSSVariableReferenceValue::create(value->variableData), important, false, 0, m_implicitShorthand)); + m_valueList->next(); + return true; + } + if (CSSParserFastPaths::isKeywordPropertyID(propId)) { if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(propId, id)) return false;
diff --git a/third_party/WebKit/Source/core/css/resolver/CSSPropertyPriority.h b/third_party/WebKit/Source/core/css/resolver/CSSPropertyPriority.h index 58a6fbb7..1b2ec8e 100644 --- a/third_party/WebKit/Source/core/css/resolver/CSSPropertyPriority.h +++ b/third_party/WebKit/Source/core/css/resolver/CSSPropertyPriority.h
@@ -15,6 +15,7 @@ // decides the pixel value of low priority properties with 'em' units. enum CSSPropertyPriority { + ResolveVariables, HighPropertyPriority, LowPropertyPriority }; @@ -32,6 +33,19 @@ }; template<> +inline CSSPropertyID CSSPropertyPriorityData<ResolveVariables>::first() +{ + static_assert(CSSPropertyVariable == firstCSSProperty - 1, "CSSPropertyVariable should be directly before the first CSS property."); + return CSSPropertyVariable; +} + +template<> +inline CSSPropertyID CSSPropertyPriorityData<ResolveVariables>::last() +{ + return CSSPropertyVariable; +} + +template<> inline CSSPropertyID CSSPropertyPriorityData<HighPropertyPriority>::first() { static_assert(CSSPropertyColor == firstCSSProperty, "CSSPropertyColor should be the first high priority property");
diff --git a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp new file mode 100644 index 0000000..2a63bf0e --- /dev/null +++ b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp
@@ -0,0 +1,179 @@ +// Copyright 2015 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 "config.h" +#include "core/css/resolver/CSSVariableResolver.h" + +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/StyleBuilderFunctions.h" +#include "core/css/CSSVariableData.h" +#include "core/css/CSSVariableReferenceValue.h" +#include "core/css/parser/CSSParserToken.h" +#include "core/css/parser/CSSParserTokenRange.h" +#include "core/css/parser/CSSParserValues.h" +#include "core/css/parser/CSSPropertyParser.h" +#include "core/css/resolver/StyleBuilder.h" +#include "core/css/resolver/StyleResolverState.h" +#include "core/style/StyleVariableData.h" +#include "wtf/Vector.h" + +namespace blink { + +// TODO(leviw): This should take a CSSParserTokenRange +static void findEndIndexOfVariableReference(const Vector<CSSParserToken>& resolvedTokens, unsigned startIndex, unsigned& endIndex, unsigned& commaIndex, bool& hasClosingBracket) +{ + endIndex = 0; + commaIndex = 0; + unsigned bracketCount = 1; + for (unsigned i = startIndex; i < resolvedTokens.size(); ++i) { + CSSParserTokenType type = resolvedTokens[i].type(); + + if (type == CommaToken && !commaIndex) { + commaIndex = i; + } else if (type == LeftParenthesisToken || type == FunctionToken) { + bracketCount++; + } else if (type == RightParenthesisToken) { + if (bracketCount == 1) { + hasClosingBracket = true; + endIndex = i; + return; + } + bracketCount--; + } + } + hasClosingBracket = false; + endIndex = resolvedTokens.size() - 1; +} + +unsigned CSSVariableResolver::resolveVariableTokensRecursive(Vector<CSSParserToken>& resolvedTokens, unsigned startIndex) +{ + unsigned variableLocation = startIndex; + while (resolvedTokens[variableLocation].type() != IdentToken) + variableLocation++; + + unsigned commaIndex; + unsigned endIndex; + bool hasClosingBracket; + // Find default value and match braces + findEndIndexOfVariableReference(resolvedTokens, variableLocation + 1, endIndex, commaIndex, hasClosingBracket); + + unsigned length = endIndex - startIndex + 1; + unsigned varFunctionPosition = startIndex; + + AtomicString variableName = resolvedTokens[variableLocation].value(); + + if (m_variablesSeen.contains(variableName)) { + m_cycleDetected = true; + resolvedTokens.clear(); + return 0; + } + + CSSVariableData* variableData = m_styleVariableData ? m_styleVariableData->getVariable(variableName) : nullptr; + if (variableData) { + Vector<CSSParserToken> tokens(variableData->tokens()); + if (variableData->needsVariableResolution()) { + m_variablesSeen.add(variableName); + resolveVariableReferencesFromTokens(tokens); + m_variablesSeen.remove(variableName); + + // The old variable data holds onto the backing string the new resolved CSSVariableData + // relies on. Ensure it will live beyond us overwriting the RefPtr in StyleVariableData. + ASSERT(variableData->refCount() > 1); + + m_styleVariableData->setVariable(variableName, CSSVariableData::createResolved(tokens)); + } + if (tokens.size()) { + resolvedTokens.remove(startIndex, length); + resolvedTokens.insert(startIndex, tokens); + return tokens.size(); + } + } + + // Fallback on default value if present + if (!commaIndex || m_cycleDetected) { + resolvedTokens.clear(); + return 0; + } + + // Move the tokens to the beginning of the variable reference + unsigned defaultValueStart = commaIndex + 1; + unsigned defaultValueLength = endIndex - commaIndex - (hasClosingBracket ? 1 : 0); + for (unsigned i = 0; i < defaultValueLength; ++i) + resolvedTokens[varFunctionPosition + i] = resolvedTokens[defaultValueStart + i]; + resolvedTokens.remove(varFunctionPosition + defaultValueLength, length - defaultValueLength); + + resolveVariableReferencesFromTokens(resolvedTokens); + + return resolvedTokens.size(); +} + +void CSSVariableResolver::resolveVariableReferencesFromTokens(Vector<CSSParserToken>& tokens) +{ + for (unsigned i = 0; i < tokens.size(); ++i) { + if (tokens[i].functionId() == CSSValueVar) { + unsigned validTokens = resolveVariableTokensRecursive(tokens, i); + if (validTokens < 1 || m_cycleDetected) { + tokens.clear(); + break; + } + i += validTokens - 1; + } + } +} + +void CSSVariableResolver::resolveAndApplyVariableReferences(StyleResolverState& state, CSSPropertyID id, const CSSVariableReferenceValue& value) +{ + // TODO(leviw): This should be a stack + Vector<CSSParserToken> tokens = value.variableDataValue()->tokens(); + + CSSVariableResolver resolver(state.style()->variables()); + + resolver.resolveVariableReferencesFromTokens(tokens); + + if (!tokens.size()) + return; + + CSSParserContext context(HTMLStandardMode, 0); + + WillBeHeapVector<CSSProperty, 256> parsedProperties; + + CSSPropertyParser::parseValue(id, false, CSSParserTokenRange(tokens), context, parsedProperties, StyleRule::Type::Style); + + unsigned parsedPropertiesCount = parsedProperties.size(); + for (unsigned i = 0; i < parsedPropertiesCount; ++i) + StyleBuilder::applyProperty(parsedProperties[i].id(), state, parsedProperties[i].value()); +} + +void CSSVariableResolver::resolveVariableDefinitions(StyleVariableData* variables) +{ + if (!variables) + return; + + for (auto& variable : variables->m_data) { + if (!variable.value->needsVariableResolution()) + continue; + Vector<CSSParserToken> resolvedTokens(variable.value->tokens()); + + CSSVariableResolver resolver(variables, variable.key); + resolver.resolveVariableReferencesFromTokens(resolvedTokens); + + variable.value = CSSVariableData::createResolved(resolvedTokens); + } +} + +CSSVariableResolver::CSSVariableResolver(StyleVariableData* styleVariableData) + : m_styleVariableData(styleVariableData) + , m_cycleDetected(false) +{ +} + +CSSVariableResolver::CSSVariableResolver(StyleVariableData* styleVariableData, AtomicString& variable) + : m_styleVariableData(styleVariableData) + , m_cycleDetected(false) +{ + m_variablesSeen.add(variable); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.h b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.h new file mode 100644 index 0000000..fb832cce --- /dev/null +++ b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.h
@@ -0,0 +1,39 @@ +// Copyright 2015 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 CSSVariableResolver_h +#define CSSVariableResolver_h + +#include "core/CSSPropertyNames.h" +#include "core/css/parser/CSSParserToken.h" +#include "wtf/HashSet.h" +#include "wtf/text/AtomicString.h" +#include "wtf/text/AtomicStringHash.h" + +namespace blink { + +class CSSVariableReferenceValue; +class StyleResolverState; +class StyleVariableData; + +class CSSVariableResolver { +public: + static void resolveVariableDefinitions(StyleVariableData*); + static void resolveAndApplyVariableReferences(StyleResolverState&, CSSPropertyID, const CSSVariableReferenceValue&); + +private: + CSSVariableResolver(StyleVariableData*); + CSSVariableResolver(StyleVariableData*, AtomicString& variable); + + unsigned resolveVariableTokensRecursive(Vector<CSSParserToken>&, unsigned startOffset); + void resolveVariableReferencesFromTokens(Vector<CSSParserToken>& tokens); + + StyleVariableData* m_styleVariableData; + HashSet<AtomicString> m_variablesSeen; + bool m_cycleDetected; +}; + +} // namespace blink + +#endif // CSSVariableResolver
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp b/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp index 5ee1a03..de1b88a 100644 --- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp +++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp
@@ -46,6 +46,7 @@ #include "core/css/CSSBasicShapeValues.h" #include "core/css/CSSCounterValue.h" #include "core/css/CSSCursorImageValue.h" +#include "core/css/CSSCustomPropertyDeclaration.h" #include "core/css/CSSFunctionValue.h" #include "core/css/CSSGradientValue.h" #include "core/css/CSSGridTemplateAreasValue.h" @@ -56,8 +57,10 @@ #include "core/css/CSSPropertyMetadata.h" #include "core/css/CSSURIValue.h" #include "core/css/CSSValuePair.h" +#include "core/css/CSSVariableReferenceValue.h" #include "core/css/StylePropertySet.h" #include "core/css/StyleRule.h" +#include "core/css/resolver/CSSVariableResolver.h" #include "core/css/resolver/ElementStyleResources.h" #include "core/css/resolver/FilterOperationResolver.h" #include "core/css/resolver/FontBuilder.h" @@ -108,6 +111,11 @@ void StyleBuilder::applyProperty(CSSPropertyID id, StyleResolverState& state, CSSValue* value) { + if (RuntimeEnabledFeatures::cssVariablesEnabled() && id != CSSPropertyVariable && value->isVariableReferenceValue()) { + CSSVariableResolver::resolveAndApplyVariableReferences(state, id, *toCSSVariableReferenceValue(value)); + return; + } + ASSERT_WITH_MESSAGE(!isShorthandProperty(id), "Shorthand property id = %d wasn't expanded at parsing time", id); bool isInherit = state.parentNode() && value->isInheritedValue(); @@ -797,6 +805,34 @@ state.setTextOrientation(toCSSPrimitiveValue(value)->convertTo<TextOrientation>()); } +void StyleBuilderFunctions::applyValueCSSPropertyVariable(StyleResolverState& state, CSSValue* value) +{ + CSSCustomPropertyDeclaration* declaration = toCSSCustomPropertyDeclaration(value); + switch (declaration->id()) { + case CSSValueInitial: + state.style()->removeVariable(declaration->name()); + break; + + case CSSValueUnset: + case CSSValueInherit: { + state.style()->removeVariable(declaration->name()); + StyleVariableData* parentVariables = state.parentStyle()->variables(); + if (!parentVariables) + return; + CSSVariableData* value = parentVariables->getVariable(declaration->name()); + if (!value) + return; + state.style()->setVariable(declaration->name(), value); + break; + } + case CSSValueInternalVariableValue: + state.style()->setVariable(declaration->name(), declaration->value()); + break; + default: + ASSERT_NOT_REACHED(); + } +} + void StyleBuilderFunctions::applyInheritCSSPropertyBaselineShift(StyleResolverState& state) { const SVGComputedStyle& parentSvgStyle = state.parentStyle()->svgStyle();
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp index 8af35a7a..71de34d 100644 --- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp +++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
@@ -61,6 +61,7 @@ #include "core/css/StyleRuleImport.h" #include "core/css/StyleSheetContents.h" #include "core/css/resolver/AnimatedStyleBuilder.h" +#include "core/css/resolver/CSSVariableResolver.h" #include "core/css/resolver/MatchResult.h" #include "core/css/resolver/MediaQueryResult.h" #include "core/css/resolver/ScopedStyleResolver.h" @@ -1230,6 +1231,11 @@ template <CSSPropertyPriority priority> void StyleResolver::applyAllProperty(StyleResolverState& state, CSSValue* allValue, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType) { + // The 'all' property doesn't apply to variables: + // https://drafts.csswg.org/css-variables/#defining-variables + if (priority == ResolveVariables) + return; + unsigned startCSSProperty = CSSPropertyPriorityData<priority>::first(); unsigned endCSSProperty = CSSPropertyPriorityData<priority>::last(); @@ -1369,6 +1375,14 @@ applyInheritedOnly = true; } + // TODO(leviw): We need the proper bit for tracking whether we need to do this work. + if (RuntimeEnabledFeatures::cssVariablesEnabled()) { + applyMatchedProperties<ResolveVariables>(state, matchResult.authorRules(), false, applyInheritedOnly); + applyMatchedProperties<ResolveVariables>(state, matchResult.authorRules(), true, applyInheritedOnly); + // TODO(leviw): stop recalculating every time + CSSVariableResolver::resolveVariableDefinitions(state.style()->variables()); + } + // Now we have all of the matched rules in the appropriate order. Walk the rules and apply // high-priority properties first, i.e., those properties that other properties depend on. // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index ed566c62..7d94d4e6a 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -376,6 +376,7 @@ : ContainerNode(0, CreateDocument) , TreeScope(*this) , m_detachingDocumentLoader(false) + , m_loadEventProgress(LoadEventNotRun) , m_hasNodesWithPlaceholderStyle(false) , m_evaluateMediaQueriesOnStyleRecalc(false) , m_pendingSheetLayout(NoLayoutWithPendingSheets) @@ -409,7 +410,6 @@ , m_markers(adoptPtrWillBeNoop(new DocumentMarkerController)) , m_updateFocusAppearanceTimer(this, &Document::updateFocusAppearanceTimerFired) , m_cssTarget(nullptr) - , m_loadEventProgress(LoadEventNotRun) , m_startTime(currentTime()) , m_scriptRunner(ScriptRunner::create(this)) , m_xmlVersion("1.0") @@ -1633,7 +1633,7 @@ // documentElement's style was dirty. We could keep track of which elements depend on // rem units like we do for viewport styles, but we assume root font size changes are // rare and just invalidate the cache for now. - if (styleEngine().usesRemUnits() && (documentElement()->needsAttach() || documentElement()->ensureComputedStyle()->fontSize() != documentElementStyle->fontSize())) { + if (styleEngine().usesRemUnits() && (documentElement()->needsAttach() || !documentElement()->computedStyle() || documentElement()->computedStyle()->fontSize() != documentElementStyle->fontSize())) { ensureStyleResolver().invalidateMatchedPropertiesCache(); documentElement()->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::FontSizeChange)); } @@ -4691,9 +4691,9 @@ Color Document::themeColor() const { for (HTMLMetaElement* metaElement = head() ? Traversal<HTMLMetaElement>::firstChild(*head()) : 0; metaElement; metaElement = Traversal<HTMLMetaElement>::nextSibling(*metaElement)) { - RGBA32 rgb = Color::transparent; - if (equalIgnoringCase(metaElement->name(), "theme-color") && CSSParser::parseColor(rgb, metaElement->content().string().stripWhiteSpace(), true)) - return Color(rgb); + Color color = Color::transparent; + if (equalIgnoringCase(metaElement->name(), "theme-color") && CSSParser::parseColor(color, metaElement->content().string().stripWhiteSpace(), true)) + return color; } return Color(); } @@ -5445,6 +5445,12 @@ return *(result.storedValue->value); } +AnimationClock& Document::animationClock() +{ + ASSERT(page()); + return page()->animator().clock(); +} + Document& Document::ensureTemplateDocument() { if (isTemplateDocument())
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h index f09478371..18669f2 100644 --- a/third_party/WebKit/Source/core/dom/Document.h +++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -953,7 +953,7 @@ // Return a Locale for the default locale if the argument is null or empty. Locale& getCachedLocale(const AtomicString& locale = nullAtom); - AnimationClock& animationClock() { return m_animationClock; } + AnimationClock& animationClock(); AnimationTimeline& timeline() const { return *m_timeline; } CompositorPendingAnimations& compositorPendingAnimations() { return m_compositorPendingAnimations; } @@ -1150,6 +1150,10 @@ void setNthIndexCache(NthIndexCache* nthIndexCache) { ASSERT(!m_nthIndexCache || !nthIndexCache); m_nthIndexCache = nthIndexCache; } + // TODO(bokan): Temporarily moved this to the top of memebers so it's likely + // to be included in a minidump memory region. crbug.com/519752 + LoadEventProgress m_loadEventProgress; + DocumentLifecycle m_lifecycle; bool m_hasNodesWithPlaceholderStyle; @@ -1255,8 +1259,6 @@ RawPtrWillBeMember<Element> m_cssTarget; - LoadEventProgress m_loadEventProgress; - double m_startTime; OwnPtrWillBeMember<ScriptRunner> m_scriptRunner; @@ -1354,7 +1356,6 @@ using LocaleIdentifierToLocaleMap = HashMap<AtomicString, OwnPtr<Locale>>; LocaleIdentifierToLocaleMap m_localeCache; - AnimationClock m_animationClock; PersistentWillBeMember<AnimationTimeline> m_timeline; CompositorPendingAnimations m_compositorPendingAnimations;
diff --git a/third_party/WebKit/Source/core/dom/Document.idl b/third_party/WebKit/Source/core/dom/Document.idl index 360e467..3f71ed5 100644 --- a/third_party/WebKit/Source/core/dom/Document.idl +++ b/third_party/WebKit/Source/core/dom/Document.idl
@@ -97,8 +97,7 @@ // DOM tree accessors [CustomElementCallbacks] attribute DOMString title; - // FIXME: dir should not have [TreatNullAs=NullString]. - [TreatNullAs=NullString, CustomElementCallbacks] attribute DOMString dir; + [CustomElementCallbacks] attribute DOMString dir; [RaisesException=Setter, CustomElementCallbacks, PerWorldBindings, TypeChecking=Interface] attribute HTMLElement? body; readonly attribute HTMLHeadElement? head; [SameObject] readonly attribute HTMLCollection images;
diff --git a/third_party/WebKit/Source/core/dom/DocumentLifecycle.cpp b/third_party/WebKit/Source/core/dom/DocumentLifecycle.cpp index f1989fa..20a3fb5c 100644 --- a/third_party/WebKit/Source/core/dom/DocumentLifecycle.cpp +++ b/third_party/WebKit/Source/core/dom/DocumentLifecycle.cpp
@@ -233,32 +233,12 @@ case PaintClean: if (!RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) break; - if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { - if (nextState == InStyleRecalc) - return true; - if (nextState == InPreLayout) - return true; - if (nextState == InCompositingUpdate) - return true; - } - if (nextState == InCompositingForSlimmingPaintV2 && RuntimeEnabledFeatures::slimmingPaintV2Enabled()) - return true; - break; - case InCompositingForSlimmingPaintV2: - if (nextState == CompositingForSlimmingPaintV2Clean && RuntimeEnabledFeatures::slimmingPaintV2Enabled()) - return true; - break; - case CompositingForSlimmingPaintV2Clean: - if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) - return false; if (nextState == InStyleRecalc) return true; if (nextState == InPreLayout) return true; if (nextState == InCompositingUpdate) return true; - if (nextState == CompositingForSlimmingPaintV2Clean) - return true; break; case Stopping: return nextState == Stopped; @@ -283,8 +263,7 @@ || m_state == LayoutClean || m_state == CompositingClean || m_state == PaintInvalidationClean - || (m_state == PaintClean && RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) - || (m_state == CompositingForSlimmingPaintV2Clean && RuntimeEnabledFeatures::slimmingPaintV2Enabled()); + || (m_state == PaintClean && RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()); } #endif @@ -337,8 +316,6 @@ DEBUG_STRING_CASE(UpdatePaintPropertiesClean); DEBUG_STRING_CASE(InPaint); DEBUG_STRING_CASE(PaintClean); - DEBUG_STRING_CASE(InCompositingForSlimmingPaintV2); - DEBUG_STRING_CASE(CompositingForSlimmingPaintV2Clean); DEBUG_STRING_CASE(Stopping); DEBUG_STRING_CASE(Stopped); DEBUG_STRING_CASE(Disposed);
diff --git a/third_party/WebKit/Source/core/dom/DocumentLifecycle.h b/third_party/WebKit/Source/core/dom/DocumentLifecycle.h index 130572e..2b02d8dd 100644 --- a/third_party/WebKit/Source/core/dom/DocumentLifecycle.h +++ b/third_party/WebKit/Source/core/dom/DocumentLifecycle.h
@@ -76,10 +76,6 @@ InPaint, PaintClean, - // When RuntimeEnabledFeatures::slimmingPaintV2Enabled. - InCompositingForSlimmingPaintV2, - CompositingForSlimmingPaintV2Clean, - // Once the document starts shutting down, we cannot return // to the style/layout/compositing states. Stopping, @@ -189,8 +185,7 @@ && m_state != InPerformLayout && m_state != InCompositingUpdate && m_state != InUpdatePaintProperties - && m_state != InPaint - && m_state != InCompositingForSlimmingPaintV2; + && m_state != InPaint; } inline bool DocumentLifecycle::stateAllowsLayoutTreeMutations() const @@ -215,7 +210,6 @@ || m_state == PaintInvalidationClean || m_state == UpdatePaintPropertiesClean || m_state == PaintClean - || m_state == CompositingForSlimmingPaintV2Clean || m_state == Stopping; } @@ -225,8 +219,7 @@ && m_state != InCompositingUpdate && m_state != InPaintInvalidation && m_state != InUpdatePaintProperties - && m_state != InPaint - && m_state != InCompositingForSlimmingPaintV2; + && m_state != InPaint; } } // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/ScriptRunner.cpp b/third_party/WebKit/Source/core/dom/ScriptRunner.cpp index c93aaa2b..fb555bb 100644 --- a/third_party/WebKit/Source/core/dom/ScriptRunner.cpp +++ b/third_party/WebKit/Source/core/dom/ScriptRunner.cpp
@@ -200,16 +200,24 @@ // to detach). RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(m_pendingAsyncScripts.contains(scriptLoader)); m_pendingAsyncScripts.remove(scriptLoader); - scriptLoader->detach(); - m_document->decrementLoadEventDelayCount(); break; case IN_ORDER_EXECUTION: RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(m_numberOfInOrderScriptsWithPendingNotification > 0); m_numberOfInOrderScriptsWithPendingNotification--; + auto it = m_pendingInOrderScripts.begin(); + for (; it != m_pendingInOrderScripts.end(); ++it) { + if (*it == scriptLoader) { + m_pendingInOrderScripts.remove(it); + break; + } + } + RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(it != m_pendingInOrderScripts.end()); break; } + scriptLoader->detach(); + m_document->decrementLoadEventDelayCount(); } void ScriptRunner::movePendingAsyncScript(Document& oldDocument, Document& newDocument, ScriptLoader* scriptLoader)
diff --git a/third_party/WebKit/Source/core/dom/TextLinkColors.cpp b/third_party/WebKit/Source/core/dom/TextLinkColors.cpp index 10b70d9..56d1cbd 100644 --- a/third_party/WebKit/Source/core/dom/TextLinkColors.cpp +++ b/third_party/WebKit/Source/core/dom/TextLinkColors.cpp
@@ -62,7 +62,7 @@ Color TextLinkColors::colorFromCSSValue(const CSSValue& value, Color currentColor, bool forVisitedLink) const { if (value.isColorValue()) - return Color(toCSSColorValue(value).value()); + return toCSSColorValue(value).value(); CSSValueID valueID = toCSSPrimitiveValue(value).getValueID(); switch (valueID) {
diff --git a/third_party/WebKit/Source/core/editing/EditingStyle.cpp b/third_party/WebKit/Source/core/editing/EditingStyle.cpp index 150cc17..3a9cc01 100644 --- a/third_party/WebKit/Source/core/editing/EditingStyle.cpp +++ b/third_party/WebKit/Source/core/editing/EditingStyle.cpp
@@ -161,7 +161,7 @@ static bool isTransparentColorValue(CSSValue*); static bool hasTransparentBackgroundColor(CSSStyleDeclaration*); static bool hasTransparentBackgroundColor(StylePropertySet*); -static PassRefPtrWillBeRawPtr<CSSValue> backgroundColorInEffect(Node*); +static PassRefPtrWillBeRawPtr<CSSValue> backgroundColorValueInEffect(Node*); class HTMLElementEquivalent : public NoBaseWillBeGarbageCollected<HTMLElementEquivalent> { USING_FAST_MALLOC_WILL_BE_REMOVED(HTMLElementEquivalent); @@ -395,7 +395,7 @@ { } -static RGBA32 cssValueToRGBA(CSSValue* colorValue) +static Color cssValueToColor(CSSValue* colorValue) { if (!colorValue || (!colorValue->isColorValue() && !colorValue->isPrimitiveValue())) return Color::transparent; @@ -403,35 +403,35 @@ if (colorValue->isColorValue()) return toCSSColorValue(colorValue)->value(); - RGBA32 rgba = 0; + Color color = 0; // FIXME: Why ignore the return value? - CSSParser::parseColor(rgba, colorValue->cssText()); - return rgba; + CSSParser::parseColor(color, colorValue->cssText()); + return color; } -static inline RGBA32 getRGBAFontColor(CSSStyleDeclaration* style) +static inline Color getFontColor(CSSStyleDeclaration* style) { - return cssValueToRGBA(style->getPropertyCSSValueInternal(CSSPropertyColor).get()); + return cssValueToColor(style->getPropertyCSSValueInternal(CSSPropertyColor).get()); } -static inline RGBA32 getRGBAFontColor(StylePropertySet* style) +static inline Color getFontColor(StylePropertySet* style) { - return cssValueToRGBA(style->getPropertyCSSValue(CSSPropertyColor).get()); + return cssValueToColor(style->getPropertyCSSValue(CSSPropertyColor).get()); } -static inline RGBA32 getRGBABackgroundColor(CSSStyleDeclaration* style) +static inline Color getBackgroundColor(CSSStyleDeclaration* style) { - return cssValueToRGBA(style->getPropertyCSSValueInternal(CSSPropertyBackgroundColor).get()); + return cssValueToColor(style->getPropertyCSSValueInternal(CSSPropertyBackgroundColor).get()); } -static inline RGBA32 getRGBABackgroundColor(StylePropertySet* style) +static inline Color getBackgroundColor(StylePropertySet* style) { - return cssValueToRGBA(style->getPropertyCSSValue(CSSPropertyBackgroundColor).get()); + return cssValueToColor(style->getPropertyCSSValue(CSSPropertyBackgroundColor).get()); } -static inline RGBA32 rgbaBackgroundColorInEffect(Node* node) +static inline Color backgroundColorInEffect(Node* node) { - return cssValueToRGBA(backgroundColorInEffect(node).get()); + return cssValueToColor(backgroundColorValueInEffect(node).get()); } static int textAlignResolvingStartAndEnd(int textAlign, int direction) @@ -473,7 +473,7 @@ m_mutableStyle = propertiesToInclude == AllProperties && computedStyleAtPosition ? computedStyleAtPosition->copyProperties() : editingStyleFromComputedStyle(computedStyleAtPosition); if (propertiesToInclude == EditingPropertiesInEffect) { - if (RefPtrWillBeRawPtr<CSSValue> value = backgroundColorInEffect(node)) + if (RefPtrWillBeRawPtr<CSSValue> value = backgroundColorValueInEffect(node)) m_mutableStyle->setProperty(CSSPropertyBackgroundColor, value->cssText()); if (RefPtrWillBeRawPtr<CSSValue> value = computedStyleAtPosition->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect)) m_mutableStyle->setProperty(CSSPropertyTextDecoration, value->cssText()); @@ -1005,11 +1005,11 @@ if (textAlignResolvingStartAndEnd(m_mutableStyle.get()) == textAlignResolvingStartAndEnd(styleAtPosition)) m_mutableStyle->removeProperty(CSSPropertyTextAlign); - if (getRGBAFontColor(m_mutableStyle.get()) == getRGBAFontColor(styleAtPosition)) + if (getFontColor(m_mutableStyle.get()) == getFontColor(styleAtPosition)) m_mutableStyle->removeProperty(CSSPropertyColor); if (hasTransparentBackgroundColor(m_mutableStyle.get()) - || cssValueToRGBA(m_mutableStyle->getPropertyCSSValue(CSSPropertyBackgroundColor).get()) == rgbaBackgroundColorInEffect(position.computeContainerNode())) + || cssValueToColor(m_mutableStyle->getPropertyCSSValue(CSSPropertyBackgroundColor).get()) == backgroundColorInEffect(position.computeContainerNode())) m_mutableStyle->removeProperty(CSSPropertyBackgroundColor); if (unicodeBidi && unicodeBidi->isPrimitiveValue()) { @@ -1339,7 +1339,7 @@ // and find the background color of the common ancestor. if (shouldUseBackgroundColorInEffect && (selection.isRange() || hasTransparentBackgroundColor(style->m_mutableStyle.get()))) { const EphemeralRange range(selection.toNormalizedEphemeralRange()); - if (PassRefPtrWillBeRawPtr<CSSValue> value = backgroundColorInEffect(Range::commonAncestorContainer(range.startPosition().computeContainerNode(), range.endPosition().computeContainerNode()))) + if (PassRefPtrWillBeRawPtr<CSSValue> value = backgroundColorValueInEffect(Range::commonAncestorContainer(range.startPosition().computeContainerNode(), range.endPosition().computeContainerNode()))) style->setProperty(CSSPropertyBackgroundColor, value->cssText()); } @@ -1544,7 +1544,7 @@ } if (style->getPropertyCSSValue(CSSPropertyColor)) { - m_applyFontColor = Color(getRGBAFontColor(style)).serialized(); + m_applyFontColor = getFontColor(style).serialized(); style->removeProperty(CSSPropertyColor); } @@ -1636,14 +1636,14 @@ } } - if (baseStyle->getPropertyCSSValueInternal(CSSPropertyColor) && getRGBAFontColor(result.get()) == getRGBAFontColor(baseStyle)) + if (baseStyle->getPropertyCSSValueInternal(CSSPropertyColor) && getFontColor(result.get()) == getFontColor(baseStyle)) result->removeProperty(CSSPropertyColor); if (baseStyle->getPropertyCSSValueInternal(CSSPropertyTextAlign) && textAlignResolvingStartAndEnd(result.get()) == textAlignResolvingStartAndEnd(baseStyle)) result->removeProperty(CSSPropertyTextAlign); - if (baseStyle->getPropertyCSSValueInternal(CSSPropertyBackgroundColor) && getRGBABackgroundColor(result.get()) == getRGBABackgroundColor(baseStyle)) + if (baseStyle->getPropertyCSSValueInternal(CSSPropertyBackgroundColor) && getBackgroundColor(result.get()) == getBackgroundColor(baseStyle)) result->removeProperty(CSSPropertyBackgroundColor); return result.release(); @@ -1695,7 +1695,7 @@ if (!cssValue) return true; if (cssValue->isColorValue()) - return !alphaChannel(toCSSColorValue(cssValue)->value()); + return !toCSSColorValue(cssValue)->value().alpha(); if (!cssValue->isPrimitiveValue()) return false; CSSPrimitiveValue* value = toCSSPrimitiveValue(cssValue); @@ -1714,7 +1714,7 @@ return isTransparentColorValue(cssValue.get()); } -PassRefPtrWillBeRawPtr<CSSValue> backgroundColorInEffect(Node* node) +PassRefPtrWillBeRawPtr<CSSValue> backgroundColorValueInEffect(Node* node) { for (Node* ancestor = node; ancestor; ancestor = ancestor->parentNode()) { RefPtrWillBeRawPtr<CSSComputedStyleDeclaration> ancestorStyle = CSSComputedStyleDeclaration::create(ancestor);
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp index 2c03798..ff9ded7 100644 --- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp +++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
@@ -650,11 +650,6 @@ setSelection(VisibleSelection(selection().base(), pos.deepEquivalent(), pos.affinity(), selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered); } -static bool isNonOrphanedCaret(const VisibleSelection& selection) -{ - return selection.isCaret() && !selection.start().isOrphan() && !selection.end().isOrphan(); -} - static bool isTextFormControl(const VisibleSelection& selection) { return enclosingTextFormControl(selection.start()); @@ -662,16 +657,18 @@ LayoutBlock* FrameSelection::caretLayoutObject() const { - if (!isNonOrphanedCaret(selection())) + ASSERT(selection().isValidFor(*m_frame->document())); + if (!isCaret()) return nullptr; return CaretBase::caretLayoutObject(selection().start().anchorNode()); } IntRect FrameSelection::absoluteCaretBounds() { + ASSERT(selection().isValidFor(*m_frame->document())); ASSERT(m_frame->document()->lifecycle().state() != DocumentLifecycle::InPaintInvalidation); m_frame->document()->updateLayoutIgnorePendingStylesheets(); - if (!isNonOrphanedCaret(selection())) { + if (!isCaret()) { clearCaretRect(); } else { if (isTextFormControl(selection())) @@ -682,23 +679,17 @@ return absoluteBoundsForLocalRect(selection().start().anchorNode(), localCaretRectWithoutUpdate()); } -static LayoutRect localCaretRect(const VisibleSelection& selection, const PositionWithAffinity& caretPosition, LayoutObject*& layoutObject) -{ - layoutObject = nullptr; - if (!isNonOrphanedCaret(selection)) - return LayoutRect(); - - return localCaretRectOfPosition(caretPosition, layoutObject); -} - void FrameSelection::invalidateCaretRect() { if (!m_caretRectDirty) return; m_caretRectDirty = false; + ASSERT(selection().isValidFor(*m_frame->document())); LayoutObject* layoutObject = nullptr; - LayoutRect newRect = localCaretRect(selection(), PositionWithAffinity(selection().start(), selection().affinity()), layoutObject); + LayoutRect newRect; + if (selection().isCaret()) + newRect = localCaretRectOfPosition(PositionWithAffinity(selection().start(), selection().affinity()), layoutObject); Node* newNode = layoutObject ? layoutObject->node() : nullptr; if (!m_caretBlinkTimer.isActive() @@ -712,7 +703,6 @@ invalidateLocalCaretRect(m_previousCaretNode.get(), m_previousCaretRect); if (newNode && (shouldRepaintCaret(*newNode) || shouldRepaintCaret(view))) invalidateLocalCaretRect(newNode, newRect); - m_previousCaretNode = newNode; m_previousCaretRect = newRect; m_previousCaretVisibility = caretVisibility();
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp index e09358a..2deec3bb 100644 --- a/third_party/WebKit/Source/core/frame/FrameView.cpp +++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -2438,18 +2438,14 @@ if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) updatePaintProperties(); - if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled() && !m_frame->document()->printing()) { + if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled() && !m_frame->document()->printing()) synchronizedPaint(); - if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) - compositeForSlimmingPaintV2(); - } if (RuntimeEnabledFeatures::frameTimingSupportEnabled()) updateFrameTimingRequestsIfNeeded(); ASSERT(!view->hasPendingSelection()); ASSERT(lifecycle().state() == DocumentLifecycle::PaintInvalidationClean - || (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && lifecycle().state() == DocumentLifecycle::CompositingForSlimmingPaintV2Clean) || (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled() && lifecycle().state() == DocumentLifecycle::PaintClean)); } } @@ -2478,22 +2474,14 @@ // A null graphics layer can occur for painting of SVG images that are not parented into the main frame tree, // or when the FrameView is the main frame view of a page overlay. The page overlay is in the layer tree of // the host page and will be painted during synchronized painting of the host page. - if (GraphicsLayer* rootGraphicsLayer = view->layer()->graphicsLayerBacking()) { - if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { - // TODO(wangxianzhu,chrishtr): What about the extra graphics layers for overflow control, virtual viewport, etc? - if (rootGraphicsLayer->drawsContent()) { - GraphicsContext context(*rootGraphicsLayer->paintController()); - rootGraphicsLayer->paint(context, nullptr); - } - } else { - // Find the real root GraphicsLayer because we also need to paint layers not under the root graphics layer of - // the LayoutView, e.g. scrollbar layers created by PaintLayerCompositor and VisualViewport. - // We could ask PaintLayerCompositor and VisualViewport for the real root GraphicsLayer, but the following loop - // has the least dependency to those things which might change for slimming paint v2. - while (GraphicsLayer* parent = rootGraphicsLayer->parent()) - rootGraphicsLayer = parent; - synchronizedPaintRecursively(rootGraphicsLayer); - } + if (GraphicsLayer* rootGraphicsLayer = view->compositor()->rootGraphicsLayer()) { + // Find the real root GraphicsLayer because we also need to paint layers not under the root graphics layer of + // the LayoutView, e.g. scrollbar layers created by PaintLayerCompositor and VisualViewport. + // We could ask PaintLayerCompositor and VisualViewport for the real root GraphicsLayer, but the following loop + // has the least dependency to those things which might change for slimming paint v2. + while (GraphicsLayer* parent = rootGraphicsLayer->parent()) + rootGraphicsLayer = parent; + synchronizedPaintRecursively(rootGraphicsLayer); } forAllNonThrottledFrameViews([](FrameView& frameView) { @@ -2505,38 +2493,25 @@ void FrameView::synchronizedPaintRecursively(GraphicsLayer* graphicsLayer) { if (graphicsLayer->drawsContent()) { - ASSERT(!RuntimeEnabledFeatures::slimmingPaintV2Enabled()); ASSERT(graphicsLayer->paintController()); - GraphicsContext context(*graphicsLayer->paintController()); graphicsLayer->paint(context, nullptr); graphicsLayer->paintController()->commitNewDisplayItems(); } - if (GraphicsLayer* maskLayer = graphicsLayer->maskLayer()) - synchronizedPaintRecursively(maskLayer); - if (GraphicsLayer* contentsClippingMaskLayer = graphicsLayer->contentsClippingMaskLayer()) - synchronizedPaintRecursively(contentsClippingMaskLayer); - if (GraphicsLayer* replicaLayer = graphicsLayer->replicaLayer()) - synchronizedPaintRecursively(replicaLayer); + if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { + if (GraphicsLayer* maskLayer = graphicsLayer->maskLayer()) + synchronizedPaintRecursively(maskLayer); + if (GraphicsLayer* contentsClippingMaskLayer = graphicsLayer->contentsClippingMaskLayer()) + synchronizedPaintRecursively(contentsClippingMaskLayer); + if (GraphicsLayer* replicaLayer = graphicsLayer->replicaLayer()) + synchronizedPaintRecursively(replicaLayer); + } for (auto& child : graphicsLayer->children()) synchronizedPaintRecursively(child); } -void FrameView::compositeForSlimmingPaintV2() -{ - ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); - ASSERT(frame() == page()->mainFrame() || (!frame().tree().parent()->isLocalFrame())); - - forAllNonThrottledFrameViews([](FrameView& frameView) { frameView.lifecycle().advanceTo(DocumentLifecycle::InCompositingForSlimmingPaintV2); }); - - if (GraphicsLayer* rootGraphicsLayer = layoutView()->layer()->graphicsLayerBacking()) - rootGraphicsLayer->paintController()->commitNewDisplayItems(); - - forAllNonThrottledFrameViews([](FrameView& frameView) { frameView.lifecycle().advanceTo(DocumentLifecycle::CompositingForSlimmingPaintV2Clean); }); -} - void FrameView::updateFrameTimingRequestsIfNeeded() { GraphicsLayerFrameTimingRequests graphicsLayerTimingRequests;
diff --git a/third_party/WebKit/Source/core/frame/FrameView.h b/third_party/WebKit/Source/core/frame/FrameView.h index bae313f..e6bea1c 100644 --- a/third_party/WebKit/Source/core/frame/FrameView.h +++ b/third_party/WebKit/Source/core/frame/FrameView.h
@@ -638,7 +638,6 @@ void updatePaintProperties(); void synchronizedPaint(); void synchronizedPaintRecursively(GraphicsLayer*); - void compositeForSlimmingPaintV2(); void reset(); void init();
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp index ef87a99..d697f96 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp +++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -133,11 +133,6 @@ if (!doc) return; - // I suspect this check wont trip since it's checked a little higher up in the call stack - // in HTMLFrameOwnerElement::loadOrRedirectSubframe, unless we're somehow navigating the - // frame from an unexpected direction. - RELEASE_ASSERT(!doc->unloadStarted()); - // I added this flag that gets set to true just before detaching the document loader. This // should trip and will hopefully illuminate why the loadEventProgress state isn't stopping // navigation.
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.cpp b/third_party/WebKit/Source/core/frame/UseCounter.cpp index b03710a..829856f 100644 --- a/third_party/WebKit/Source/core/frame/UseCounter.cpp +++ b/third_party/WebKit/Source/core/frame/UseCounter.cpp
@@ -547,6 +547,7 @@ case CSSPropertyGridRowGap: return 512; case CSSPropertyGridGap: return 513; case CSSPropertyFontFeatureSettings: return 514; + case CSSPropertyVariable: return 515; // 1. Add new features above this line (don't change the assigned numbers of the existing // items). @@ -563,7 +564,7 @@ return 0; } -static int maximumCSSSampleId() { return 514; } +static int maximumCSSSampleId() { return 515; } void UseCounter::muteForInspector() {
diff --git a/third_party/WebKit/Source/core/html/HTMLBodyElement.cpp b/third_party/WebKit/Source/core/html/HTMLBodyElement.cpp index 64f599f..21e19fca 100644 --- a/third_party/WebKit/Source/core/html/HTMLBodyElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLBodyElement.cpp
@@ -93,7 +93,7 @@ else document().textLinkColors().resetActiveLinkColor(); } else { - RGBA32 color; + Color color; if (CSSParser::parseColor(color, value, !document().inQuirksMode())) { if (name == linkAttr) document().textLinkColors().setLinkColor(color);
diff --git a/third_party/WebKit/Source/core/layout/ColumnBalancer.cpp b/third_party/WebKit/Source/core/layout/ColumnBalancer.cpp index d56a08a..65d3f4c 100644 --- a/third_party/WebKit/Source/core/layout/ColumnBalancer.cpp +++ b/third_party/WebKit/Source/core/layout/ColumnBalancer.cpp
@@ -66,7 +66,7 @@ examineBoxAfterEntering(childBox); // Unless the child is unsplittable, or if the child establishes an inner multicol // container, we descend into its subtree for further examination. - if (!childBox.isUnsplittableForPagination() + if (childBox.paginationBreakability() != LayoutBox::ForbidBreaks && (!childBox.isLayoutBlockFlow() || !toLayoutBlockFlow(childBox).multiColumnFlowThread())) traverseSubtree(childBox); examineBoxBeforeLeaving(childBox); @@ -216,10 +216,11 @@ // Look for breaks before the child box. bool isFirstAfterBreak = this->isFirstAfterBreak(flowThreadOffset()); ASSERT(isFirstAfterBreak || !box.paginationStrut()); + LayoutBox::PaginationBreakability breakability = box.paginationBreakability(); if (isFirstAfterBreak && !box.hasForcedBreakBefore()) { // This box is first after a soft break. LayoutUnit strut = box.paginationStrut(); - if (box.isUnsplittableForPagination()) { + if (breakability == LayoutBox::ForbidBreaks) { // Since we cannot break inside the box, just figure out how much more space we would // need to prevent it from being pushed to the next column. recordSpaceShortage(box.logicalHeight() - strut); @@ -233,7 +234,7 @@ } } - if (!box.isUnsplittableForPagination()) { + if (breakability != LayoutBox::ForbidBreaks) { // See if this breakable box crosses column boundaries. LayoutUnit bottomInFlowThread = flowThreadOffset() + box.logicalHeight(); if (isFirstAfterBreak || group().columnLogicalTopForOffset(flowThreadOffset()) != group().columnLogicalTopForOffset(bottomInFlowThread)) { @@ -250,7 +251,7 @@ void MinimumSpaceShortageFinder::examineBoxBeforeLeaving(const LayoutBox& box) { - if (m_pendingStrut == LayoutUnit::min() || !box.isUnsplittableForPagination()) + if (m_pendingStrut == LayoutUnit::min() || box.paginationBreakability() != LayoutBox::ForbidBreaks) return; // The previous break was before a breakable block. Here's the first piece of unbreakable
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp index 0cea0eb..e61715ff 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
@@ -625,8 +625,12 @@ // There are still block children in the container, so any anonymous wrappers are still needed. if (!child->isAnonymousBlock()) return; + // If one of the children is being destroyed then it is unsafe to clean up anonymous wrappers as the + // entire branch may be being destroyed. + if (toLayoutBlock(child)->beingDestroyed()) + return; // We can't remove anonymous wrappers if they contain continuations as this means there are block children present. - if (child->isLayoutBlock() && toLayoutBlock(child)->continuation()) + if (toLayoutBlock(child)->continuation()) return; // We are only interested in removing anonymous wrappers if there are inline siblings underneath them. if (!child->childrenInline()) @@ -1219,7 +1223,7 @@ positionedObject->setPreferredLogicalWidthsDirty(MarkOnlyThis); LayoutUnit logicalTopEstimate; - bool needsBlockDirectionLocationSetBeforeLayout = isPaginated && !positionedObject->isUnsplittableForPagination(); + bool needsBlockDirectionLocationSetBeforeLayout = isPaginated && positionedObject->paginationBreakability() != ForbidBreaks; if (needsBlockDirectionLocationSetBeforeLayout) { // Out-of-flow objects are normally positioned after layout (while in-flow objects are // positioned before layout). If the child object is paginated in the same context as
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp index 0355ea0e..e394118 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -838,11 +838,7 @@ LayoutUnit LayoutBlockFlow::adjustForUnsplittableChild(LayoutBox& child, LayoutUnit logicalOffset) { - bool checkColumnBreaks = flowThreadContainingBlock(); - bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->pageLogicalHeight(); - bool isUnsplittable = child.isUnsplittableForPagination() || (checkColumnBreaks && child.style()->columnBreakInside() == PBAVOID) - || (checkPageBreaks && child.style()->pageBreakInside() == PBAVOID); - if (!isUnsplittable) + if (child.paginationBreakability() == AllowAnyBreaks) return logicalOffset; LayoutUnit childLogicalHeight = logicalHeightForChild(child); // Floats' margins do not collapse with page or column boundaries.
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp index 11c92ae1..4319671 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -4406,12 +4406,21 @@ || (!style()->logicalMinHeight().isIntrinsicOrAuto() && style()->logicalMinHeight().isPositive() && (!style()->logicalMinHeight().hasPercent() || percentageLogicalHeightIsResolvable())); } -bool LayoutBox::isUnsplittableForPagination() const +LayoutBox::PaginationBreakability LayoutBox::paginationBreakability() const { - return isReplaced() + if (isReplaced() || hasUnsplittableScrollingOverflow() || (parent() && isWritingModeRoot()) - || (isOutOfFlowPositioned() && style()->position() == FixedPosition); + || (isOutOfFlowPositioned() && style()->position() == FixedPosition)) + return ForbidBreaks; + + bool checkColumnBreaks = flowThreadContainingBlock(); + bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->pageLogicalHeight(); + bool isUnsplittable = (checkColumnBreaks && style()->columnBreakInside() == PBAVOID) + || (checkPageBreaks && style()->pageBreakInside() == PBAVOID); + if (isUnsplittable) + return AvoidBreaks; + return AllowAnyBreaks; } LayoutUnit LayoutBox::lineHeight(bool /*firstLine*/, LineDirectionMode direction, LinePositionMode /*linePositionMode*/) const
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.h b/third_party/WebKit/Source/core/layout/LayoutBox.h index 5f22bb6..d61344e 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.h +++ b/third_party/WebKit/Source/core/layout/LayoutBox.h
@@ -692,7 +692,14 @@ virtual bool isIntrinsicallyScrollable(ScrollbarOrientation orientation) const { return false; } bool hasUnsplittableScrollingOverflow() const; - bool isUnsplittableForPagination() const; + + // Page / column breakability inside block-level objects. + enum PaginationBreakability { + AllowAnyBreaks, // No restrictions on breaking. May examine children to find possible break points. + ForbidBreaks, // Forbid breaks inside this object. Content cannot be split nicely into smaller pieces. + AvoidBreaks // Preferably avoid breaks. If not possible, examine children to find possible break points. + }; + PaginationBreakability paginationBreakability() const; LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = nullptr) override;
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp index 5035d2b..2ce5335c 100644 --- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
@@ -383,6 +383,10 @@ { if (child.isHorizontalWritingMode() && needToStretchChildLogicalHeight(child)) return constrainedChildIntrinsicContentLogicalHeight(child); + // If our height is auto, make sure that our returned height is unaffected by earlier layouts by + // returning the max preferred height (=logical width) + if (!child.isHorizontalWritingMode() && child.styleRef().height().isAuto()) + return child.maxPreferredLogicalWidth(); return child.size().height(); } @@ -390,6 +394,7 @@ { if (!child.isHorizontalWritingMode() && needToStretchChildLogicalHeight(child)) return constrainedChildIntrinsicContentLogicalHeight(child); + // TOOO(cbiesinger): should this return the maxPreferredLogicalWidth? return child.size().width(); } @@ -667,7 +672,6 @@ return LayoutUnit(); if (child.needsLayout() || childLayoutType == ForceLayout || !m_intrinsicSizeAlongMainAxis.contains(&child)) { - m_intrinsicSizeAlongMainAxis.remove(&child); child.forceChildLayout(); m_intrinsicSizeAlongMainAxis.set(&child, hasOrthogonalFlow(child) ? child.logicalHeight() : child.logicalWidth()); } @@ -946,8 +950,12 @@ // If this condition is true, then computeMainAxisExtentForChild will call child.contentLogicalHeight() // and child.scrollbarLogicalHeight(), so if the child has intrinsic min/max/preferred size, // run layout on it now to make sure its logical height and scroll bars are up-to-date. - if (childHasIntrinsicMainAxisSize(*child)) + if (childHasIntrinsicMainAxisSize(*child)) { + child->clearOverrideSize(); child->layoutIfNeeded(); + // Keep our cache up-to-date + m_intrinsicSizeAlongMainAxis.set(child, hasOrthogonalFlow(*child) ? child->logicalHeight() : child->logicalWidth()); + } LayoutUnit childInnerFlexBaseSize = computeInnerFlexBaseSizeForChild(*child, relayoutChildren ? ForceLayout : LayoutIfNeeded); LayoutUnit childMainAxisMarginBorderPadding = mainAxisBorderAndPaddingExtentForChild(*child) @@ -1141,13 +1149,17 @@ { // This function is a little bit magical. It relies on the fact that blocks intrinsically // "stretch" themselves in their inline axis, i.e. a <div> has an implicit width: 100%. - // Therefore, we never need to stretch an item if we're a vertical flow, because the child - // will automatically stretch itself. - // TODO(cbiesinger): this code is wrong when the child has an orthogonal flow and we're vertical. crbug.com/482766 + // So the child will automatically stretch if our cross axis is the child's inline axis. That's the case if: + // - We are horizontal and the child is in vertical writing mode + // - We are vertical and the child is in horizontal writing mode + // Otherwise, we need to stretch if the cross axis size is auto. if (alignmentForChild(child) != ItemPositionStretch) return false; - return isHorizontalFlow() && child.style()->height().isAuto(); + if (isHorizontalFlow() != child.styleRef().isHorizontalWritingMode()) + return false; + + return isHorizontalFlow() ? child.styleRef().height().isAuto() : child.styleRef().width().isAuto(); } bool LayoutFlexibleBox::childHasIntrinsicMainAxisSize(const LayoutBox& child) const @@ -1459,38 +1471,32 @@ void LayoutFlexibleBox::applyStretchAlignmentToChild(LayoutBox& child, LayoutUnit lineCrossAxisExtent) { - if (!isColumnFlow() && child.style()->logicalHeight().isAuto()) { - // FIXME: If the child has orthogonal flow, then it already has an override height set, so use it. - if (!hasOrthogonalFlow(child)) { - LayoutUnit heightBeforeStretching = needToStretchChildLogicalHeight(child) ? constrainedChildIntrinsicContentLogicalHeight(child) : child.logicalHeight(); - LayoutUnit stretchedLogicalHeight = std::max(child.borderAndPaddingLogicalHeight(), heightBeforeStretching + availableAlignmentSpaceForChildBeforeStretching(lineCrossAxisExtent, child)); - ASSERT(!child.needsLayout()); - LayoutUnit desiredLogicalHeight = child.constrainLogicalHeightByMinMax(stretchedLogicalHeight, heightBeforeStretching - child.borderAndPaddingLogicalHeight()); + if (!hasOrthogonalFlow(child) && child.style()->logicalHeight().isAuto()) { + LayoutUnit heightBeforeStretching = needToStretchChildLogicalHeight(child) ? constrainedChildIntrinsicContentLogicalHeight(child) : child.logicalHeight(); + LayoutUnit stretchedLogicalHeight = std::max(child.borderAndPaddingLogicalHeight(), heightBeforeStretching + availableAlignmentSpaceForChildBeforeStretching(lineCrossAxisExtent, child)); + ASSERT(!child.needsLayout()); + LayoutUnit desiredLogicalHeight = child.constrainLogicalHeightByMinMax(stretchedLogicalHeight, heightBeforeStretching - child.borderAndPaddingLogicalHeight()); - // FIXME: Can avoid laying out here in some cases. See https://webkit.org/b/87905. - bool childNeedsRelayout = desiredLogicalHeight != child.logicalHeight(); - if (childNeedsRelayout || !child.hasOverrideLogicalContentHeight()) - child.setOverrideLogicalContentHeight(desiredLogicalHeight - child.borderAndPaddingLogicalHeight()); - if (childNeedsRelayout) { - child.setLogicalHeight(0); - // We cache the child's intrinsic content logical height to avoid it being reset to the stretched height. - // FIXME: This is fragile. LayoutBoxes should be smart enough to determine their intrinsic content logical - // height correctly even when there's an overrideHeight. - LayoutUnit childIntrinsicContentLogicalHeight = child.intrinsicContentLogicalHeight(); - child.forceChildLayout(); - child.setIntrinsicContentLogicalHeight(childIntrinsicContentLogicalHeight); - } + // FIXME: Can avoid laying out here in some cases. See https://webkit.org/b/87905. + bool childNeedsRelayout = desiredLogicalHeight != child.logicalHeight(); + if (childNeedsRelayout || !child.hasOverrideLogicalContentHeight()) + child.setOverrideLogicalContentHeight(desiredLogicalHeight - child.borderAndPaddingLogicalHeight()); + if (childNeedsRelayout) { + child.setLogicalHeight(0); + // We cache the child's intrinsic content logical height to avoid it being reset to the stretched height. + // FIXME: This is fragile. LayoutBoxes should be smart enough to determine their intrinsic content logical + // height correctly even when there's an overrideHeight. + LayoutUnit childIntrinsicContentLogicalHeight = child.intrinsicContentLogicalHeight(); + child.forceChildLayout(); + child.setIntrinsicContentLogicalHeight(childIntrinsicContentLogicalHeight); } - } else if (isColumnFlow() && child.style()->logicalWidth().isAuto()) { - // FIXME: If the child doesn't have orthogonal flow, then it already has an override width set, so use it. - if (hasOrthogonalFlow(child)) { - LayoutUnit childWidth = std::max<LayoutUnit>(0, lineCrossAxisExtent - crossAxisMarginExtentForChild(child)); - childWidth = child.constrainLogicalWidthByMinMax(childWidth, childWidth, this); + } else if (hasOrthogonalFlow(child) && child.style()->logicalWidth().isAuto()) { + LayoutUnit childWidth = std::max<LayoutUnit>(0, lineCrossAxisExtent - crossAxisMarginExtentForChild(child)); + childWidth = child.constrainLogicalWidthByMinMax(childWidth, childWidth, this); - if (childWidth != child.logicalWidth()) { - child.setOverrideLogicalContentWidth(childWidth - child.borderAndPaddingLogicalWidth()); - child.forceChildLayout(); - } + if (childWidth != child.logicalWidth()) { + child.setOverrideLogicalContentWidth(childWidth - child.borderAndPaddingLogicalWidth()); + child.forceChildLayout(); } } }
diff --git a/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp b/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp index eed2317..4298a5a 100644 --- a/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp
@@ -593,7 +593,7 @@ if (!ancestor->isLayoutBlockFlow()) return false; const LayoutBlockFlow& ancestorBlockFlow = *toLayoutBlockFlow(ancestor); - if (ancestorBlockFlow.createsNewFormattingContext() || ancestorBlockFlow.isUnsplittableForPagination()) + if (ancestorBlockFlow.createsNewFormattingContext() || ancestorBlockFlow.paginationBreakability() == ForbidBreaks) return false; } ASSERT_NOT_REACHED();
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp index 5224caf8..ddb466c5 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -2083,7 +2083,7 @@ void LayoutObject::updateFillImages(const FillLayer* oldLayers, const FillLayer& newLayers) { // Optimize the common case - if (oldLayers && !oldLayers->next() && !newLayers.next() && (oldLayers->image() == newLayers.image())) + if (FillLayer::imagesIdentical(oldLayers, &newLayers)) return; // Go through the new layers and addClients first, to avoid removing all clients of an image.
diff --git a/third_party/WebKit/Source/core/layout/LayoutState.cpp b/third_party/WebKit/Source/core/layout/LayoutState.cpp index 8e9f3cd..bedcbad2 100644 --- a/third_party/WebKit/Source/core/layout/LayoutState.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutState.cpp
@@ -94,7 +94,7 @@ // Disable pagination for objects we don't support. For now this includes overflow:scroll/auto, inline blocks and // writing mode roots. - if (layoutObject.isUnsplittableForPagination()) { + if (layoutObject.paginationBreakability() == LayoutBox::ForbidBreaks) { m_flowThread = nullptr; m_pageLogicalHeight = 0; m_isPaginated = false;
diff --git a/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp b/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp index b814f78..aa46e439 100644 --- a/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp +++ b/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp
@@ -875,10 +875,7 @@ { #if ENABLE(ASSERT) FrameView* view = m_layoutView.frameView(); - if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { - ASSERT(lifecycle().state() == DocumentLifecycle::CompositingForSlimmingPaintV2Clean - || view->shouldThrottleRendering()); - } else if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) { + if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) { ASSERT(lifecycle().state() == DocumentLifecycle::PaintClean || (view && view->shouldThrottleRendering())); } else {
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp index 0f25b1f0..fa81ccee 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp +++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -1366,16 +1366,16 @@ m_frame->document()->cancelParsing(); - // In certain circumstances on pages with multiple frames, stopAllLoaders() or firing readystatechanged - // might detach the current FrameLoader, in which case we should bail on this newly defunct load. - if (!m_frame->host()) - return; - if (m_provisionalDocumentLoader) { m_provisionalDocumentLoader->stopLoading(); detachDocumentLoader(m_provisionalDocumentLoader); } + // beforeunload fired above, and detaching a DocumentLoader can fire + // events, which can detach this frame. + if (!m_frame->host()) + return; + m_provisionalDocumentLoader = client()->createDocumentLoader(m_frame, request, frameLoadRequest.substituteData().isValid() ? frameLoadRequest.substituteData() : defaultSubstituteDataForURL(request.url())); m_provisionalDocumentLoader->setNavigationType(navigationType); m_provisionalDocumentLoader->setReplacesCurrentHistoryItem(type == FrameLoadTypeReplaceCurrentItem);
diff --git a/third_party/WebKit/Source/core/loader/HttpEquiv.cpp b/third_party/WebKit/Source/core/loader/HttpEquiv.cpp index 4891b71d..2b78adb 100644 --- a/third_party/WebKit/Source/core/loader/HttpEquiv.cpp +++ b/third_party/WebKit/Source/core/loader/HttpEquiv.cpp
@@ -103,19 +103,18 @@ if (!frame->loader().shouldInterruptLoadForXFrameOptions(content, document.url(), requestIdentifier)) return; - String message = "Refused to display '" + document.url().elidedString() + "' in a frame because it set 'X-Frame-Options' to '" + content + "'."; - frame->loader().stopAllLoaders(); - // TODO(dglazkov): This should probably check document lifecycle instead. - if (!document.frame()) - return; + RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel, + "Refused to display '" + document.url().elidedString() + "' in a frame because it set 'X-Frame-Options' to '" + content + "'."); + consoleMessage->setRequestIdentifier(requestIdentifier); + document.addConsoleMessage(consoleMessage.release()); + frame->loader().stopAllLoaders(); // Stopping the loader isn't enough, as we're already parsing the document; to honor the header's // intent, we must navigate away from the possibly partially-rendered document to a location that // doesn't inherit the parent's SecurityOrigin. - frame->navigate(document, SecurityOrigin::urlWithUniqueSecurityOrigin(), true, UserGestureStatus::None); - RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel, message); - consoleMessage->setRequestIdentifier(requestIdentifier); - document.addConsoleMessage(consoleMessage.release()); + // TODO(dglazkov): This should probably check document lifecycle instead. + if (document.frame()) + frame->navigate(document, SecurityOrigin::urlWithUniqueSecurityOrigin(), true, UserGestureStatus::None); } }
diff --git a/third_party/WebKit/Source/core/page/Page.cpp b/third_party/WebKit/Source/core/page/Page.cpp index 37b0bdbb..0115e0c 100644 --- a/third_party/WebKit/Source/core/page/Page.cpp +++ b/third_party/WebKit/Source/core/page/Page.cpp
@@ -582,6 +582,12 @@ MemoryPurgeClient::trace(visitor); } +void Page::willCloseLayerTreeView() +{ + if (m_scrollingCoordinator) + m_scrollingCoordinator->willCloseLayerTreeView(); +} + void Page::willBeDestroyed() { RefPtrWillBeRawPtr<Frame> mainFrame = m_mainFrame;
diff --git a/third_party/WebKit/Source/core/page/Page.h b/third_party/WebKit/Source/core/page/Page.h index b33cc42c..0f8a3c4d 100644 --- a/third_party/WebKit/Source/core/page/Page.h +++ b/third_party/WebKit/Source/core/page/Page.h
@@ -206,6 +206,8 @@ void purgeMemory(MemoryPurgeMode, DeviceKind) override; DECLARE_TRACE(); + + void willCloseLayerTreeView(); void willBeDestroyed(); private:
diff --git a/third_party/WebKit/Source/core/page/PageAnimator.cpp b/third_party/WebKit/Source/core/page/PageAnimator.cpp index 03c746d..d0b8591 100644 --- a/third_party/WebKit/Source/core/page/PageAnimator.cpp +++ b/third_party/WebKit/Source/core/page/PageAnimator.cpp
@@ -36,6 +36,7 @@ { RefPtrWillBeRawPtr<PageAnimator> protector(this); TemporaryChange<bool> servicing(m_servicingAnimations, true); + clock().updateTime(monotonicAnimationStartTime); WillBeHeapVector<RefPtrWillBeMember<Document>> documents; for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) { @@ -44,7 +45,7 @@ } for (auto& document : documents) { - DocumentAnimations::updateAnimationTimingForAnimationFrame(*document, monotonicAnimationStartTime); + DocumentAnimations::updateAnimationTimingForAnimationFrame(*document); if (document->view()) { if (document->view()->shouldThrottleRendering()) continue;
diff --git a/third_party/WebKit/Source/core/page/PageAnimator.h b/third_party/WebKit/Source/core/page/PageAnimator.h index d1f547fa4..436f473 100644 --- a/third_party/WebKit/Source/core/page/PageAnimator.h +++ b/third_party/WebKit/Source/core/page/PageAnimator.h
@@ -6,6 +6,7 @@ #define PageAnimator_h #include "core/CoreExport.h" +#include "core/animation/AnimationClock.h" #include "platform/heap/Handle.h" namespace blink { @@ -23,6 +24,7 @@ bool isServicingAnimations() const { return m_servicingAnimations; } void updateLayoutAndStyleForPainting(LocalFrame& rootFrame); void updateAllLifecyclePhases(LocalFrame& rootFrame); + AnimationClock& clock() { return m_animationClock; } private: explicit PageAnimator(Page&); @@ -30,6 +32,7 @@ RawPtrWillBeMember<Page> m_page; bool m_servicingAnimations; bool m_updatingLayoutAndStyleForPainting; + AnimationClock m_animationClock; }; }
diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp index 151fa5c..f3b10cc 100644 --- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp +++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
@@ -94,14 +94,7 @@ , m_wasFrameScrollable(false) , m_lastMainThreadScrollingReasons(0) { - if (RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled() && Platform::current()->isThreadedAnimationEnabled()) { - ASSERT(m_page); - if (m_page->mainFrame()->isLocalFrame()) { - ASSERT(Platform::current()->compositorSupport()); - m_programmaticScrollAnimatorTimeline = adoptPtr(Platform::current()->compositorSupport()->createAnimationTimeline()); - m_page->chromeClient().attachCompositorAnimationTimeline(m_programmaticScrollAnimatorTimeline.get(), toLocalFrame(m_page->mainFrame())); - } - } + createProgrammaticScrollAnimatorTimeline(); } ScrollingCoordinator::~ScrollingCoordinator() @@ -727,15 +720,16 @@ } } +void ScrollingCoordinator::willCloseLayerTreeView() +{ + destroyProgrammaticScrollAnimatorTimeline(); +} + void ScrollingCoordinator::willBeDestroyed() { ASSERT(m_page); - if (m_programmaticScrollAnimatorTimeline) { - ASSERT(m_page->mainFrame()->isLocalFrame()); - m_page->chromeClient().detachCompositorAnimationTimeline(m_programmaticScrollAnimatorTimeline.get(), toLocalFrame(m_page->mainFrame())); - m_programmaticScrollAnimatorTimeline.clear(); - } + destroyProgrammaticScrollAnimatorTimeline(); m_page = nullptr; for (const auto& scrollbar : m_horizontalScrollbars) @@ -1081,4 +1075,26 @@ return false; } +void ScrollingCoordinator::createProgrammaticScrollAnimatorTimeline() +{ + if (RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled() && Platform::current()->isThreadedAnimationEnabled()) { + ASSERT(m_page); + if (m_page->mainFrame()->isLocalFrame()) { + ASSERT(Platform::current()->compositorSupport()); + m_programmaticScrollAnimatorTimeline = adoptPtr(Platform::current()->compositorSupport()->createAnimationTimeline()); + m_page->chromeClient().attachCompositorAnimationTimeline(m_programmaticScrollAnimatorTimeline.get(), toLocalFrame(m_page->mainFrame())); + } + } +} + +void ScrollingCoordinator::destroyProgrammaticScrollAnimatorTimeline() +{ + if (m_programmaticScrollAnimatorTimeline) { + ASSERT(m_page); + ASSERT(m_page->mainFrame()->isLocalFrame()); + m_page->chromeClient().detachCompositorAnimationTimeline(m_programmaticScrollAnimatorTimeline.get(), toLocalFrame(m_page->mainFrame())); + m_programmaticScrollAnimatorTimeline.clear(); + } +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.h b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.h index 4d6b4d0e..6e3921c4 100644 --- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.h +++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.h
@@ -59,6 +59,7 @@ ~ScrollingCoordinator(); DECLARE_TRACE(); + void willCloseLayerTreeView(); void willBeDestroyed(); // Return whether this scrolling coordinator handles scrolling for the given frame view. @@ -155,6 +156,9 @@ bool frameViewIsDirty() const; + void createProgrammaticScrollAnimatorTimeline(); + void destroyProgrammaticScrollAnimatorTimeline(); + OwnPtr<WebCompositorAnimationTimeline> m_programmaticScrollAnimatorTimeline; using ScrollbarMap = WillBeHeapHashMap<RawPtrWillBeMember<ScrollableArea>, OwnPtr<WebScrollbarLayer>>;
diff --git a/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h b/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h index cf8b631..72886970 100644 --- a/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h +++ b/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
@@ -5,6 +5,7 @@ #ifndef ObjectPaintProperties_h #define ObjectPaintProperties_h +#include "platform/graphics/paint/EffectPaintPropertyNode.h" #include "platform/graphics/paint/TransformPaintPropertyNode.h" #include "wtf/PassRefPtr.h" #include "wtf/RefPtr.h" @@ -27,10 +28,11 @@ static PassOwnPtr<ObjectPaintProperties> create( PassRefPtr<TransformPaintPropertyNode> paintOffsetTranslation, PassRefPtr<TransformPaintPropertyNode> transform, + PassRefPtr<EffectPaintPropertyNode> effect, PassRefPtr<TransformPaintPropertyNode> perspective, PassRefPtr<TransformPaintPropertyNode> scrollTranslation) { - return adoptPtr(new ObjectPaintProperties(paintOffsetTranslation, transform, perspective, scrollTranslation)); + return adoptPtr(new ObjectPaintProperties(paintOffsetTranslation, transform, effect, perspective, scrollTranslation)); } // The hierarchy of transform subtree created by a LayoutObject. @@ -44,19 +46,24 @@ const TransformPaintPropertyNode* perspective() const { return m_perspective.get(); } const TransformPaintPropertyNode* scrollTranslation() const { return m_scrollTranslation.get(); } + const EffectPaintPropertyNode* effect() const { return m_effect.get(); } + private: ObjectPaintProperties( PassRefPtr<TransformPaintPropertyNode> paintOffsetTranslation, PassRefPtr<TransformPaintPropertyNode> transform, + PassRefPtr<EffectPaintPropertyNode> effect, PassRefPtr<TransformPaintPropertyNode> perspective, PassRefPtr<TransformPaintPropertyNode> scrollTranslation) : m_paintOffsetTranslation(paintOffsetTranslation) , m_transform(transform) + , m_effect(effect) , m_perspective(perspective) , m_scrollTranslation(scrollTranslation) { } RefPtr<TransformPaintPropertyNode> m_paintOffsetTranslation; RefPtr<TransformPaintPropertyNode> m_transform; + RefPtr<EffectPaintPropertyNode> m_effect; RefPtr<TransformPaintPropertyNode> m_perspective; RefPtr<TransformPaintPropertyNode> m_scrollTranslation; };
diff --git a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h index a5bf45f..6e415581 100644 --- a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h +++ b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h
@@ -76,16 +76,11 @@ } } - // TODO(who removes pre-v2 code): rename to composite(). void commit() { - // For v1, only root graphics layer is supported. - if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { - document().view()->compositeForSlimmingPaintV2(); - } else { - rootPaintController().commitNewDisplayItems(); - document().view()->lifecycle().advanceTo(DocumentLifecycle::PaintClean); - } + // Only root graphics layer is supported. + rootPaintController().commitNewDisplayItems(); + document().view()->lifecycle().advanceTo(DocumentLifecycle::PaintClean); } private:
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.cpp b/third_party/WebKit/Source/core/paint/PaintLayer.cpp index ac1ff2d..ded24777 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayer.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
@@ -2172,7 +2172,10 @@ if (layoutObject()->isLayoutFlowThread()) return LayoutRect(); - LayoutRect result = clipper().localClipRect(); + // If there is a clip applied by an ancestor to this PaintLayer but below or equal to |ancestorLayer|, + // use that clip as the bounds rather than the recursive bounding boxes, since the latter may be larger than the + // actual size. See https://bugs.webkit.org/show_bug.cgi?id=80372 for examples. + LayoutRect result = clipper().localClipRect(ancestorLayer); // TODO(chrishtr): avoid converting to IntRect and back. if (result == LayoutRect(LayoutRect::infiniteIntRect())) { result = physicalBoundingBox(LayoutPoint()); @@ -2675,10 +2678,10 @@ m_needsRepaint = true; // Do this unconditionally to ensure container chain is marked when compositing status of the layer changes. - markAncestorChainForNeedsRepaint(); + markCompositingContainerChainForNeedsRepaint(); } -void PaintLayer::markAncestorChainForNeedsRepaint() +void PaintLayer::markCompositingContainerChainForNeedsRepaint() { // Need to access compositingState(). We've ensured correct flag setting when compositingState() changes. DisableCompositingQueryAsserts disabler; @@ -2692,7 +2695,7 @@ return; } - PaintLayer* container = layer->parent(); + PaintLayer* container = layer->compositingContainer(); if (!container) { LayoutObject* owner = layer->layoutObject()->frame()->ownerLayoutObject(); if (!owner)
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.h b/third_party/WebKit/Source/core/paint/PaintLayer.h index ce09fe0..4b47a60 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayer.h +++ b/third_party/WebKit/Source/core/paint/PaintLayer.h
@@ -691,7 +691,7 @@ void blockSelectionGapsBoundsChanged(); - void markAncestorChainForNeedsRepaint(); + void markCompositingContainerChainForNeedsRepaint(); PaintLayerType m_layerType;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp b/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp index c3eddeee..989dc1c8 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp
@@ -183,10 +183,8 @@ return LayoutRect(clippingRootLayer->layoutObject()->localToAbsoluteQuad(FloatQuad(FloatRect(foregroundRect.rect()))).enclosingBoundingBox()); } -LayoutRect PaintLayerClipper::localClipRect() const +LayoutRect PaintLayerClipper::localClipRect(const PaintLayer* clippingRootLayer) const { - // FIXME: border-radius not accounted for. - PaintLayer* clippingRootLayer = clippingRootForPainting(); LayoutRect layerBounds; ClipRect backgroundRect, foregroundRect; ClipRectsContext context(clippingRootLayer, PaintingClipRects);
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerClipper.h b/third_party/WebKit/Source/core/paint/PaintLayerClipper.h index e8339b2..2092d7f9 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerClipper.h +++ b/third_party/WebKit/Source/core/paint/PaintLayerClipper.h
@@ -157,7 +157,9 @@ void clearClipRectsIncludingDescendants(ClipRectsCacheSlot); LayoutRect childrenClipRect() const; // Returns the foreground clip rect of the layer in the document's coordinate space. - LayoutRect localClipRect() const; // Returns the background clip rect of the layer in the local coordinate space. + + // Returns the background clip rect of the layer in the local coordinate space. Only looks for clips up to the given ancestor. + LayoutRect localClipRect(const PaintLayer* ancestorLayer) const; ClipRect backgroundClipRect(const ClipRectsContext&) const;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp index 0d4fbde..5477d3a8 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
@@ -478,7 +478,7 @@ Optional<SubsequenceRecorder> subsequenceRecorder; if (!paintingInfo.disableSubsequenceCache && !context->printing() - && m_paintLayer.isSelfPaintingLayer() + && m_paintLayer.stackingNode()->isStackingContext() && !(paintingInfo.globalPaintFlags() & GlobalPaintFlattenCompositingLayers) && !(paintFlags & (PaintLayerPaintingReflection | PaintLayerPaintingRootBackgroundOnly | PaintLayerPaintingOverlayScrollbars))) { if (!m_paintLayer.needsRepaint()
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp index 4898686..04079d8 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -19,7 +19,11 @@ // responsible for bookkeeping tree state in other order, for example, the most recent position // container seen. struct PaintPropertyTreeBuilderContext { - PaintPropertyTreeBuilderContext() : currentTransform(nullptr), transformForOutOfFlowPositioned(nullptr), transformForFixedPositioned(nullptr) { } + PaintPropertyTreeBuilderContext() + : currentTransform(nullptr) + , transformForOutOfFlowPositioned(nullptr) + , transformForFixedPositioned(nullptr) + , currentEffect(nullptr) { } // The combination of a transform and paint offset describes a linear space. // When a layout object recur to its children, the main context is expected to refer @@ -38,6 +42,8 @@ TransformPaintPropertyNode* transformForFixedPositioned; LayoutPoint paintOffsetForFixedPositioned; + + EffectPaintPropertyNode* currentEffect; }; void PaintPropertyTreeBuilder::buildPropertyTrees(FrameView& rootFrame) @@ -145,6 +151,16 @@ return newTransformNodeForTransform.release(); } +static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context) +{ + const ComputedStyle& style = object.styleRef(); + if (!object.isBox() || !style.hasOpacity()) + return nullptr; + RefPtr<EffectPaintPropertyNode> newEffectNode = EffectPaintPropertyNode::create(style.opacity(), context.currentEffect); + context.currentEffect = newEffectNode.get(); + return newEffectNode.release(); +} + static FloatPoint perspectiveOrigin(const LayoutBox& box) { const ComputedStyle& style = box.styleRef(); @@ -164,7 +180,6 @@ TransformationMatrix().applyPerspective(style.perspective()), perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.paintOffset), context.currentTransform); context.currentTransform = newTransformNodeForPerspective.get(); - return newTransformNodeForPerspective.release(); } @@ -209,14 +224,16 @@ deriveBorderBoxFromContainerContext(object, localContext); RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = createPaintOffsetTranslationIfNeeded(object, localContext); RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = createTransformIfNeeded(object, localContext); + RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(object, localContext); RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = createPerspectiveIfNeeded(object, localContext); RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = createScrollTranslationIfNeeded(object, localContext); updateOutOfFlowContext(object, localContext); - if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransform || newTransformNodeForPerspective || newTransformNodeForScrollTranslation) { + if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransform || newEffectNode || newTransformNodeForPerspective || newTransformNodeForScrollTranslation) { OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPaintProperties::create( newTransformNodeForPaintOffsetTranslation.release(), newTransformNodeForTransform.release(), + newEffectNode.release(), newTransformNodeForPerspective.release(), newTransformNodeForScrollTranslation.release()); object.setObjectPaintProperties(updatedPaintProperties.release());
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp index d59ffd3..6ad7cf19 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -184,4 +184,86 @@ EXPECT_EQ(document().view()->scrollTranslation(), inlineBlockProperties->paintOffsetTranslation()->parent()); } +TEST_F(PaintPropertyTreeBuilderTest, NestedOpacityEffect) +{ + setBodyInnerHTML( + "<div id='nodeWithoutOpacity'>" + " <div id='childWithOpacity' style='opacity: 0.5'>" + " <div id='grandChildWithoutOpacity'>" + " <div id='greatGrandChildWithOpacity' style='opacity: 0.2'/>" + " </div>" + " </div" + "</div>"); + + LayoutObject& nodeWithoutOpacity = *document().getElementById("nodeWithoutOpacity")->layoutObject(); + ObjectPaintProperties* nodeWithoutOpacityProperties = nodeWithoutOpacity.objectPaintProperties(); + EXPECT_EQ(nullptr, nodeWithoutOpacityProperties); + + LayoutObject& childWithOpacity = *document().getElementById("childWithOpacity")->layoutObject(); + ObjectPaintProperties* childWithOpacityProperties = childWithOpacity.objectPaintProperties(); + EXPECT_EQ(0.5f, childWithOpacityProperties->effect()->opacity()); + // childWithOpacity is the root effect node. + EXPECT_EQ(nullptr, childWithOpacityProperties->effect()->parent()); + + LayoutObject& grandChildWithoutOpacity = *document().getElementById("grandChildWithoutOpacity")->layoutObject(); + EXPECT_EQ(nullptr, grandChildWithoutOpacity.objectPaintProperties()); + + LayoutObject& greatGrandChildWithOpacity = *document().getElementById("greatGrandChildWithOpacity")->layoutObject(); + ObjectPaintProperties* greatGrandChildWithOpacityProperties = greatGrandChildWithOpacity.objectPaintProperties(); + EXPECT_EQ(0.2f, greatGrandChildWithOpacityProperties->effect()->opacity()); + EXPECT_EQ(childWithOpacityProperties->effect(), greatGrandChildWithOpacityProperties->effect()->parent()); +} + +TEST_F(PaintPropertyTreeBuilderTest, TransformNodeDoesNotAffectEffectNodes) +{ + setBodyInnerHTML( + "<div id='nodeWithOpacity' style='opacity: 0.6'>" + " <div id='childWithTransform' style='transform: translate3d(10px, 10px, 0px);'>" + " <div id='grandChildWithOpacity' style='opacity: 0.4'/>" + " </div" + "</div>"); + + LayoutObject& nodeWithOpacity = *document().getElementById("nodeWithOpacity")->layoutObject(); + ObjectPaintProperties* nodeWithOpacityProperties = nodeWithOpacity.objectPaintProperties(); + EXPECT_EQ(0.6f, nodeWithOpacityProperties->effect()->opacity()); + EXPECT_EQ(nullptr, nodeWithOpacityProperties->effect()->parent()); + EXPECT_EQ(nullptr, nodeWithOpacityProperties->transform()); + + LayoutObject& childWithTransform = *document().getElementById("childWithTransform")->layoutObject(); + ObjectPaintProperties* childWithTransformProperties = childWithTransform.objectPaintProperties(); + EXPECT_EQ(nullptr, childWithTransformProperties->effect()); + EXPECT_EQ(TransformationMatrix().translate(10, 10), childWithTransformProperties->transform()->matrix()); + + LayoutObject& grandChildWithOpacity = *document().getElementById("grandChildWithOpacity")->layoutObject(); + ObjectPaintProperties* grandChildWithOpacityProperties = grandChildWithOpacity.objectPaintProperties(); + EXPECT_EQ(0.4f, grandChildWithOpacityProperties->effect()->opacity()); + EXPECT_EQ(nodeWithOpacityProperties->effect(), grandChildWithOpacityProperties->effect()->parent()); + EXPECT_EQ(nullptr, grandChildWithOpacityProperties->transform()); +} + +TEST_F(PaintPropertyTreeBuilderTest, EffectNodesAcrossStackingContext) +{ + setBodyInnerHTML( + "<div id='nodeWithOpacity' style='opacity: 0.6'>" + " <div id='childWithStackingContext' style='position:absolute;'>" + " <div id='grandChildWithOpacity' style='opacity: 0.4'/>" + " </div" + "</div>"); + + LayoutObject& nodeWithOpacity = *document().getElementById("nodeWithOpacity")->layoutObject(); + ObjectPaintProperties* nodeWithOpacityProperties = nodeWithOpacity.objectPaintProperties(); + EXPECT_EQ(0.6f, nodeWithOpacityProperties->effect()->opacity()); + EXPECT_EQ(nullptr, nodeWithOpacityProperties->effect()->parent()); + EXPECT_EQ(nullptr, nodeWithOpacityProperties->transform()); + + LayoutObject& childWithStackingContext = *document().getElementById("childWithStackingContext")->layoutObject(); + EXPECT_EQ(nullptr, childWithStackingContext.objectPaintProperties()); + + LayoutObject& grandChildWithOpacity = *document().getElementById("grandChildWithOpacity")->layoutObject(); + ObjectPaintProperties* grandChildWithOpacityProperties = grandChildWithOpacity.objectPaintProperties(); + EXPECT_EQ(0.4f, grandChildWithOpacityProperties->effect()->opacity()); + EXPECT_EQ(nodeWithOpacityProperties->effect(), grandChildWithOpacityProperties->effect()->parent()); + EXPECT_EQ(nullptr, grandChildWithOpacityProperties->transform()); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp index 222c332..2cfe368 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp +++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -1269,6 +1269,32 @@ return rareInheritedData->appliedTextDecorations->vector(); } +StyleVariableData* ComputedStyle::variables() const +{ + ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); + return rareInheritedData->variables.get(); +} + +void ComputedStyle::setVariable(const AtomicString& name, PassRefPtr<CSSVariableData> value) +{ + RefPtr<StyleVariableData>& variables = rareInheritedData.access()->variables; + if (!variables) + variables = StyleVariableData::create(); + else if (!variables->hasOneRef()) + variables = variables->copy(); + variables->setVariable(name, value); +} + +void ComputedStyle::removeVariable(const AtomicString& name) +{ + RefPtr<StyleVariableData>& variables = rareInheritedData.access()->variables; + if (!variables) + return; + if (!variables->hasOneRef()) + variables = variables->copy(); + variables->removeVariable(name); +} + float ComputedStyle::wordSpacing() const { return fontDescription().wordSpacing(); } float ComputedStyle::letterSpacing() const { return fontDescription().letterSpacing(); }
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h index c4f0ede..d8eff8e2 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyle.h +++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -593,6 +593,10 @@ TextDecorationStyle textDecorationStyle() const { return static_cast<TextDecorationStyle>(rareNonInheritedData->m_textDecorationStyle); } float wordSpacing() const; float letterSpacing() const; + StyleVariableData* variables() const; + + void setVariable(const AtomicString&, PassRefPtr<CSSVariableData>); + void removeVariable(const AtomicString&); float zoom() const { return visual->m_zoom; } float effectiveZoom() const { return rareInheritedData->m_effectiveZoom; } @@ -1742,6 +1746,7 @@ static TouchAction initialTouchAction() { return TouchActionAuto; } static ShadowList* initialBoxShadow() { return 0; } static ShadowList* initialTextShadow() { return 0; } + static StyleVariableData* initialVariables() { return nullptr; } static ScrollBehavior initialScrollBehavior() { return ScrollBehaviorAuto; } static ScrollSnapType initialScrollSnapType() { return ScrollSnapTypeNone; } static ScrollSnapPoints initialScrollSnapPointsX() { return ScrollSnapPoints(); }
diff --git a/third_party/WebKit/Source/core/style/FillLayer.cpp b/third_party/WebKit/Source/core/style/FillLayer.cpp index 693e869a..efbab33 100644 --- a/third_party/WebKit/Source/core/style/FillLayer.cpp +++ b/third_party/WebKit/Source/core/style/FillLayer.cpp
@@ -394,4 +394,20 @@ return m_repeatX == RepeatFill && m_repeatY == RepeatFill; } +static inline bool layerImagesIdentical(const FillLayer& layer1, const FillLayer& layer2) +{ + // We just care about pointer equivalency. + return layer1.image() == layer2.image(); +} + +bool FillLayer::imagesIdentical(const FillLayer* layer1, const FillLayer* layer2) +{ + for (; layer1 && layer2; layer1 = layer1->next(), layer2 = layer2->next()) { + if (!layerImagesIdentical(*layer1, *layer2)) + return false; + } + + return !layer1 && !layer2; +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/style/FillLayer.h b/third_party/WebKit/Source/core/style/FillLayer.h index 473fbd0..fd86d5dc9 100644 --- a/third_party/WebKit/Source/core/style/FillLayer.h +++ b/third_party/WebKit/Source/core/style/FillLayer.h
@@ -184,6 +184,8 @@ void fillUnsetProperties(); void cullEmptyLayers(); + static bool imagesIdentical(const FillLayer*, const FillLayer*); + EFillBox thisOrNextLayersClipMax() const { computeCachedPropertiesIfNeeded(); return static_cast<EFillBox>(m_thisOrNextLayersClipMax); } bool thisOrNextLayersUseContentBox() const { computeCachedPropertiesIfNeeded(); return m_thisOrNextLayersUseContentBox; } bool thisOrNextLayersHaveLocalAttachment() const { computeCachedPropertiesIfNeeded(); return m_thisOrNextLayersHaveLocalAttachment; }
diff --git a/third_party/WebKit/Source/core/style/StyleRareInheritedData.cpp b/third_party/WebKit/Source/core/style/StyleRareInheritedData.cpp index 612e93a..1c1622c 100644 --- a/third_party/WebKit/Source/core/style/StyleRareInheritedData.cpp +++ b/third_party/WebKit/Source/core/style/StyleRareInheritedData.cpp
@@ -54,6 +54,7 @@ Color touchColors; TabSize tabSize; + void* variables[1]; }; static_assert(sizeof(StyleRareInheritedData) <= sizeof(SameSizeAsStyleRareInheritedData), "StyleRareInheritedData should stay small"); @@ -159,6 +160,7 @@ , tapHighlightColor(o.tapHighlightColor) , appliedTextDecorations(o.appliedTextDecorations) , m_tabSize(o.m_tabSize) + , variables(o.variables) { } @@ -222,7 +224,8 @@ && m_textUnderlinePosition == o.m_textUnderlinePosition && m_rubyPosition == o.m_rubyPosition && dataEquivalent(listStyleImage.get(), o.listStyleImage.get()) - && dataEquivalent(appliedTextDecorations, o.appliedTextDecorations); + && dataEquivalent(appliedTextDecorations, o.appliedTextDecorations) + && variables == o.variables; } bool StyleRareInheritedData::shadowDataEquivalent(const StyleRareInheritedData& o) const
diff --git a/third_party/WebKit/Source/core/style/StyleRareInheritedData.h b/third_party/WebKit/Source/core/style/StyleRareInheritedData.h index f26650c..260cd1cb 100644 --- a/third_party/WebKit/Source/core/style/StyleRareInheritedData.h +++ b/third_party/WebKit/Source/core/style/StyleRareInheritedData.h
@@ -28,6 +28,7 @@ #include "core/CoreExport.h" #include "core/css/StyleColor.h" #include "core/style/DataRef.h" +#include "core/style/StyleVariableData.h" #include "platform/Length.h" #include "platform/graphics/Color.h" #include "platform/heap/Handle.h" @@ -159,6 +160,8 @@ RefPtr<AppliedTextDecorationList> appliedTextDecorations; TabSize m_tabSize; + RefPtr<StyleVariableData> variables; + private: StyleRareInheritedData(); StyleRareInheritedData(const StyleRareInheritedData&);
diff --git a/third_party/WebKit/Source/core/style/StyleVariableData.h b/third_party/WebKit/Source/core/style/StyleVariableData.h new file mode 100644 index 0000000..1c7d941 --- /dev/null +++ b/third_party/WebKit/Source/core/style/StyleVariableData.h
@@ -0,0 +1,34 @@ +#ifndef StyleVariableData_h +#define StyleVariableData_h + +#include "core/css/CSSVariableData.h" +#include "wtf/Forward.h" +#include "wtf/HashMap.h" +#include "wtf/RefCounted.h" +#include "wtf/text/AtomicStringHash.h" + +namespace blink { + +class StyleVariableData : public RefCounted<StyleVariableData> { +public: + static PassRefPtr<StyleVariableData> create() { return adoptRef(new StyleVariableData()); } + PassRefPtr<StyleVariableData> copy() const { return adoptRef(new StyleVariableData(*this)); } + + bool operator==(const StyleVariableData& other) const { return other.m_data == m_data; } + bool operator!=(const StyleVariableData& other) const { return !(*this == other); } + + void setVariable(const AtomicString& name, PassRefPtr<CSSVariableData> value) { m_data.set(name, value); } + CSSVariableData* getVariable(const AtomicString& name) const { return m_data.get(name); } + void removeVariable(const AtomicString& name) { return m_data.remove(name); } +private: + StyleVariableData() = default; + StyleVariableData(const StyleVariableData& other) : RefCounted<StyleVariableData>(), m_data(other.m_data) { } + + friend class CSSVariableResolver; + + HashMap<AtomicString, RefPtr<CSSVariableData>> m_data; +}; + +} // namespace blink + +#endif // StyleVariableData_h
diff --git a/third_party/WebKit/Source/core/svg/SVGAnimatedColor.cpp b/third_party/WebKit/Source/core/svg/SVGAnimatedColor.cpp index 68e547a5..b05eebe 100644 --- a/third_party/WebKit/Source/core/svg/SVGAnimatedColor.cpp +++ b/third_party/WebKit/Source/core/svg/SVGAnimatedColor.cpp
@@ -31,9 +31,9 @@ : SVGPropertyBase(classType()) , m_styleColor(StyleColor::currentColor()) { - RGBA32 color; + Color color; if (CSSParser::parseColor(color, colorString.stripWhiteSpace())) - m_styleColor = StyleColor(color); + m_styleColor = color; } String SVGColorProperty::valueAsString() const
diff --git a/third_party/WebKit/Source/core/svg/SVGAnimatedColor.h b/third_party/WebKit/Source/core/svg/SVGAnimatedColor.h index 212ba5c8..a3299ff 100644 --- a/third_party/WebKit/Source/core/svg/SVGAnimatedColor.h +++ b/third_party/WebKit/Source/core/svg/SVGAnimatedColor.h
@@ -32,7 +32,7 @@ #define SVGAnimatedColor_h #include "core/css/StyleColor.h" -#include "core/svg/properties/SVGAnimatedProperty.h" +#include "core/svg/properties/SVGProperty.h" namespace blink { @@ -62,12 +62,7 @@ StyleColor m_styleColor; }; -inline PassRefPtrWillBeRawPtr<SVGColorProperty> toSVGColorProperty(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase) -{ - RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase; - ASSERT(base->type() == SVGColorProperty::classType()); - return static_pointer_cast<SVGColorProperty>(base.release()); -} +DEFINE_SVG_PROPERTY_TYPE_CASTS(SVGColorProperty); } // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGBoolean.h b/third_party/WebKit/Source/core/svg/SVGBoolean.h index 7d2592e..c5aef85 100644 --- a/third_party/WebKit/Source/core/svg/SVGBoolean.h +++ b/third_party/WebKit/Source/core/svg/SVGBoolean.h
@@ -69,12 +69,7 @@ bool m_value; }; -inline PassRefPtrWillBeRawPtr<SVGBoolean> toSVGBoolean(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase) -{ - RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase; - ASSERT(base->type() == SVGBoolean::classType()); - return static_pointer_cast<SVGBoolean>(base.release()); -} +DEFINE_SVG_PROPERTY_TYPE_CASTS(SVGBoolean); } // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGEnumeration.cpp b/third_party/WebKit/Source/core/svg/SVGEnumeration.cpp index 32b3e4f..c4c4a85 100644 --- a/third_party/WebKit/Source/core/svg/SVGEnumeration.cpp +++ b/third_party/WebKit/Source/core/svg/SVGEnumeration.cpp
@@ -29,7 +29,6 @@ */ #include "config.h" - #include "core/svg/SVGEnumeration.h" #include "bindings/core/v8/ExceptionState.h" @@ -39,12 +38,7 @@ namespace blink { -inline PassRefPtrWillBeRawPtr<SVGEnumerationBase> toSVGEnumerationBase(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase) -{ - RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase; - ASSERT(base->type() == SVGEnumerationBase::classType()); - return static_pointer_cast<SVGEnumerationBase>(base.release()); -} +DEFINE_SVG_PROPERTY_TYPE_CASTS(SVGEnumerationBase); SVGEnumerationBase::~SVGEnumerationBase() {
diff --git a/third_party/WebKit/Source/core/svg/SVGInteger.h b/third_party/WebKit/Source/core/svg/SVGInteger.h index cc0141b..ae20a3d4 100644 --- a/third_party/WebKit/Source/core/svg/SVGInteger.h +++ b/third_party/WebKit/Source/core/svg/SVGInteger.h
@@ -67,12 +67,7 @@ int m_value; }; -inline PassRefPtrWillBeRawPtr<SVGInteger> toSVGInteger(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase) -{ - RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase; - ASSERT(base->type() == SVGInteger::classType()); - return static_pointer_cast<SVGInteger>(base.release()); -} +DEFINE_SVG_PROPERTY_TYPE_CASTS(SVGInteger); } // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGIntegerOptionalInteger.h b/third_party/WebKit/Source/core/svg/SVGIntegerOptionalInteger.h index b62fb1f8..51979d8 100644 --- a/third_party/WebKit/Source/core/svg/SVGIntegerOptionalInteger.h +++ b/third_party/WebKit/Source/core/svg/SVGIntegerOptionalInteger.h
@@ -31,7 +31,7 @@ #ifndef SVGIntegerOptionalInteger_h #define SVGIntegerOptionalInteger_h -#include "core/svg/SVGAnimatedInteger.h" +#include "core/svg/SVGInteger.h" #include "platform/heap/Handle.h" namespace blink { @@ -71,12 +71,7 @@ RefPtrWillBeMember<SVGInteger> m_secondInteger; }; -inline PassRefPtrWillBeRawPtr<SVGIntegerOptionalInteger> toSVGIntegerOptionalInteger(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase) -{ - RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase; - ASSERT(base->type() == SVGIntegerOptionalInteger::classType()); - return static_pointer_cast<SVGIntegerOptionalInteger>(base.release()); -} +DEFINE_SVG_PROPERTY_TYPE_CASTS(SVGIntegerOptionalInteger); } // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGLength.h b/third_party/WebKit/Source/core/svg/SVGLength.h index 088acd0..4662cbb5 100644 --- a/third_party/WebKit/Source/core/svg/SVGLength.h +++ b/third_party/WebKit/Source/core/svg/SVGLength.h
@@ -123,12 +123,7 @@ unsigned m_unitType : 4; }; -inline PassRefPtrWillBeRawPtr<SVGLength> toSVGLength(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase) -{ - RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase; - ASSERT(base->type() == SVGLength::classType()); - return static_pointer_cast<SVGLength>(base.release()); -} +DEFINE_SVG_PROPERTY_TYPE_CASTS(SVGLength); } // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGLengthList.cpp b/third_party/WebKit/Source/core/svg/SVGLengthList.cpp index 1fadc5e..46c57c91 100644 --- a/third_party/WebKit/Source/core/svg/SVGLengthList.cpp +++ b/third_party/WebKit/Source/core/svg/SVGLengthList.cpp
@@ -28,12 +28,7 @@ namespace blink { -inline PassRefPtrWillBeRawPtr<SVGLengthList> toSVGLengthList(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase) -{ - RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase; - ASSERT(base->type() == SVGLengthList::classType()); - return static_pointer_cast<SVGLengthList>(base.release()); -} +DEFINE_SVG_PROPERTY_TYPE_CASTS(SVGLengthList); SVGLengthList::SVGLengthList(SVGLengthMode mode) : m_mode(mode)
diff --git a/third_party/WebKit/Source/core/svg/SVGNumberList.cpp b/third_party/WebKit/Source/core/svg/SVGNumberList.cpp index 061251c..feb3c60 100644 --- a/third_party/WebKit/Source/core/svg/SVGNumberList.cpp +++ b/third_party/WebKit/Source/core/svg/SVGNumberList.cpp
@@ -28,12 +28,7 @@ namespace blink { -inline PassRefPtrWillBeRawPtr<SVGNumberList> toSVGNumberList(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase) -{ - RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase; - ASSERT(base->type() == SVGNumberList::classType()); - return static_pointer_cast<SVGNumberList>(base.release()); -} +DEFINE_SVG_PROPERTY_TYPE_CASTS(SVGNumberList); SVGNumberList::SVGNumberList() {
diff --git a/third_party/WebKit/Source/core/svg/SVGNumberOptionalNumber.h b/third_party/WebKit/Source/core/svg/SVGNumberOptionalNumber.h index ae3c398c..0be4092b 100644 --- a/third_party/WebKit/Source/core/svg/SVGNumberOptionalNumber.h +++ b/third_party/WebKit/Source/core/svg/SVGNumberOptionalNumber.h
@@ -31,7 +31,7 @@ #ifndef SVGNumberOptionalNumber_h #define SVGNumberOptionalNumber_h -#include "core/svg/SVGAnimatedNumber.h" +#include "core/svg/SVGNumber.h" #include "platform/heap/Handle.h" namespace blink { @@ -71,12 +71,7 @@ RefPtrWillBeMember<SVGNumber> m_secondNumber; }; -inline PassRefPtrWillBeRawPtr<SVGNumberOptionalNumber> toSVGNumberOptionalNumber(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase) -{ - RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase; - ASSERT(base->type() == SVGNumberOptionalNumber::classType()); - return static_pointer_cast<SVGNumberOptionalNumber>(base.release()); -} +DEFINE_SVG_PROPERTY_TYPE_CASTS(SVGNumberOptionalNumber); } // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGPath.h b/third_party/WebKit/Source/core/svg/SVGPath.h index 0f9ac5b..781f6d5 100644 --- a/third_party/WebKit/Source/core/svg/SVGPath.h +++ b/third_party/WebKit/Source/core/svg/SVGPath.h
@@ -78,12 +78,7 @@ mutable OwnPtr<Path> m_cachedPath; }; -inline PassRefPtrWillBeRawPtr<SVGPath> toSVGPath(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase) -{ - RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase; - ASSERT(base->type() == SVGPath::classType()); - return static_pointer_cast<SVGPath>(base.release()); -} +DEFINE_SVG_PROPERTY_TYPE_CASTS(SVGPath); } // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGPoint.h b/third_party/WebKit/Source/core/svg/SVGPoint.h index 58030a5..5393a909 100644 --- a/third_party/WebKit/Source/core/svg/SVGPoint.h +++ b/third_party/WebKit/Source/core/svg/SVGPoint.h
@@ -84,12 +84,7 @@ FloatPoint m_value; }; -inline PassRefPtrWillBeRawPtr<SVGPoint> toSVGPoint(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase) -{ - RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase; - ASSERT(base->type() == SVGPoint::classType()); - return static_pointer_cast<SVGPoint>(base.release()); -} +DEFINE_SVG_PROPERTY_TYPE_CASTS(SVGPoint); } // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGPointList.cpp b/third_party/WebKit/Source/core/svg/SVGPointList.cpp index 41059ff..bc11d6b 100644 --- a/third_party/WebKit/Source/core/svg/SVGPointList.cpp +++ b/third_party/WebKit/Source/core/svg/SVGPointList.cpp
@@ -29,12 +29,7 @@ namespace blink { -inline PassRefPtrWillBeRawPtr<SVGPointList> toSVGPointList(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase) -{ - RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase; - ASSERT(base->type() == SVGPointList::classType()); - return static_pointer_cast<SVGPointList>(base.release()); -} +DEFINE_SVG_PROPERTY_TYPE_CASTS(SVGPointList); SVGPointList::SVGPointList() {
diff --git a/third_party/WebKit/Source/core/svg/SVGPreserveAspectRatio.h b/third_party/WebKit/Source/core/svg/SVGPreserveAspectRatio.h index 9b31149..7474aca4 100644 --- a/third_party/WebKit/Source/core/svg/SVGPreserveAspectRatio.h +++ b/third_party/WebKit/Source/core/svg/SVGPreserveAspectRatio.h
@@ -97,12 +97,7 @@ SVGMeetOrSliceType m_meetOrSlice; }; -inline PassRefPtrWillBeRawPtr<SVGPreserveAspectRatio> toSVGPreserveAspectRatio(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase) -{ - RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase; - ASSERT(base->type() == SVGPreserveAspectRatio::classType()); - return static_pointer_cast<SVGPreserveAspectRatio>(base.release()); -} +DEFINE_SVG_PROPERTY_TYPE_CASTS(SVGPreserveAspectRatio); } // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGRect.h b/third_party/WebKit/Source/core/svg/SVGRect.h index d2cf1f7d4..88d9c77 100644 --- a/third_party/WebKit/Source/core/svg/SVGRect.h +++ b/third_party/WebKit/Source/core/svg/SVGRect.h
@@ -86,12 +86,7 @@ FloatRect m_value; }; -inline PassRefPtrWillBeRawPtr<SVGRect> toSVGRect(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase) -{ - RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase; - ASSERT(base->type() == SVGRect::classType()); - return static_pointer_cast<SVGRect>(base.release()); -} +DEFINE_SVG_PROPERTY_TYPE_CASTS(SVGRect); } // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGString.h b/third_party/WebKit/Source/core/svg/SVGString.h index f17b0175..d7472ff1 100644 --- a/third_party/WebKit/Source/core/svg/SVGString.h +++ b/third_party/WebKit/Source/core/svg/SVGString.h
@@ -86,12 +86,7 @@ String m_value; }; -inline PassRefPtrWillBeRawPtr<SVGString> toSVGString(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase) -{ - RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase; - ASSERT(base->type() == SVGString::classType()); - return static_pointer_cast<SVGString>(base.release()); -} +DEFINE_SVG_PROPERTY_TYPE_CASTS(SVGString); } // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGTransformList.cpp b/third_party/WebKit/Source/core/svg/SVGTransformList.cpp index 652fa55f..c8c96aef 100644 --- a/third_party/WebKit/Source/core/svg/SVGTransformList.cpp +++ b/third_party/WebKit/Source/core/svg/SVGTransformList.cpp
@@ -35,12 +35,7 @@ namespace blink { -inline PassRefPtrWillBeRawPtr<SVGTransformList> toSVGTransformList(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase) -{ - RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase; - ASSERT(base->type() == SVGTransformList::classType()); - return static_pointer_cast<SVGTransformList>(base.release()); -} +DEFINE_SVG_PROPERTY_TYPE_CASTS(SVGTransformList); SVGTransformList::SVGTransformList() {
diff --git a/third_party/WebKit/Source/core/svg/animation/SMILTimeContainer.cpp b/third_party/WebKit/Source/core/svg/animation/SMILTimeContainer.cpp index 34072b0..af2bcfa 100644 --- a/third_party/WebKit/Source/core/svg/animation/SMILTimeContainer.cpp +++ b/third_party/WebKit/Source/core/svg/animation/SMILTimeContainer.cpp
@@ -413,7 +413,7 @@ double SMILTimeContainer::currentTime() const { - return document().animationClock().currentTime(); + return document().timeline().currentTimeInternal(); } void SMILTimeContainer::serviceOnNextFrame()
diff --git a/third_party/WebKit/Source/core/svg/properties/SVGProperty.h b/third_party/WebKit/Source/core/svg/properties/SVGProperty.h index 27d06f0..210bb70f 100644 --- a/third_party/WebKit/Source/core/svg/properties/SVGProperty.h +++ b/third_party/WebKit/Source/core/svg/properties/SVGProperty.h
@@ -107,6 +107,15 @@ SVGPropertyBase* m_ownerList; }; +#define DEFINE_SVG_PROPERTY_TYPE_CASTS(thisType)\ + DEFINE_TYPE_CASTS(thisType, SVGPropertyBase, value, value->type() == thisType::classType(), value.type() == thisType::classType());\ + inline PassRefPtrWillBeRawPtr<thisType> to##thisType(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase)\ + {\ + RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase;\ + ASSERT(base->type() == thisType::classType());\ + return static_pointer_cast<thisType>(base.release());\ + } + } #endif // SVGProperty_h
diff --git a/third_party/WebKit/Source/core/svg/properties/SVGPropertyHelper.h b/third_party/WebKit/Source/core/svg/properties/SVGPropertyHelper.h index fdfae73..aa1b1e5f 100644 --- a/third_party/WebKit/Source/core/svg/properties/SVGPropertyHelper.h +++ b/third_party/WebKit/Source/core/svg/properties/SVGPropertyHelper.h
@@ -26,16 +26,6 @@ } }; -#define DEFINE_SVG_PROPERTY_TYPE_CASTS(thisType)\ - DEFINE_TYPE_CASTS(thisType, SVGPropertyBase, value, value->type() == thisType::classType(), value.type() == thisType::classType());\ - inline PassRefPtrWillBeRawPtr<thisType> to##thisType(PassRefPtrWillBeRawPtr<SVGPropertyBase> passBase)\ - {\ - RefPtrWillBeRawPtr<SVGPropertyBase> base = passBase;\ - ASSERT(base->type() == thisType::classType());\ - return static_pointer_cast<thisType>(base.release());\ - } - - } // namespace blink #endif // SVGPropertyHelper_h
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp index 3677823..a7c18c2 100644 --- a/third_party/WebKit/Source/core/testing/Internals.cpp +++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -2561,7 +2561,7 @@ return document->loader()->timing().monotonicTimeToZeroBasedDocumentTime(platformTime); } -void Internals::setMediaElementNetworkState(HTMLMediaElement* mediaElement, int32_t state) +void Internals::setMediaElementNetworkState(HTMLMediaElement* mediaElement, int state) { ASSERT(mediaElement); ASSERT(state >= HTMLMediaElement::NetworkState::NETWORK_EMPTY);
diff --git a/third_party/WebKit/Source/core/testing/Internals.h b/third_party/WebKit/Source/core/testing/Internals.h index f65d7dab..c763e26 100644 --- a/third_party/WebKit/Source/core/testing/Internals.h +++ b/third_party/WebKit/Source/core/testing/Internals.h
@@ -396,7 +396,7 @@ // document time in seconds double monotonicTimeToZeroBasedDocumentTime(double, ExceptionState&); - void setMediaElementNetworkState(HTMLMediaElement*, int32_t state); + void setMediaElementNetworkState(HTMLMediaElement*, int state); private: explicit Internals(ScriptState*);
diff --git a/third_party/WebKit/Source/devtools/front_end/components/NetworkConditionsSelector.js b/third_party/WebKit/Source/devtools/front_end/components/NetworkConditionsSelector.js index 983c947..b43471e 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/NetworkConditionsSelector.js +++ b/third_party/WebKit/Source/devtools/front_end/components/NetworkConditionsSelector.js
@@ -156,9 +156,6 @@ _conditionsUpdated: function() { - if (this._muteUpdate) - return; - this._list.clear(); var conditions = this._customSetting.get(); @@ -207,10 +204,7 @@ { var list = this._customSetting.get(); list.splice(index, 1); - this._muteUpdate = true; this._customSetting.set(list); - this._muteUpdate = false; - this._list.removeItem(index); }, /** @@ -284,30 +278,36 @@ return editor; /** + * @param {*} item + * @param {number} index * @param {!HTMLInputElement|!HTMLSelectElement} input * @return {boolean} */ - function titleValidator(input) + function titleValidator(item, index, input) { var value = input.value.trim(); return value.length > 0 && value.length < 50; } /** + * @param {*} item + * @param {number} index * @param {!HTMLInputElement|!HTMLSelectElement} input * @return {boolean} */ - function throughputValidator(input) + function throughputValidator(item, index, input) { var value = input.value.trim(); return !value || (/^[\d]+(\.\d+)?|\.\d+$/.test(value) && value >= 0 && value <= 10000000); } /** + * @param {*} item + * @param {number} index * @param {!HTMLInputElement|!HTMLSelectElement} input * @return {boolean} */ - function latencyValidator(input) + function latencyValidator(item, index, input) { var value = input.value.trim(); return !value || (/^[\d]+$/.test(value) && value >= 0 && value <= 1000000);
diff --git a/third_party/WebKit/Source/devtools/front_end/devices/DevicesView.js b/third_party/WebKit/Source/devtools/front_end/devices/DevicesView.js index 4e91b620..cf223e4 100644 --- a/third_party/WebKit/Source/devtools/front_end/devices/DevicesView.js +++ b/third_party/WebKit/Source/devtools/front_end/devices/DevicesView.js
@@ -42,6 +42,9 @@ InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.DevicesUpdated, this._devicesUpdated, this); InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, this._devicesDiscoveryConfigChanged, this); + + this.contentElement.tabIndex = 0; + this.setDefaultFocusedElement(this.contentElement); } WebInspector.DevicesView.prototype = { @@ -324,29 +327,41 @@ this._editor = editor; var content = editor.contentElement(); var fields = content.createChild("div", "port-forwarding-edit-row"); - fields.createChild("div", "port-forwarding-value port-forwarding-port").appendChild(editor.createInput("port", "text", "Device port (3333)", portValidator)); + fields.createChild("div", "port-forwarding-value port-forwarding-port").appendChild(editor.createInput("port", "text", "Device port (3333)", portValidator.bind(this))); fields.createChild("div", "port-forwarding-separator port-forwarding-separator-invisible"); fields.createChild("div", "port-forwarding-value").appendChild(editor.createInput("address", "text", "Local address (dev.example.corp:3333)", addressValidator)); return editor; /** + * @param {*} item + * @param {number} index * @param {!HTMLInputElement|!HTMLSelectElement} input + * @this {WebInspector.DevicesView.DiscoveryView} * @return {boolean} */ - function portValidator(input) + function portValidator(item, index, input) { - var match = input.value.trim().match(/^(\d+)$/); + var value = input.value.trim(); + var match = value.match(/^(\d+)$/); if (!match) return false; var port = parseInt(match[1], 10); - return port >= 1024 && port <= 65535; + if (port < 1024 || port > 65535) + return false; + for (var i = 0; i < this._portForwardingConfig.length; ++i) { + if (i !== index && this._portForwardingConfig[i].port === value) + return false; + } + return true; } /** + * @param {*} item + * @param {number} index * @param {!HTMLInputElement|!HTMLSelectElement} input * @return {boolean} */ - function addressValidator(input) + function addressValidator(item, index, input) { var match = input.value.trim().match(/^([a-zA-Z0-9\.\-_]+):(\d+)$/); if (!match)
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/DevicesSettingsTab.js b/third_party/WebKit/Source/devtools/front_end/emulation/DevicesSettingsTab.js index a9b5ba0..26ba0e8 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/DevicesSettingsTab.js +++ b/third_party/WebKit/Source/devtools/front_end/emulation/DevicesSettingsTab.js
@@ -19,8 +19,8 @@ this.containerElement = this.element.createChild("div", "help-container-wrapper").createChild("div", "settings-tab help-content help-container"); var buttonsRow = this.containerElement.createChild("div", "devices-button-row"); - var addCustomButton = createTextButton(WebInspector.UIString("Add custom device..."), this._addCustomDevice.bind(this)); - buttonsRow.appendChild(addCustomButton); + this._addCustomButton = createTextButton(WebInspector.UIString("Add custom device..."), this._addCustomDevice.bind(this)); + buttonsRow.appendChild(this._addCustomButton); this._list = new WebInspector.ListWidget(this); this._list.registerRequiredCSS("emulation/devicesSettingsTab.css"); @@ -31,7 +31,7 @@ WebInspector.emulatedDevicesList.addEventListener(WebInspector.EmulatedDevicesList.Events.CustomDevicesUpdated, this._devicesUpdated, this); WebInspector.emulatedDevicesList.addEventListener(WebInspector.EmulatedDevicesList.Events.StandardDevicesUpdated, this._devicesUpdated, this); - this.setDefaultFocusedElement(addCustomButton); + this.setDefaultFocusedElement(this._addCustomButton); } WebInspector.DevicesSettingsTab.prototype = { @@ -156,6 +156,8 @@ WebInspector.emulatedDevicesList.addCustomDevice(device); else WebInspector.emulatedDevicesList.saveCustomDevices(); + this._addCustomButton.scrollIntoView(); + this._addCustomButton.focus(); }, /** @@ -202,38 +204,46 @@ return editor; /** + * @param {*} item + * @param {number} index * @param {!HTMLInputElement|!HTMLSelectElement} input * @return {boolean} */ - function titleValidator(input) + function titleValidator(item, index, input) { var value = input.value.trim(); return value.length > 0 && value.length < 50; } /** + * @param {*} item + * @param {number} index * @param {!HTMLInputElement|!HTMLSelectElement} input * @return {boolean} */ - function sizeValidator(input) + function sizeValidator(item, index, input) { return !WebInspector.OverridesSupport.deviceSizeValidator(input.value); } /** + * @param {*} item + * @param {number} index * @param {!HTMLInputElement|!HTMLSelectElement} input * @return {boolean} */ - function scaleValidator(input) + function scaleValidator(item, index, input) { return !WebInspector.OverridesSupport.deviceScaleFactorValidator(input.value); } /** + * @param {*} item + * @param {number} index * @param {!HTMLInputElement|!HTMLSelectElement} input * @return {boolean} */ - function userAgentValidator(input) + function userAgentValidator(item, index, input) { return true; }
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/OverridesSupport.js b/third_party/WebKit/Source/devtools/front_end/emulation/OverridesSupport.js index eabbacb..ee61c3a 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/OverridesSupport.js +++ b/third_party/WebKit/Source/devtools/front_end/emulation/OverridesSupport.js
@@ -486,7 +486,11 @@ */ _onPageResizerInsetsChanged: function(event) { - this._pageResizerInsets = /** @type {!Insets} */ (event.data); + var insets = /** @type {!Insets} */ (event.data); + if (!insets.isEqual(this._pageResizerInsets)) { + this._pageResizerInsets = insets; + this._deviceMetricsChanged(false); + } }, /**
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/OverridesView.js b/third_party/WebKit/Source/devtools/front_end/emulation/OverridesView.js index b8f96ad..990534c 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/OverridesView.js +++ b/third_party/WebKit/Source/devtools/front_end/emulation/OverridesView.js
@@ -39,24 +39,7 @@ this.registerRequiredCSS("emulation/overrides.css"); this.element.classList.add("overrides-view"); - this._tabbedPane = new WebInspector.TabbedPane(); - this._tabbedPane.setShrinkableTabs(false); - this._tabbedPane.setVerticalTabLayout(true); - - new WebInspector.OverridesView.DeviceTab().appendAsTab(this._tabbedPane); - - this._lastSelectedTabSetting = WebInspector.settings.createSetting("lastSelectedEmulateTab", "device"); - this._tabbedPane.selectTab(this._lastSelectedTabSetting.get()); - this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this); - this._tabbedPane.show(this.element); - - var resetButtonElement = createTextButton(WebInspector.UIString("Reset"), WebInspector.overridesSupport.reset.bind(WebInspector.overridesSupport)); - resetButtonElement.id = "overrides-reset-button"; - this._tabbedPane.appendAfterTabStrip(resetButtonElement); - - var disableButtonElement = createTextButton(WebInspector.UIString("Disable"), this._toggleEmulationEnabled.bind(this), "overrides-disable-button"); - disableButtonElement.id = "overrides-disable-button"; - this._tabbedPane.appendAfterTabStrip(disableButtonElement); + this._deviceElement = this._createDeviceElement(); this._splashScreenElement = this.element.createChild("div", "overrides-splash-screen"); this._splashScreenElement.appendChild(createTextButton(WebInspector.UIString("Enable emulation"), this._toggleEmulationEnabled.bind(this), "overrides-enable-button")); @@ -73,139 +56,30 @@ } WebInspector.OverridesView.prototype = { - /** - * @param {!WebInspector.Event} event - */ - _tabSelected: function(event) - { - this._lastSelectedTabSetting.set(this._tabbedPane.selectedTabId); - }, - - _overridesWarningUpdated: function() - { - var message = WebInspector.overridesSupport.warningMessage(); - this._warningFooter.classList.toggle("hidden", !message); - this._warningFooter.textContent = message; - }, - - _toggleEmulationEnabled: function() - { - WebInspector.overridesSupport.setEmulationEnabled(!WebInspector.overridesSupport.emulationEnabled()); - }, - - _emulationStateChanged: function() - { - this._unavailableSplashScreenElement.classList.toggle("hidden", WebInspector.overridesSupport.canEmulate()); - this._tabbedPane.element.classList.toggle("hidden", !WebInspector.overridesSupport.emulationEnabled()); - this._splashScreenElement.classList.toggle("hidden", WebInspector.overridesSupport.emulationEnabled() || !WebInspector.overridesSupport.canEmulate()); - }, - - __proto__: WebInspector.VBox.prototype -} - -/** - * @constructor - * @extends {WebInspector.VBox} - * @param {string} id - * @param {string} name - * @param {!Array.<!WebInspector.Setting>} settings - * @param {!Array.<function():boolean>=} predicates - */ -WebInspector.OverridesView.Tab = function(id, name, settings, predicates) -{ - WebInspector.VBox.call(this); - this._id = id; - this._name = name; - this._settings = settings; - this._predicates = predicates || []; - for (var i = 0; i < settings.length; ++i) - settings[i].addChangeListener(this.updateActiveState, this); -} - -WebInspector.OverridesView.Tab.prototype = { - /** - * @param {!WebInspector.TabbedPane} tabbedPane - */ - appendAsTab: function(tabbedPane) - { - this._tabbedPane = tabbedPane; - tabbedPane.appendTab(this._id, this._name, this); - this.updateActiveState(); - }, - - updateActiveState: function() - { - if (!this._tabbedPane) - return; - var active = false; - for (var i = 0; !active && i < this._settings.length; ++i) - active = this._settings[i].get(); - for (var i = 0; !active && i < this._predicates.length; ++i) - active = this._predicates[i](); - this._tabbedPane.toggleTabClass(this._id, "overrides-activate", active); - }, - - /** - * @param {string} name - * @param {!WebInspector.Setting} setting - * @param {function(boolean)=} callback - */ - _createSettingCheckbox: function(name, setting, callback) - { - var checkbox = WebInspector.SettingsUI.createSettingCheckbox(name, setting, true); - - function changeListener(value) - { - callback(setting.get()); - } - - if (callback) - setting.addChangeListener(changeListener); - - return checkbox; - }, - - __proto__: WebInspector.VBox.prototype -} - -/** - * @constructor - * @extends {WebInspector.OverridesView.Tab} - */ -WebInspector.OverridesView.DeviceTab = function() -{ - WebInspector.OverridesView.Tab.call(this, "device", WebInspector.UIString("Device"), [ - WebInspector.overridesSupport.settings.emulateResolution, - WebInspector.overridesSupport.settings.deviceScaleFactor, - WebInspector.overridesSupport.settings.emulateMobile, - WebInspector.overridesSupport.settings.emulateTouch - ]); - this.element.classList.add("overrides-device"); - - this.element.appendChild(this._createDeviceElement()); - - var footnote = this.element.createChild("p", "help-footnote"); - footnote.appendChild(WebInspector.linkifyDocumentationURLAsNode("setup/remote-debugging/remote-debugging", WebInspector.UIString("More information about screen emulation"))); -} - -WebInspector.OverridesView.DeviceTab.prototype = { _createDeviceElement: function() { - var fieldsetElement = createElement("fieldset"); + var container = this.element.createChild("div", "overrides-device"); + + var disableButtonElement = createTextButton(WebInspector.UIString("Disable emulation"), this._toggleEmulationEnabled.bind(this), "overrides-disable-button"); + disableButtonElement.id = "overrides-disable-button"; + container.appendChild(disableButtonElement); + + var fieldsetElement = container.createChild("fieldset"); fieldsetElement.id = "metrics-override-section"; var deviceModelElement = fieldsetElement.createChild("p", "overrides-device-model-section"); - deviceModelElement.createChild("span").textContent = WebInspector.UIString("Model:"); + deviceModelElement.createChild("span").textContent = WebInspector.UIString("Device:"); var rotateButton = createElement("button"); rotateButton.textContent = " \u21C4 "; var deviceSelect = new WebInspector.DeviceSelect(rotateButton, null); deviceModelElement.appendChild(deviceSelect.element); + var deviceModelFieldset = fieldsetElement.createChild("fieldset", "overrides-device-model-settings"); var emulateResolutionCheckbox = WebInspector.SettingsUI.createSettingCheckbox(WebInspector.UIString("Emulate screen resolution"), WebInspector.overridesSupport.settings.emulateResolution, true); - fieldsetElement.appendChild(emulateResolutionCheckbox); + deviceModelFieldset.appendChild(emulateResolutionCheckbox); var resolutionFieldset = WebInspector.SettingsUI.createSettingFieldset(WebInspector.overridesSupport.settings.emulateResolution); - fieldsetElement.appendChild(resolutionFieldset); + deviceModelFieldset.appendChild(resolutionFieldset); var tableElement = resolutionFieldset.createChild("table"); var rowElement = tableElement.createChild("tr"); @@ -227,17 +101,44 @@ rowElement.createChild("td").createTextChild(WebInspector.UIString("Device pixel ratio:")); rowElement.createChild("td").appendChild(WebInspector.SettingsUI.createSettingInputField("", WebInspector.overridesSupport.settings.deviceScaleFactor, true, 4, "80px", WebInspector.OverridesSupport.deviceScaleFactorValidator, true, true, WebInspector.UIString("\u2013"))); - var mobileCheckbox = this._createSettingCheckbox(WebInspector.UIString("Emulate mobile"), WebInspector.overridesSupport.settings.emulateMobile); + var mobileCheckbox = WebInspector.SettingsUI.createSettingCheckbox(WebInspector.UIString("Emulate mobile"), WebInspector.overridesSupport.settings.emulateMobile, true); mobileCheckbox.title = WebInspector.UIString("Enable meta viewport, overlay scrollbars, text autosizing and default 980px body width"); - fieldsetElement.appendChild(mobileCheckbox); + deviceModelFieldset.appendChild(mobileCheckbox); - fieldsetElement.appendChild(this._createSettingCheckbox(WebInspector.UIString("Shrink to fit"), WebInspector.overridesSupport.settings.deviceFitWindow)); + deviceModelFieldset.appendChild(WebInspector.SettingsUI.createSettingCheckbox(WebInspector.UIString("Emulate touch screen"), WebInspector.overridesSupport.settings.emulateTouch, true)); - fieldsetElement.appendChild(this._createSettingCheckbox(WebInspector.UIString("Emulate touch screen"), WebInspector.overridesSupport.settings.emulateTouch)); - return fieldsetElement; + var resetButtonElement = createTextButton(WebInspector.UIString("Reset"), WebInspector.overridesSupport.reset.bind(WebInspector.overridesSupport)); + resetButtonElement.id = "overrides-reset-button"; + deviceModelFieldset.appendChild(resetButtonElement); + + fieldsetElement.appendChild(WebInspector.SettingsUI.createSettingCheckbox(WebInspector.UIString("Shrink to fit"), WebInspector.overridesSupport.settings.deviceFitWindow, true)); + + var footnote = container.createChild("p", "help-footnote"); + footnote.appendChild(WebInspector.linkifyDocumentationURLAsNode("setup/remote-debugging/remote-debugging", WebInspector.UIString("More information about screen emulation"))); + + return container; }, - __proto__: WebInspector.OverridesView.Tab.prototype + _overridesWarningUpdated: function() + { + var message = WebInspector.overridesSupport.warningMessage(); + this._warningFooter.classList.toggle("hidden", !message); + this._warningFooter.textContent = message; + }, + + _toggleEmulationEnabled: function() + { + WebInspector.overridesSupport.setEmulationEnabled(!WebInspector.overridesSupport.emulationEnabled()); + }, + + _emulationStateChanged: function() + { + this._unavailableSplashScreenElement.classList.toggle("hidden", WebInspector.overridesSupport.canEmulate()); + this._deviceElement.classList.toggle("hidden", !WebInspector.overridesSupport.emulationEnabled()); + this._splashScreenElement.classList.toggle("hidden", WebInspector.overridesSupport.emulationEnabled() || !WebInspector.overridesSupport.canEmulate()); + }, + + __proto__: WebInspector.VBox.prototype } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/ResponsiveDesignView.js b/third_party/WebKit/Source/devtools/front_end/emulation/ResponsiveDesignView.js index fb4b94eb..ec00cf5 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/ResponsiveDesignView.js +++ b/third_party/WebKit/Source/devtools/front_end/emulation/ResponsiveDesignView.js
@@ -532,7 +532,7 @@ this._inspectedPagePlaceholder.onResize(); } - if (this._cachedCssPageWidth !== cssPageHeight || this._cachedCssPageHeight !== cssPageHeight) { + if (this._cachedCssPageWidth !== cssPageWidth || this._cachedCssPageHeight !== cssPageHeight) { this._pageContainerImage.style.width = cssPageWidth + "px"; this._pageContainerImage.style.height = cssPageHeight + "px"; }
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/module.json b/third_party/WebKit/Source/devtools/front_end/emulation/module.json index 8fed14c..fcb1292 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/module.json +++ b/third_party/WebKit/Source/devtools/front_end/emulation/module.json
@@ -5,7 +5,7 @@ "name": "emulation", "title": "Emulation", "order": 10, - "persistence": "permanent", + "persistence": "closeable", "className": "WebInspector.OverridesView" }, {
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/overrides.css b/third_party/WebKit/Source/devtools/front_end/emulation/overrides.css index 3baa018..85a72a7 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/overrides.css +++ b/third_party/WebKit/Source/devtools/front_end/emulation/overrides.css
@@ -30,8 +30,9 @@ .overrides-view fieldset { border: none; - padding: 0 0 5px 15px; flex: 0 0 auto; + padding: 0; + margin: 0; } .overrides-view fieldset p { @@ -41,7 +42,7 @@ border: 0; } -.overrides-view fieldset p label { +.overrides-device-model-settings p label { display: inline-block; } @@ -57,38 +58,12 @@ overflow: hidden; } -/* Network tab */ - -.overrides-network fieldset { - padding-top: 5px; -} - -.overrides-network fieldset p { - width: 100%; - margin-left: 2px; -} - -.overrides-network fieldset select { - margin: 5px 0; -} - -.overrides-network fieldset p label { - cursor: default; - margin-right: 5px; -} - -.overrides-network fieldset input[type='text'] { - display: block; - width: 100%; - max-width: 400px; - min-width: 176px; - margin: 5px 0; -} - /* Device tab */ .overrides-device { - width: 100%; + flex: 1 1 auto; + overflow: auto; + padding: 12px; } .overrides-device input.numeric { @@ -105,10 +80,6 @@ white-space: nowrap; } -.overrides-device button { - margin: 0 3px; -} - .overrides-device label { margin-bottom: 10px; } @@ -138,12 +109,11 @@ } .overrides-device .overrides-device-model-section { - margin-bottom: 15px; white-space: nowrap; } .overrides-device .overrides-device-model-section > span { - padding: 0 10px 0 3px; + padding-right: 10px; } .overrides-device .overrides-device-model-section select { @@ -160,25 +130,17 @@ width: 140px; } -/* Media tab */ - -.overrides-media > label { - margin-bottom: 4px; +.overrides-device .overrides-device-model-section .mode-container label { + margin: 0; + display: inline-block; } - -.tabbed-pane-header-tab.overrides-activate { - opacity: 0.8; +fieldset.overrides-device-model-settings { + padding: 16px; } -.tabbed-pane-header-tab.overrides-activate .tabbed-pane-header-tab-title::after { - padding-left: 3px; - content: "\2713"; - color: rgb(25, 100, 228); -} - -.tabbed-pane-header-tab.overrides-activate.selected { - opacity: 1; +.overrides-device-model-settings > fieldset { + margin-left: 16px; } .overrides-view input[type=text]:enabled:focus, @@ -209,8 +171,8 @@ } .overrides-view .overrides-footer { - flex: none; - padding: 0 0 1px 3px; + flex: 0 0 auto; + padding: 5px 8px; border-top: 1px solid rgb(203,203,203); background-color: #eee; } @@ -239,8 +201,8 @@ } .overrides-splash-screen { - padding: 10px 10px; flex: auto; + padding: 12px; } .overrides-splash-screen .toolbar { @@ -250,13 +212,6 @@ top: 8px; } -#overrides-reset-button, #overrides-disable-button { - margin: 9px 0 0 17px; - display: block; - width: 60px; -} - -.overrides-enable-button { - margin: 4px !important; + margin-bottom: 12px; }
diff --git a/third_party/WebKit/Source/devtools/front_end/settings/EditFileSystemView.js b/third_party/WebKit/Source/devtools/front_end/settings/EditFileSystemView.js index bf90adf..627629a0 100644 --- a/third_party/WebKit/Source/devtools/front_end/settings/EditFileSystemView.js +++ b/third_party/WebKit/Source/devtools/front_end/settings/EditFileSystemView.js
@@ -85,14 +85,19 @@ return; this._mappingsList.clear(); - this._mappings = WebInspector.fileSystemMapping.mappingEntries(this._fileSystemPath); - for (var entry of this._mappings) { - if (entry.configurable) + this._mappings = []; + var mappings = WebInspector.fileSystemMapping.mappingEntries(this._fileSystemPath); + for (var entry of mappings) { + if (entry.configurable) { this._mappingsList.appendItem(entry, true); + this._mappings.push(entry); + } } - for (var entry of this._mappings) { - if (!entry.configurable) + for (var entry of mappings) { + if (!entry.configurable) { this._mappingsList.appendItem(entry, false); + this._mappings.push(entry); + } } this._excludedFoldersList.clear(); @@ -156,16 +161,12 @@ */ removeItemRequested: function(item, index) { - this._muteUpdate = true; if (item instanceof WebInspector.FileSystemMapping.Entry) { var entry = this._mappings[index]; WebInspector.fileSystemMapping.removeFileMapping(entry.fileSystemPath, entry.urlPrefix, entry.pathPrefix); - this._mappingsList.removeItem(index); } else { WebInspector.isolatedFileSystemManager.fileSystem(this._fileSystemPath).removeExcludedFolder(this._excludedFolders[index]); - this._excludedFoldersList.removeItem(index); } - this._muteUpdate = false; }, /** @@ -236,24 +237,36 @@ return editor; /** + * @param {*} item + * @param {number} index * @param {!HTMLInputElement|!HTMLSelectElement} input * @return {boolean} * @this {WebInspector.EditFileSystemView} */ - function urlPrefixValidator(input) + function urlPrefixValidator(item, index, input) { var prefix = this._normalizePrefix(input.value); + for (var i = 0; i < this._mappings.length; ++i) { + if (i !== index && this._mappings[i].configurable && this._mappings[i].urlPrefix === prefix) + return false; + } return !!prefix; } /** + * @param {*} item + * @param {number} index * @param {!HTMLInputElement|!HTMLSelectElement} input * @return {boolean} * @this {WebInspector.EditFileSystemView} */ - function pathPrefixValidator(input) + function pathPrefixValidator(item, index, input) { var prefix = this._normalizePrefix(input.value); + for (var i = 0; i < this._mappings.length; ++i) { + if (i !== index && this._mappings[i].configurable && this._mappings[i].pathPrefix === prefix) + return false; + } return !!prefix; } }, @@ -279,13 +292,20 @@ return editor; /** + * @param {*} item + * @param {number} index * @param {!HTMLInputElement|!HTMLSelectElement} input * @return {boolean} * @this {WebInspector.EditFileSystemView} */ - function pathPrefixValidator(input) + function pathPrefixValidator(item, index, input) { var prefix = this._normalizePrefix(input.value); + var configurableCount = WebInspector.isolatedFileSystemManager.fileSystem(this._fileSystemPath).excludedFolders().size; + for (var i = 0; i < configurableCount; ++i) { + if (i !== index && this._excludedFolders[i] === prefix) + return false; + } return !!prefix; } },
diff --git a/third_party/WebKit/Source/devtools/front_end/settings/FrameworkBlackboxSettingsTab.js b/third_party/WebKit/Source/devtools/front_end/settings/FrameworkBlackboxSettingsTab.js index f994054f..3e18f628 100644 --- a/third_party/WebKit/Source/devtools/front_end/settings/FrameworkBlackboxSettingsTab.js +++ b/third_party/WebKit/Source/devtools/front_end/settings/FrameworkBlackboxSettingsTab.js
@@ -45,9 +45,6 @@ _settingUpdated: function() { - if (this._muteUpdate) - return; - this._list.clear(); var patterns = this._setting.getAsArray(); for (var i = 0; i < patterns.length; ++i) @@ -87,10 +84,7 @@ { var patterns = this._setting.getAsArray(); patterns.splice(index, 1); - this._muteUpdate = true; this._setting.setAsArray(patterns); - this._muteUpdate = false; - this._list.removeItem(index); }, /** @@ -141,19 +135,28 @@ titles.createChild("div", "blackbox-behavior").textContent = WebInspector.UIString("Behavior"); var fields = content.createChild("div", "blackbox-edit-row"); - fields.createChild("div", "blackbox-pattern").appendChild(editor.createInput("pattern", "text", "/framework\\.js$", patternValidator)); + fields.createChild("div", "blackbox-pattern").appendChild(editor.createInput("pattern", "text", "/framework\\.js$", patternValidator.bind(this))); fields.createChild("div", "blackbox-separator blackbox-separator-invisible"); fields.createChild("div", "blackbox-behavior").appendChild(editor.createSelect("behavior", [this._blackboxLabel, this._disabledLabel], behaviorValidator)); return editor; /** + * @param {*} item + * @param {number} index * @param {!HTMLInputElement|!HTMLSelectElement} input + * @this {WebInspector.FrameworkBlackboxSettingsTab} * @return {boolean} */ - function patternValidator(input) + function patternValidator(item, index, input) { var pattern = input.value.trim(); + var patterns = this._setting.getAsArray(); + for (var i = 0; i < patterns.length; ++i) { + if (i !== index && patterns[i].pattern === pattern) + return false; + } + var regex; try { regex = new RegExp(pattern); @@ -163,10 +166,12 @@ } /** + * @param {*} item + * @param {number} index * @param {!HTMLInputElement|!HTMLSelectElement} input * @return {boolean} */ - function behaviorValidator(input) + function behaviorValidator(item, index, input) { return true; }
diff --git a/third_party/WebKit/Source/devtools/front_end/settings/editFileSystemView.css b/third_party/WebKit/Source/devtools/front_end/settings/editFileSystemView.css index 7d8c654..4ee0115d 100644 --- a/third_party/WebKit/Source/devtools/front_end/settings/editFileSystemView.css +++ b/third_party/WebKit/Source/devtools/front_end/settings/editFileSystemView.css
@@ -23,7 +23,6 @@ } .file-system-list { - max-width: 600px; flex: auto; }
diff --git a/third_party/WebKit/Source/devtools/front_end/settings/settingsScreen.css b/third_party/WebKit/Source/devtools/front_end/settings/settingsScreen.css index dbfaaeb..fa9f5f3 100644 --- a/third_party/WebKit/Source/devtools/front_end/settings/settingsScreen.css +++ b/third_party/WebKit/Source/devtools/front_end/settings/settingsScreen.css
@@ -292,6 +292,7 @@ margin-bottom: 18px; padding: 0 8px; border-left: 1px solid hsl(0, 0%, 90%); + max-width: 800px; } .settings-tab .file-system-header {
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js index 457d057..305de96d 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js
@@ -945,17 +945,6 @@ }, /** - * @override - * @param {number} index - * @return {?Array.<!{title: string, value: (string|!Element)}>} - */ - prepareHighlightedEntryInfo: function(index) - { - var request = /** @type {!WebInspector.TimelineModel.NetworkRequest} */ (this._requests[index]); - return WebInspector.TimelineUIUtils.buildNetworkRequestInfo(request); - }, - - /** * @param {!Array.<!WebInspector.TracingModel.Event>} events */ _appendTimelineData: function(events)
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineModel.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineModel.js index c1c839ed..11752c3 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineModel.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineModel.js
@@ -189,13 +189,21 @@ * @param {!Array.<!WebInspector.TracingModel.Event>} events * @param {function(!WebInspector.TracingModel.Event)} onStartEvent * @param {function(!WebInspector.TracingModel.Event)} onEndEvent - * @param {function(!WebInspector.TracingModel.Event,?WebInspector.TracingModel.Event)=} onInstantEvent + * @param {function(!WebInspector.TracingModel.Event,?WebInspector.TracingModel.Event)|undefined=} onInstantEvent + * @param {number=} startTime + * @param {number=} endTime */ -WebInspector.TimelineModel.forEachEvent = function(events, onStartEvent, onEndEvent, onInstantEvent) +WebInspector.TimelineModel.forEachEvent = function(events, onStartEvent, onEndEvent, onInstantEvent, startTime, endTime) { + startTime = startTime || 0; + endTime = endTime || Infinity; var stack = []; for (var i = 0; i < events.length; ++i) { var e = events[i]; + if ((e.endTime || e.startTime) < startTime) + continue; + if (e.startTime >= endTime) + break; if (WebInspector.TracingModel.isAsyncPhase(e.phase) || WebInspector.TracingModel.isFlowPhase(e.phase)) continue; while (stack.length && stack.peekLast().endTime <= e.startTime) @@ -1498,12 +1506,6 @@ */ function filter(e) { - if (!e.endTime && e.phase !== WebInspector.TracingModel.Phase.Instant) - return false; - if (e.endTime <= startTime || e.startTime >= endTime) - return false; - if (WebInspector.TracingModel.isAsyncPhase(e.phase)) - return false; for (var i = 0, l = filters.length; i < l; ++i) { if (!filters[i].accept(e)) return false; @@ -1553,7 +1555,7 @@ parent = parent.parent; } - WebInspector.TimelineModel.forEachEvent(events, onStartEvent, onEndEvent); + WebInspector.TimelineModel.forEachEvent(events, onStartEvent, onEndEvent, undefined, startTime, endTime); root.totalTime -= root.selfTime; root.selfTime = 0; return root; @@ -1575,6 +1577,7 @@ var nodesOnStack = /** @type {!Set<string>} */ (new Set()); if (topDownTree.children) topDownTree.children.forEach(processNode); + buRoot.totalTime = topDownTree.totalTime; /** * @param {!WebInspector.TimelineModel.ProfileTreeNode} tdNode @@ -1582,6 +1585,8 @@ function processNode(tdNode) { var buParent = groupingCallback && groupingCallback(tdNode) || buRoot; + if (buParent !== buRoot) + buRoot.children.set(buParent.id, buParent); appendNode(tdNode, buParent); var hadNode = nodesOnStack.has(tdNode.id); if (!hadNode)
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js index 1e5db322..3765521 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
@@ -452,6 +452,7 @@ _buildGroupNode: function(id, event) { var groupNode = new WebInspector.TimelineModel.ProfileTreeNode(); + groupNode.id = id; groupNode.selfTime = 0; groupNode.totalTime = 0; groupNode.children = new Map(); @@ -617,10 +618,7 @@ this._groupNodes = new Map(); var nodeToGroupId = this._nodeToGroupIdFunction(); var nodeToGroupNode = nodeToGroupId ? this._nodeToGroupNode.bind(this, nodeToGroupId) : null; - var bottomUpRoot = WebInspector.TimelineModel.buildBottomUpTree(topDownTree, nodeToGroupNode); - for (var group of this._groupNodes) - bottomUpRoot.children.set(group[0], group[1]); - return bottomUpRoot; + return WebInspector.TimelineModel.buildBottomUpTree(topDownTree, nodeToGroupNode); }, __proto__: WebInspector.AggregatedTimelineTreeView.prototype
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js index d37770b3..f5f07ae 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
@@ -308,7 +308,7 @@ break; case recordType.FunctionCall: // Omit internally generated script names. - if (eventData["scriptName"]) + if (eventData && eventData["scriptName"]) detailsText = linkifyLocationAsText(eventData["scriptId"], eventData["scriptLine"], 0); break; case recordType.JSFrame:
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineView.js index 448c76f..6353e48 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineView.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineView.js
@@ -733,8 +733,10 @@ var taskBarElement = e.target.enclosingNodeOrSelfWithClass("timeline-graph-bar"); if (taskBarElement && taskBarElement._tasksInfo) { - var offset = taskBarElement.offsetLeft; - this._timelineGrid.showCurtains(offset >= 0 ? offset : 0, taskBarElement.offsetWidth); + var parentWidth = taskBarElement.parentElement.offsetWidth; + var offset = Math.max(0, taskBarElement.offsetLeft); + var width = taskBarElement.offsetWidth; + this._timelineGrid.showCurtains(offset / parentWidth, (offset + width) / parentWidth); } else this._timelineGrid.hideCurtains(); },
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css index c6d940b4..949c51b8 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css +++ b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
@@ -585,22 +585,6 @@ background-color: #aaa; } -.timeline-cpu-curtain-left, .timeline-cpu-curtain-right { - background-color: rgba(210, 210, 210, 0.5); - position: absolute; - top: 0; - height: 100%; - z-index: 300; -} - -.timeline-cpu-curtain-left { - left: 0; -} - -.timeline-cpu-curtain-right { - right: 0; -} - .image-preview-container { background: transparent; text-align: left;
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/ContextMenu.js b/third_party/WebKit/Source/devtools/front_end/ui/ContextMenu.js index 5b988e9..430abb6 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/ContextMenu.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/ContextMenu.js
@@ -401,8 +401,19 @@ this._softMenu.show(this._event.target.ownerDocument, this._x, this._y); } else { InspectorFrontendHost.showContextMenuAtPoint(this._x, this._y, menuObject, this._event.target.ownerDocument); - InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.ContextMenuCleared, this._menuCleared, this); - InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.ContextMenuItemSelected, this._onItemSelected, this); + + /** + * @this {WebInspector.ContextMenu} + */ + function listenToEvents() + { + InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.ContextMenuCleared, this._menuCleared, this); + InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.ContextMenuItemSelected, this._onItemSelected, this); + } + + // showContextMenuAtPoint call above synchronously issues a clear event for previous context menu (if any), + // so we skip it before subscribing to the clear event. + setImmediate(listenToEvents.bind(this)); } },
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/ListWidget.js b/third_party/WebKit/Source/devtools/front_end/ui/ListWidget.js index 8de1aab0..1a53abdc 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/ListWidget.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/ListWidget.js
@@ -228,10 +228,11 @@ if (element) element.classList.add("hidden"); + var index = element ? this._elements.indexOf(element) : -1; this._editor = this._delegate.beginEdit(item); this._updatePlaceholder(); this._list.insertBefore(this._editor.element, insertionPoint); - this._editor.beginEdit(element ? WebInspector.UIString("Save") : WebInspector.UIString("Add"), this._commitEditing.bind(this), this._stopEditing.bind(this)); + this._editor.beginEdit(item, index, element ? WebInspector.UIString("Save") : WebInspector.UIString("Add"), this._commitEditing.bind(this), this._stopEditing.bind(this)); }, _commitEditing: function() @@ -295,13 +296,17 @@ this._controls = []; /** @type {!Map<string, !HTMLInputElement|!HTMLSelectElement>} */ this._controlByName = new Map(); - /** @type {!Array<function((!HTMLInputElement|!HTMLSelectElement)):boolean>} */ + /** @type {!Array<function(*, number, (!HTMLInputElement|!HTMLSelectElement)):boolean>} */ this._validators = []; /** @type {?function()} */ this._commit = null; /** @type {?function()} */ this._cancel = null; + /** @type {*|null} */ + this._item = null; + /** @type {number} */ + this._index = -1; } WebInspector.ListWidget.Editor.prototype = { @@ -317,7 +322,7 @@ * @param {string} name * @param {string} type * @param {string} title - * @param {function((!HTMLInputElement|!HTMLSelectElement)):boolean} validator + * @param {function(*, number, (!HTMLInputElement|!HTMLSelectElement)):boolean} validator * @return {!HTMLInputElement} */ createInput: function(name, type, title, validator) @@ -336,7 +341,7 @@ /** * @param {string} name * @param {!Array<string>} options - * @param {function((!HTMLInputElement|!HTMLSelectElement)):boolean} validator + * @param {function(*, number, (!HTMLInputElement|!HTMLSelectElement)):boolean} validator * @return {!HTMLSelectElement} */ createSelect: function(name, options, validator) @@ -372,7 +377,7 @@ var allValid = true; for (var index = 0; index < this._controls.length; ++index) { var input = this._controls[index]; - var valid = this._validators[index].call(null, input); + var valid = this._validators[index].call(null, this._item, this._index, input); input.classList.toggle("error-input", !valid && !forceValid); allValid &= valid; } @@ -380,17 +385,21 @@ }, /** + * @param {*} item + * @param {number} index * @param {string} commitButtonTitle * @param {function()} commit * @param {function()} cancel */ - beginEdit: function(commitButtonTitle, commit, cancel) + beginEdit: function(item, index, commitButtonTitle, commit, cancel) { this._commit = commit; this._cancel = cancel; + this._item = item; + this._index = index; this._commitButton.textContent = commitButtonTitle; - this.element.scrollIntoView(); + this.element.scrollIntoView(false); if (this._controls.length) this._controls[0].focus(); this._validateControls(true); @@ -404,6 +413,8 @@ var commit = this._commit; this._commit = null; this._cancel = null; + this._item = null; + this._index = -1; commit(); }, @@ -412,6 +423,8 @@ var cancel = this._cancel; this._commit = null; this._cancel = null; + this._item = null; + this._index = -1; cancel(); } }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js b/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js index 324787d..6025c53 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js
@@ -98,8 +98,7 @@ maxHeight -= y - WebInspector.Dialog.modalHostView().element.totalOffsetTop(); this.element.style.maxHeight = maxHeight + "px"; - if (!this._parentMenu) - this._focus(); + this._focus(); }, discard: function()
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/OverviewGrid.js b/third_party/WebKit/Source/devtools/front_end/ui_lazy/OverviewGrid.js index 7d32f93..690fba8f 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/OverviewGrid.js +++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/OverviewGrid.js
@@ -44,6 +44,7 @@ this.element.appendChild(this._grid.element); this._window = new WebInspector.OverviewGrid.Window(this.element, this._grid.dividersLabelBarElement); + this._window.addEventListener(WebInspector.OverviewGrid.Events.WindowChanged, this._onWindowChanged, this); } WebInspector.OverviewGrid.prototype = { @@ -132,6 +133,11 @@ setResizeEnabled: function(enabled) { this._window.setEnabled(enabled); + }, + + _onWindowChanged: function() + { + this._grid.showCurtains(this.windowLeft(), this.windowRight()); } } @@ -161,17 +167,13 @@ this._parentElement.addEventListener("mousewheel", this._onMouseWheel.bind(this), true); this._parentElement.addEventListener("dblclick", this._resizeWindowMaximum.bind(this), true); - - this._overviewWindowElement = parentElement.createChild("div", "overview-grid-window"); - this._overviewWindowElement.appendChild(WebInspector.Widget.createStyleElement("ui_lazy/overviewGrid.css")); - this._overviewWindowBordersElement = parentElement.createChild("div", "overview-grid-window-rulers"); - parentElement.createChild("div", "overview-grid-dividers-background"); + this._parentElement.appendChild(WebInspector.Widget.createStyleElement("ui_lazy/overviewGrid.css")); this._leftResizeElement = parentElement.createChild("div", "overview-grid-window-resizer"); this._leftResizeElement.style.left = 0; WebInspector.installDragHandle(this._leftResizeElement, this._resizerElementStartDragging.bind(this), this._leftResizeElementDragging.bind(this), null, "ew-resize"); - this._rightResizeElement = parentElement.createChild("div", "overview-grid-window-resizer overview-grid-window-resizer-right"); + this._rightResizeElement = parentElement.createChild("div", "overview-grid-window-resizer"); this._rightResizeElement.style.right = 0; WebInspector.installDragHandle(this._rightResizeElement, this._resizerElementStartDragging.bind(this), this._rightResizeElementDragging.bind(this), null, "ew-resize"); this.setEnabled(true); @@ -187,11 +189,6 @@ { this.windowLeft = 0.0; this.windowRight = 1.0; - - this._overviewWindowElement.style.left = "0%"; - this._overviewWindowElement.style.width = "100%"; - this._overviewWindowBordersElement.style.left = "0%"; - this._overviewWindowBordersElement.style.right = "0%"; this._leftResizeElement.style.left = "0%"; this._rightResizeElement.style.left = "100%"; this.setEnabled(true); @@ -364,11 +361,6 @@ this.windowRight = windowRight; this._rightResizeElement.style.left = right * 100 + "%"; - this._overviewWindowElement.style.left = left * 100 + "%"; - this._overviewWindowBordersElement.style.left = left * 100 + "%"; - this._overviewWindowElement.style.width = (right - left) * 100 + "%"; - this._overviewWindowBordersElement.style.right = (1 - right) * 100 + "%"; - this.dispatchEventToListeners(WebInspector.OverviewGrid.Events.WindowChanged); },
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/TimelineGrid.js b/third_party/WebKit/Source/devtools/front_end/ui_lazy/TimelineGrid.js index 2231ca0..d656b32 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/TimelineGrid.js +++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/TimelineGrid.js
@@ -44,8 +44,8 @@ this._dividersLabelBarElement = this._gridHeaderElement.createChild("div", "resources-dividers-label-bar"); this.element.appendChild(this._gridHeaderElement); - this._leftCurtainElement = this.element.createChild("div", "timeline-cpu-curtain-left"); - this._rightCurtainElement = this.element.createChild("div", "timeline-cpu-curtain-right"); + this._leftCurtainElement = this.element.createChild("div", "timeline-curtain-left"); + this._rightCurtainElement = this.element.createChild("div", "timeline-curtain-right"); } /** @@ -278,14 +278,14 @@ }, /** - * @param {number} gapOffset - * @param {number} gapWidth + * @param {number} left + * @param {number} right */ - showCurtains: function(gapOffset, gapWidth) + showCurtains: function(left, right) { - this._leftCurtainElement.style.width = gapOffset + "px"; + this._leftCurtainElement.style.width = (100 * left).toFixed(2) + "%"; this._leftCurtainElement.classList.remove("hidden"); - this._rightCurtainElement.style.left = (gapOffset + gapWidth) + "px"; + this._rightCurtainElement.style.width = (100 * (1 - right)).toFixed(2) + "%"; this._rightCurtainElement.classList.remove("hidden"); },
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/TimelineOverviewPane.js b/third_party/WebKit/Source/devtools/front_end/ui_lazy/TimelineOverviewPane.js index 5d604ed9..6f6fce0 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/TimelineOverviewPane.js +++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/TimelineOverviewPane.js
@@ -272,6 +272,8 @@ reset: function() { + this._windowStartTime = 0; + this._windowEndTime = Infinity; this._overviewCalculator.reset(); this._overviewGrid.reset(); this._overviewGrid.setResizeEnabled(false);
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/overviewGrid.css b/third_party/WebKit/Source/devtools/front_end/ui_lazy/overviewGrid.css index 595c5e4..fd9141f 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/overviewGrid.css +++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/overviewGrid.css
@@ -13,52 +13,15 @@ pointer-events: none; } -.overview-grid-window { - background-color: white; - position: absolute; - left: 0; - right: 0; - top: 0; - height: 20px; - z-index: 150; -} - -.overview-grid-dividers-background { - left: 0; - right: 0; - top: 0; - height: 20px; - background-color: black; - position: absolute; -} - -.overview-grid-window-rulers { - top: 0; - bottom: 0; - position: absolute; - opacity: 0.2; - border-right: 1px solid black; - border-left: 1px solid black; - z-index: 250; - pointer-events: none; -} - .overview-grid-window-resizer { position: absolute; - top: 0; + top: -1px; height: 20px; - width: 5px; - margin-left: -2px; - margin-right: -3px; - background-color: rgb(153, 153, 153); - z-index: 500; - border-radius: 2px; - box-shadow: white 1px 0 0, white -1px 0 0, white 0 1px 0, white 0 -1px 0; -} - -.overview-grid-window-resizer-right { + width: 6px; margin-left: -3px; - margin-right: -2px; + background-color: rgb(153, 153, 153); + border: 1px solid white; + z-index: 500; } .overview-grid-cursor-area {
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/timelineGrid.css b/third_party/WebKit/Source/devtools/front_end/ui_lazy/timelineGrid.css index 68d0f183..3d952f4 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/timelineGrid.css +++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/timelineGrid.css
@@ -65,3 +65,20 @@ height: 20px; pointer-events: none; } + +.timeline-curtain-left, .timeline-curtain-right { + background-color: hsla(0, 0%, 80%, 0.3); + position: absolute; + top: 0; + height: 100%; + z-index: 300; + pointer-events: none; +} + +.timeline-curtain-left { + left: 0; +} + +.timeline-curtain-right { + right: 0; +}
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasGradient.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasGradient.cpp index 3d5f361..01b1c50c 100644 --- a/third_party/WebKit/Source/modules/canvas2d/CanvasGradient.cpp +++ b/third_party/WebKit/Source/modules/canvas2d/CanvasGradient.cpp
@@ -44,20 +44,20 @@ { } -void CanvasGradient::addColorStop(float value, const String& color, ExceptionState& exceptionState) +void CanvasGradient::addColorStop(float value, const String& colorString, ExceptionState& exceptionState) { if (!(value >= 0 && value <= 1.0f)) { exceptionState.throwDOMException(IndexSizeError, "The provided value (" + String::number(value) + ") is outside the range (0.0, 1.0)."); return; } - RGBA32 rgba = 0; - if (!parseColorOrCurrentColor(rgba, color, 0 /*canvas*/)) { - exceptionState.throwDOMException(SyntaxError, "The value provided ('" + color + "') could not be parsed as a color."); + Color color = 0; + if (!parseColorOrCurrentColor(color, colorString, 0 /*canvas*/)) { + exceptionState.throwDOMException(SyntaxError, "The value provided ('" + colorString + "') could not be parsed as a color."); return; } - m_gradient->addColorStop(value, Color(rgba)); + m_gradient->addColorStop(value, color); } } // namespace
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp index c39c19b..c5771ec5 100644 --- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp +++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
@@ -384,14 +384,14 @@ colorString = style.getAsString(); if (colorString == state().unparsedStrokeColor()) return; - RGBA32 parsedColor = 0; + Color parsedColor = 0; if (!parseColorOrCurrentColor(parsedColor, colorString, canvas())) return; - if (state().strokeStyle()->isEquivalentRGBA(parsedColor)) { + if (state().strokeStyle()->isEquivalentRGBA(parsedColor.rgb())) { modifiableState().setUnparsedStrokeColor(colorString); return; } - canvasStyle = CanvasStyle::createFromRGBA(parsedColor); + canvasStyle = CanvasStyle::createFromRGBA(parsedColor.rgb()); } else if (style.isCanvasGradient()) { canvasStyle = CanvasStyle::createFromGradient(style.getAsCanvasGradient()); } else if (style.isCanvasPattern()) { @@ -424,14 +424,14 @@ colorString = style.getAsString(); if (colorString == state().unparsedFillColor()) return; - RGBA32 parsedColor = 0; + Color parsedColor = 0; if (!parseColorOrCurrentColor(parsedColor, colorString, canvas())) return; - if (state().fillStyle()->isEquivalentRGBA(parsedColor)) { + if (state().fillStyle()->isEquivalentRGBA(parsedColor.rgb())) { modifiableState().setUnparsedFillColor(colorString); return; } - canvasStyle = CanvasStyle::createFromRGBA(parsedColor); + canvasStyle = CanvasStyle::createFromRGBA(parsedColor.rgb()); } else if (style.isCanvasGradient()) { canvasStyle = CanvasStyle::createFromGradient(style.getAsCanvasGradient()); } else if (style.isCanvasPattern()) { @@ -554,14 +554,14 @@ return Color(state().shadowColor()).serialized(); } -void CanvasRenderingContext2D::setShadowColor(const String& color) +void CanvasRenderingContext2D::setShadowColor(const String& colorString) { - RGBA32 rgba; - if (!parseColorOrCurrentColor(rgba, color, canvas())) + Color color; + if (!parseColorOrCurrentColor(color, colorString, canvas())) return; - if (state().shadowColor() == rgba) + if (state().shadowColor() == color) return; - modifiableState().setShadowColor(rgba); + modifiableState().setShadowColor(color.rgb()); } const Vector<float>& CanvasRenderingContext2D::getLineDash() const
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasStyle.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasStyle.cpp index 183fcf6..a1c55bf 100644 --- a/third_party/WebKit/Source/modules/canvas2d/CanvasStyle.cpp +++ b/third_party/WebKit/Source/modules/canvas2d/CanvasStyle.cpp
@@ -41,7 +41,7 @@ enum ColorParseResult { ParsedRGBA, ParsedCurrentColor, ParsedSystemColor, ParseFailed }; -static ColorParseResult parseColor(RGBA32& parsedColor, const String& colorString) +static ColorParseResult parseColor(Color& parsedColor, const String& colorString) { if (equalIgnoringCase(colorString, "currentcolor")) return ParsedCurrentColor; @@ -53,16 +53,16 @@ return ParseFailed; } -static RGBA32 currentColor(HTMLCanvasElement* canvas) +static Color currentColor(HTMLCanvasElement* canvas) { if (!canvas || !canvas->inDocument() || !canvas->inlineStyle()) return Color::black; - RGBA32 rgba = Color::black; - CSSParser::parseColor(rgba, canvas->inlineStyle()->getPropertyValue(CSSPropertyColor)); - return rgba; + Color color = Color::black; + CSSParser::parseColor(color, canvas->inlineStyle()->getPropertyValue(CSSPropertyColor)); + return color; } -bool parseColorOrCurrentColor(RGBA32& parsedColor, const String& colorString, HTMLCanvasElement* canvas) +bool parseColorOrCurrentColor(Color& parsedColor, const String& colorString, HTMLCanvasElement* canvas) { ColorParseResult parseResult = parseColor(parsedColor, colorString); switch (parseResult) {
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasStyle.h b/third_party/WebKit/Source/modules/canvas2d/CanvasStyle.h index 6daf99f..742e2706 100644 --- a/third_party/WebKit/Source/modules/canvas2d/CanvasStyle.h +++ b/third_party/WebKit/Source/modules/canvas2d/CanvasStyle.h
@@ -73,7 +73,7 @@ Member<CanvasPattern> m_pattern; }; -bool parseColorOrCurrentColor(RGBA32& parsedColor, const String& colorString, HTMLCanvasElement*); +bool parseColorOrCurrentColor(Color& parsedColor, const String& colorString, HTMLCanvasElement*); } // namespace blink
diff --git a/third_party/WebKit/Source/modules/modules.gni b/third_party/WebKit/Source/modules/modules.gni index d6cb0e6d..d423092 100644 --- a/third_party/WebKit/Source/modules/modules.gni +++ b/third_party/WebKit/Source/modules/modules.gni
@@ -7,37 +7,38 @@ blink_modules_output_dir = "$root_gen_dir/blink/modules" _gypi = exec_script( - "//build/gypi_to_gn.py", - [ rebase_path("modules.gypi"), - "--replace=<(SHARED_INTERMEDIATE_DIR)=$root_gen_dir", - "--replace=<(blink_modules_output_dir)=$blink_modules_output_dir" ], - "scope", - [ "modules.gypi" ]) + "//build/gypi_to_gn.py", + [ + rebase_path("modules.gypi"), + "--replace=<(SHARED_INTERMEDIATE_DIR)=$root_gen_dir", + "--replace=<(blink_modules_output_dir)=$blink_modules_output_dir", + ], + "scope", + [ "modules.gypi" ]) _tmp_modules_idl_files = _gypi.modules_idl_files + # modules_idl_files has a magic variable in it that is an embedder hook, # remove that since it's not a file (need to do this before rebasing). -_tmp_modules_idl_files -= [ - "<@(extra_blink_module_idl_files)", -] +_tmp_modules_idl_files -= [ "<@(extra_blink_module_idl_files)" ] modules_idl_files = get_path_info(_tmp_modules_idl_files, "abspath") modules_dictionary_idl_files = - get_path_info(_gypi.modules_dictionary_idl_files, "abspath") + get_path_info(_gypi.modules_dictionary_idl_files, "abspath") # 'partial interface' or target (right side of) 'implements' modules_dependency_idl_files = - get_path_info(_gypi.modules_dependency_idl_files, "abspath") + get_path_info(_gypi.modules_dependency_idl_files, "abspath") modules_event_idl_files = - get_path_info(_gypi.modules_event_idl_files, "abspath") + get_path_info(_gypi.modules_event_idl_files, "abspath") # interfaces that inherit from Event generated_modules_files = - get_path_info(_gypi.generated_modules_files, "abspath") + get_path_info(_gypi.generated_modules_files, "abspath") generated_modules_dictionary_files = - get_path_info(_gypi.generated_modules_dictionary_files, "abspath") + get_path_info(_gypi.generated_modules_dictionary_files, "abspath") # Remove GYP variables from the list (need to do this before rebasing). _tmp_modules_files = _gypi.modules_files @@ -47,12 +48,13 @@ "<@(generated_modules_files)", ] modules_files = get_path_info(_tmp_modules_files, "abspath") + # Account for GYP var expansion. modules_files += generated_modules_files + generated_modules_dictionary_files # 'partial interface' or target (right side of) 'implements' modules_testing_dependency_idl_files = - get_path_info(_gypi.modules_testing_dependency_idl_files, "abspath") + get_path_info(_gypi.modules_testing_dependency_idl_files, "abspath") modules_testing_files = get_path_info(_gypi.modules_testing_files, "abspath") modules_unittest_files = get_path_info(_gypi.modules_unittest_files, "abspath")
diff --git a/third_party/WebKit/Source/modules/webdatabase/Database.cpp b/third_party/WebKit/Source/modules/webdatabase/Database.cpp index b3e2973..737f4f8 100644 --- a/third_party/WebKit/Source/modules/webdatabase/Database.cpp +++ b/third_party/WebKit/Source/modules/webdatabase/Database.cpp
@@ -86,6 +86,13 @@ namespace blink { +// Defines static local variable after making sure that guid lock is held. +// (We can't use DEFINE_STATIC_LOCAL for this because it asserts thread +// safety, which is externally guaranteed by the guideMutex lock) +#define DEFINE_STATIC_LOCAL_WITH_LOCK(type, name, arguments) \ + ASSERT(guidMutex().locked()); \ + static type& name = *new type arguments + static const char versionKey[] = "WebKitDatabaseVersionKey"; static const char infoTableName[] = "__WebKitDatabaseInfoTable__"; @@ -149,9 +156,7 @@ typedef HashMap<DatabaseGuid, String> GuidVersionMap; static GuidVersionMap& guidToVersionMap() { - // Ensure the the mutex is locked. - ASSERT(guidMutex().locked()); - DEFINE_STATIC_LOCAL_NOASSERT(GuidVersionMap, map, ()); + DEFINE_STATIC_LOCAL_WITH_LOCK(GuidVersionMap, map, ()); return map; } @@ -174,9 +179,7 @@ static HashCountedSet<DatabaseGuid>& guidCount() { - // Ensure the the mutex is locked. - ASSERT(guidMutex().locked()); - DEFINE_STATIC_LOCAL_NOASSERT(HashCountedSet<DatabaseGuid>, guidCount, ()); + DEFINE_STATIC_LOCAL_WITH_LOCK(HashCountedSet<DatabaseGuid>, guidCount, ()); return guidCount; } @@ -188,7 +191,7 @@ String stringID = origin + "/" + name; typedef HashMap<String, int> IDGuidMap; - DEFINE_STATIC_LOCAL_NOASSERT(IDGuidMap, stringIdentifierToGUIDMap, ()); + DEFINE_STATIC_LOCAL_WITH_LOCK(IDGuidMap, stringIdentifierToGUIDMap, ()); DatabaseGuid guid = stringIdentifierToGUIDMap.get(stringID); if (!guid) { static int currentNewGUID = 1;
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in index 63bd6c8..b7578bad 100644 --- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in +++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
@@ -53,6 +53,7 @@ CSSStickyPosition CSSTouchActionPanDirections status=experimental CSSTypedOM status=experimental +CSSVariables status=experimental CSSViewport status=experimental CSSScrollSnapPoints status=test // getPropertyCSSValue, CSSValue, etc. will be removed once layout tests no longer depend on them. crbug.com/331608 @@ -143,7 +144,7 @@ RequestIdleCallback status=stable RequestAutocomplete status=test RestrictIFramePermissions -RTCCertificate status=test +RTCCertificate status=experimental SandboxBlocksModals status=stable ScreenOrientation status=stable ScriptedSpeech status=stable
diff --git a/third_party/WebKit/Source/platform/blink_platform.gypi b/third_party/WebKit/Source/platform/blink_platform.gypi index 6b9c357a..6b708b1 100644 --- a/third_party/WebKit/Source/platform/blink_platform.gypi +++ b/third_party/WebKit/Source/platform/blink_platform.gypi
@@ -677,6 +677,7 @@ 'graphics/paint/DrawingDisplayItem.h', 'graphics/paint/DrawingRecorder.cpp', 'graphics/paint/DrawingRecorder.h', + 'graphics/paint/EffectPaintPropertyNode.h', 'graphics/paint/FilterDisplayItem.cpp', 'graphics/paint/FilterDisplayItem.h', 'graphics/paint/FixedPositionContainerDisplayItem.cpp',
diff --git a/third_party/WebKit/Source/platform/blink_platform_tests.gyp b/third_party/WebKit/Source/platform/blink_platform_tests.gyp index dc7e3339..ee8e54d7 100644 --- a/third_party/WebKit/Source/platform/blink_platform_tests.gyp +++ b/third_party/WebKit/Source/platform/blink_platform_tests.gyp
@@ -146,10 +146,14 @@ ], 'variables': { 'dest_path': '<(asset_location)', - 'src_files': [ + 'renaming_sources': [ '<(PRODUCT_DIR)/natives_blob.bin', '<(PRODUCT_DIR)/snapshot_blob.bin', ], + 'renaming_destinations': [ + 'natives_blob_<(arch_suffix).bin', + 'snapshot_blob_<(arch_suffix).bin', + ], 'clear': 1, }, 'includes': ['../../../../build/android/copy_ex.gypi'], @@ -161,13 +165,16 @@ ['v8_use_external_startup_data==1', { 'asset_location': '<(PRODUCT_DIR)/blink_heap_unittests_apk/assets', 'additional_input_paths': [ - '<(PRODUCT_DIR)/blink_heap_unittests_apk/assets/natives_blob.bin', - '<(PRODUCT_DIR)/blink_heap_unittests_apk/assets/snapshot_blob.bin', + '<(PRODUCT_DIR)/blink_heap_unittests_apk/assets/natives_blob_<(arch_suffix).bin', + '<(PRODUCT_DIR)/blink_heap_unittests_apk/assets/snapshot_blob_<(arch_suffix).bin', ], }], ], }, - 'includes': [ '../../../../build/apk_test.gypi' ], + 'includes': [ + '../../../../build/apk_test.gypi', + '../../../../build/android/v8_external_startup_data_arch_suffix.gypi', + ], }, { 'target_name': 'blink_platform_unittests_apk',
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp index c3f6af8..93f225da 100644 --- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp +++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -527,8 +527,8 @@ if (!contextLost) { // Invalidate texture state in case the compositor altered it since the copy-on-write. if (releasedMailboxInfo->m_image) { - if (mailbox.syncPoint) { - context()->waitSyncPoint(mailbox.syncPoint); + if (mailbox.validSyncToken) { + context()->waitSyncToken(mailbox.syncToken); } GrTexture* texture = releasedMailboxInfo->m_image->getTexture(); if (texture) {
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp index 51465ee0..06088dc 100644 --- a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp +++ b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
@@ -214,9 +214,10 @@ sharedContext->produceTextureDirectCHROMIUM(textureId, GL_TEXTURE_2D, mailbox->name); sharedContext->flush(); - mailbox->syncPoint = sharedContext->insertSyncPoint(); + mailbox->validSyncToken = sharedContext->insertSyncPoint(mailbox->syncToken); + if (mailbox->validSyncToken) + context->waitSyncToken(mailbox->syncToken); - context->waitSyncPoint(mailbox->syncPoint); Platform3DObject sourceTexture = context->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox->name); // The canvas is stored in a premultiplied format, so unpremultiply if necessary. @@ -226,7 +227,10 @@ context->deleteTexture(sourceTexture); context->flush(); - sharedContext->waitSyncPoint(context->insertSyncPoint()); + + WGC3Dbyte syncToken[24]; + if (context->insertSyncPoint(syncToken)) + sharedContext->waitSyncToken(syncToken); // Undo grContext texture binding changes introduced in this function provider->grContext()->resetContext(kTextureBinding_GrGLBackendState);
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp index ccac5a91..d1efb9d 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -313,7 +313,7 @@ m_context->produceTextureDirectCHROMIUM(frontColorBufferMailbox->textureInfo.textureId, GL_TEXTURE_2D, frontColorBufferMailbox->mailbox.name); m_context->flush(); - frontColorBufferMailbox->mailbox.syncPoint = m_context->insertSyncPoint(); + frontColorBufferMailbox->mailbox.validSyncToken = m_context->insertSyncPoint(frontColorBufferMailbox->mailbox.syncToken); frontColorBufferMailbox->mailbox.allowOverlay = frontColorBufferMailbox->textureInfo.imageId != 0; setBufferClearNeeded(true); @@ -335,7 +335,9 @@ for (size_t i = 0; i < m_textureMailboxes.size(); i++) { RefPtr<MailboxInfo> mailboxInfo = m_textureMailboxes[i]; if (nameEquals(mailboxInfo->mailbox, mailbox)) { - mailboxInfo->mailbox.syncPoint = mailbox.syncPoint; + memcpy(mailboxInfo->mailbox.syncToken, mailbox.syncToken, + sizeof(mailboxInfo->mailbox.syncToken)); + mailboxInfo->mailbox.validSyncToken = mailbox.validSyncToken; ASSERT(mailboxInfo->m_parentDrawingBuffer.get() == this); mailboxInfo->m_parentDrawingBuffer.clear(); m_recycledMailboxQueue.prepend(mailboxInfo->mailbox); @@ -375,9 +377,9 @@ } ASSERT(mailboxInfo); - if (mailboxInfo->mailbox.syncPoint) { - m_context->waitSyncPoint(mailboxInfo->mailbox.syncPoint); - mailboxInfo->mailbox.syncPoint = 0; + if (mailboxInfo->mailbox.validSyncToken) { + m_context->waitSyncToken(mailboxInfo->mailbox.syncToken); + mailboxInfo->mailbox.validSyncToken = false; } if (mailboxInfo->size != m_size) { @@ -403,8 +405,8 @@ { for (size_t i = 0; i < m_textureMailboxes.size(); i++) { if (nameEquals(m_textureMailboxes[i]->mailbox, mailbox)) { - if (mailbox.syncPoint) - m_context->waitSyncPoint(mailbox.syncPoint); + if (mailbox.validSyncToken) + m_context->waitSyncToken(mailbox.syncToken); deleteChromiumImageForTexture(&m_textureMailboxes[i]->textureInfo); @@ -512,10 +514,10 @@ m_context->genMailboxCHROMIUM(mailbox.name); m_context->produceTextureDirectCHROMIUM(textureId, GL_TEXTURE_2D, mailbox.name); m_context->flush(); - mailbox.syncPoint = m_context->insertSyncPoint(); + mailbox.validSyncToken = m_context->insertSyncPoint(mailbox.syncToken); } - context->waitSyncPoint(mailbox.syncPoint); + context->waitSyncToken(mailbox.syncToken); Platform3DObject sourceTexture = context->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); GLboolean unpackPremultiplyAlphaNeeded = GL_FALSE; @@ -530,7 +532,9 @@ context->deleteTexture(sourceTexture); context->flush(); - m_context->waitSyncPoint(context->insertSyncPoint()); + GLbyte syncToken[24]; + if (context->insertSyncPoint(syncToken)) + m_context->waitSyncToken(syncToken); return true; }
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp index 574379e0..214cb9e 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
@@ -53,8 +53,10 @@ : MockWebGraphicsContext3D() , m_boundTexture(0) , m_currentMailboxByte(0) - , m_mostRecentlyWaitedSyncPoint(0) - , m_currentImageId(1) { } + , m_mostRecentlyWaitedSyncToken(0) + , m_currentImageId(1) + { + } void bindTexture(WGC3Denum target, WebGLId texture) override { @@ -89,15 +91,17 @@ return m_mostRecentlyProducedSize; } - unsigned insertSyncPoint() override + bool insertSyncPoint(WGC3Dbyte* syncToken) override { - static unsigned syncPointGenerator = 0; - return ++syncPointGenerator; + static WGC3Duint syncPointGenerator = 0; + WGC3Duint newSyncPoint = ++syncPointGenerator; + memcpy(syncToken, &newSyncPoint, sizeof(newSyncPoint)); + return true; } - void waitSyncPoint(unsigned syncPoint) override + void waitSyncToken(const WGC3Dbyte* syncToken) override { - m_mostRecentlyWaitedSyncPoint = syncPoint; + memcpy(&m_mostRecentlyWaitedSyncToken, syncToken, sizeof(m_mostRecentlyWaitedSyncToken)); } WGC3Duint createGpuMemoryBufferImageCHROMIUM(WGC3Dsizei width, WGC3Dsizei height, WGC3Denum internalformat, WGC3Denum usage) override @@ -136,9 +140,9 @@ } } - unsigned mostRecentlyWaitedSyncPoint() + WGC3Duint mostRecentlyWaitedSyncToken() { - return m_mostRecentlyWaitedSyncPoint; + return m_mostRecentlyWaitedSyncToken; } WGC3Duint nextImageIdToBeCreated() @@ -151,7 +155,7 @@ HashMap<WebGLId, IntSize> m_textureSizes; WGC3Dbyte m_currentMailboxByte; IntSize m_mostRecentlyProducedSize; - unsigned m_mostRecentlyWaitedSyncPoint; + WGC3Duint m_mostRecentlyWaitedSyncToken; WGC3Duint m_currentImageId; HashMap<WGC3Duint, IntSize> m_imageSizes; HashMap<WGC3Duint, WebGLId> m_imageToTextureMap; @@ -401,34 +405,37 @@ m_drawingBuffer->beginDestruction(); } -TEST_F(DrawingBufferTest, verifyInsertAndWaitSyncPointCorrectly) +TEST_F(DrawingBufferTest, verifyInsertAndWaitSyncTokenCorrectly) { WebExternalTextureMailbox mailbox; // Produce mailboxes. m_drawingBuffer->markContentsChanged(); - EXPECT_EQ(0u, webContext()->mostRecentlyWaitedSyncPoint()); + EXPECT_EQ(0u, webContext()->mostRecentlyWaitedSyncToken()); EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); // prepareMailbox() does not wait for any sync point. - EXPECT_EQ(0u, webContext()->mostRecentlyWaitedSyncPoint()); + EXPECT_EQ(0u, webContext()->mostRecentlyWaitedSyncToken()); - unsigned waitSyncPoint = webContext()->insertSyncPoint(); - mailbox.syncPoint = waitSyncPoint; + WGC3Duint waitSyncToken = 0; + webContext()->insertSyncPoint(reinterpret_cast<WGC3Dbyte*>(&waitSyncToken)); + memcpy(mailbox.syncToken, &waitSyncToken, sizeof(waitSyncToken)); + mailbox.validSyncToken = true; m_drawingBuffer->mailboxReleased(mailbox, false); // m_drawingBuffer will wait for the sync point when recycling. - EXPECT_EQ(0u, webContext()->mostRecentlyWaitedSyncPoint()); + EXPECT_EQ(0u, webContext()->mostRecentlyWaitedSyncToken()); m_drawingBuffer->markContentsChanged(); EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); // m_drawingBuffer waits for the sync point when recycling in prepareMailbox(). - EXPECT_EQ(waitSyncPoint, webContext()->mostRecentlyWaitedSyncPoint()); + EXPECT_EQ(waitSyncToken, webContext()->mostRecentlyWaitedSyncToken()); m_drawingBuffer->beginDestruction(); - waitSyncPoint = webContext()->insertSyncPoint(); - mailbox.syncPoint = waitSyncPoint; + webContext()->insertSyncPoint(reinterpret_cast<WGC3Dbyte*>(&waitSyncToken)); + memcpy(mailbox.syncToken, &waitSyncToken, sizeof(waitSyncToken)); + mailbox.validSyncToken = true; m_drawingBuffer->mailboxReleased(mailbox, false); // m_drawingBuffer waits for the sync point because the destruction is in progress. - EXPECT_EQ(waitSyncPoint, webContext()->mostRecentlyWaitedSyncPoint()); + EXPECT_EQ(waitSyncToken, webContext()->mostRecentlyWaitedSyncToken()); } class DrawingBufferImageChromiumTest : public DrawingBufferTest { @@ -654,12 +661,14 @@ m_drawingBuffer->markContentsChanged(); EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); - unsigned waitSyncPoint = webContext()->insertSyncPoint(); - mailbox.syncPoint = waitSyncPoint; + mailbox.validSyncToken = webContext()->insertSyncPoint(mailbox.syncToken); m_drawingBuffer->setIsHidden(true); m_drawingBuffer->mailboxReleased(mailbox); // m_drawingBuffer deletes mailbox immediately when hidden. - EXPECT_EQ(waitSyncPoint, webContext()->mostRecentlyWaitedSyncPoint()); + + WGC3Duint waitSyncToken = 0; + memcpy(&waitSyncToken, mailbox.syncToken, sizeof(waitSyncToken)); + EXPECT_EQ(waitSyncToken, webContext()->mostRecentlyWaitedSyncToken()); m_drawingBuffer->beginDestruction(); }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h new file mode 100644 index 0000000..46cf9c51 --- /dev/null +++ b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h
@@ -0,0 +1,46 @@ +// Copyright 2015 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 EffectPaintPropertyNode_h +#define EffectPaintPropertyNode_h + +#include "platform/PlatformExport.h" +#include "wtf/PassRefPtr.h" +#include "wtf/RefCounted.h" +#include "wtf/RefPtr.h" + +#include <iosfwd> + +namespace blink { + +// A paint effect created by the opacity css property along with a reference to +// the parent effect node, or nullptr for the root. +// TODO(pdr): Support more effects than just opacity. +class PLATFORM_EXPORT EffectPaintPropertyNode : public RefCounted<EffectPaintPropertyNode> { +public: + static PassRefPtr<EffectPaintPropertyNode> create(float opacity, PassRefPtr<EffectPaintPropertyNode> parent = nullptr) + { + return adoptRef(new EffectPaintPropertyNode(opacity, parent)); + } + + float opacity() const { return m_opacity; } + + // Parent effect or nullptr if this is the root effect. + const EffectPaintPropertyNode* parent() const { return m_parent.get(); } + +private: + EffectPaintPropertyNode(float opacity, PassRefPtr<EffectPaintPropertyNode> parent) + : m_opacity(opacity), m_parent(parent) { } + + const float m_opacity; + RefPtr<EffectPaintPropertyNode> m_parent; +}; + +// Redeclared here to avoid ODR issues. +// See platform/testing/PaintPrinters.h. +void PrintTo(const EffectPaintPropertyNode&, std::ostream*); + +} // namespace blink + +#endif // EffectPaintPropertyNode_h
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintArtifactToSkCanvas.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintArtifactToSkCanvas.cpp index 1ef8764..438d4b6 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/PaintArtifactToSkCanvas.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/PaintArtifactToSkCanvas.cpp
@@ -6,6 +6,7 @@ #include "platform/graphics/paint/PaintArtifactToSkCanvas.h" #include "platform/graphics/paint/DrawingDisplayItem.h" +#include "platform/graphics/paint/EffectPaintPropertyNode.h" #include "platform/graphics/paint/PaintArtifact.h" #include "platform/graphics/paint/PaintChunk.h" #include "platform/graphics/paint/TransformPaintPropertyNode.h" @@ -32,10 +33,72 @@ } // namespace +// Compute the list of nodes from 'a' to commonAncestor(a, b) and 'b' to +// commonAncestor(a, b), exclusive. +// +// For the following tree: +// _root_ +// | | +// a d +// | | +// b e +// | +// c +// The common ancestor of 'c' and 'e' is 'root'. The paths would be: +// path from c to commonAncestor(c,e) = [b,a] +// path from e to commonAncestor(c,e) = [d] +static void computePathsToCommonAncestor(const EffectPaintPropertyNode* a, const EffectPaintPropertyNode* b, Vector<const EffectPaintPropertyNode*>& aToCommonAncestor, Vector<const EffectPaintPropertyNode*>& bToCommonAncestor) +{ + // Calculate the path from a -> root. + const EffectPaintPropertyNode* current = a; + while (current) { + aToCommonAncestor.append(current); + current = current->parent(); + } + + // Calculate the path from b -> root. + current = b; + while (current) { + bToCommonAncestor.append(current); + current = current->parent(); + } + + // Pop nodes from root -> a and root -> b while the last node is equal so we + // are left with just the common ancestor path, not including the common + // ancestor itself. + while (aToCommonAncestor.size() && bToCommonAncestor.size() && aToCommonAncestor.last() == bToCommonAncestor.last()) { + aToCommonAncestor.removeLast(); + bToCommonAncestor.removeLast(); + } +} + +static void applyEffectNodesToCanvas(const EffectPaintPropertyNode* previousEffect, const EffectPaintPropertyNode* currentEffect, SkCanvas* canvas) +{ + if (previousEffect == currentEffect) + return; + + Vector<const EffectPaintPropertyNode*> effectsToUnapply; + Vector<const EffectPaintPropertyNode*> effectsToApply; + computePathsToCommonAncestor(previousEffect, currentEffect, effectsToUnapply, effectsToApply); + + size_t popEffectCount = effectsToUnapply.size(); + for (size_t popEffect = 0; popEffect < popEffectCount; popEffect++) + canvas->restore(); + + for (Vector<const EffectPaintPropertyNode*>::reverse_iterator it = effectsToApply.rbegin(); it != effectsToApply.rend(); ++it) { + const EffectPaintPropertyNode* node = *it; + ASSERT(node); + SkPaint layerPaint; + layerPaint.setAlpha(static_cast<unsigned char>(node->opacity() * 255)); + canvas->saveLayer(nullptr, &layerPaint); + } +} + void paintArtifactToSkCanvas(const PaintArtifact& artifact, SkCanvas* canvas) { SkAutoCanvasRestore restore(canvas, true); const DisplayItemList& displayItems = artifact.displayItemList(); + const EffectPaintPropertyNode* previousEffect = nullptr; for (const PaintChunk& chunk : artifact.paintChunks()) { // Compute the total transformation matrix for this chunk. TransformationMatrix matrix; @@ -49,6 +112,14 @@ // Set the canvas state to match the paint properties. canvas->setMatrix(TransformationMatrix::toSkMatrix44(matrix)); + // Push and pop layers on the SkCanvas as necessary to implement the + // current effect. + // TODO(pdr): This will need to be revisited for non-opacity effects + // such as filters which require interleaving with transforms. + const EffectPaintPropertyNode* chunkEffect = chunk.properties.effect.get(); + applyEffectNodesToCanvas(previousEffect, chunkEffect, canvas); + previousEffect = chunkEffect; + // Draw the display items in the paint chunk. DisplayItemList::const_iterator begin = displayItems.begin() + chunk.beginIndex; DisplayItemList::const_iterator end = displayItems.begin() + chunk.endIndex;
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintArtifactToSkCanvasTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintArtifactToSkCanvasTest.cpp index f356365..792538d2 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/PaintArtifactToSkCanvasTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/PaintArtifactToSkCanvasTest.cpp
@@ -44,12 +44,19 @@ MockCanvas(int width, int height) : SkCanvas(width, height) {} MOCK_METHOD3(onDrawRect, void(const SkRect&, const SkPaint&, MockCanvas*)); + MOCK_METHOD2(willSaveLayer, void(unsigned alpha, MockCanvas*)); private: void onDrawRect(const SkRect& rect, const SkPaint& paint) override { onDrawRect(rect, paint, this); } + + SaveLayerStrategy willSaveLayer(const SkRect* rect, const SkPaint* paint, SaveFlags saveFlags) override + { + willSaveLayer(paint->getAlpha(), this); + return SaveLayerStrategy::kFullLayer_SaveLayerStrategy; + } }; class DummyRectClient { @@ -148,5 +155,91 @@ paintArtifactToSkCanvas(artifact, &canvas); } +TEST(PaintArtifactToSkCanvasTest, OpacityEffectsCombining) +{ + DummyRectClient client1(SkRect::MakeXYWH(0, 0, 300, 200), SK_ColorRED); + DummyRectClient client2(SkRect::MakeXYWH(0, 0, 300, 200), SK_ColorBLUE); + + unsigned expectedFirstOpacity = 127; // floor(0.5 * 255) + unsigned expectedSecondOpacity = 63; // floor(0.25 * 255) + MockCanvas canvas(kCanvasWidth, kCanvasHeight); + { + testing::InSequence sequence; + EXPECT_CALL(canvas, willSaveLayer(expectedFirstOpacity, _)); + EXPECT_CALL(canvas, onDrawRect(client1.rect(), Property(&SkPaint::getColor, client1.color()), _)); + EXPECT_CALL(canvas, willSaveLayer(expectedSecondOpacity, _)); + EXPECT_CALL(canvas, onDrawRect(client2.rect(), Property(&SkPaint::getColor, client2.color()), _)); + } + + // Build an opacity effect tree. + RefPtr<EffectPaintPropertyNode> opacityEffect1 = EffectPaintPropertyNode::create(0.5); + RefPtr<EffectPaintPropertyNode> opacityEffect2 = EffectPaintPropertyNode::create(0.25, opacityEffect1); + + // Build a two-chunk artifact directly. + PaintArtifact artifact; + artifact.displayItemList().allocateAndConstruct<DrawingDisplayItem>( + client1, DisplayItem::DrawingFirst, client1.makePicture()); + PaintChunk chunk1(0, 1, PaintChunkProperties()); + chunk1.properties.effect = opacityEffect1.get(); + artifact.paintChunks().append(chunk1); + + artifact.displayItemList().allocateAndConstruct<DrawingDisplayItem>( + client2, DisplayItem::DrawingFirst, client2.makePicture()); + PaintChunk chunk2(1, 2, PaintChunkProperties()); + chunk2.properties.effect = opacityEffect2.get(); + artifact.paintChunks().append(chunk2); + + paintArtifactToSkCanvas(artifact, &canvas); +} + +TEST(PaintArtifactToSkCanvasTest, ChangingOpacityEffects) +{ + DummyRectClient client1(SkRect::MakeXYWH(0, 0, 300, 200), SK_ColorRED); + DummyRectClient client2(SkRect::MakeXYWH(0, 0, 300, 200), SK_ColorBLUE); + + unsigned expectedAOpacity = 25; // floor(0.1 * 255) + unsigned expectedBOpacity = 51; // floor(0.2 * 255) + unsigned expectedCOpacity = 76; // floor(0.3 * 255) + unsigned expectedDOpacity = 102; // floor(0.4 * 255) + MockCanvas canvas(kCanvasWidth, kCanvasHeight); + { + testing::InSequence sequence; + EXPECT_CALL(canvas, willSaveLayer(expectedAOpacity, _)); + EXPECT_CALL(canvas, willSaveLayer(expectedBOpacity, _)); + EXPECT_CALL(canvas, onDrawRect(client1.rect(), Property(&SkPaint::getColor, client1.color()), _)); + EXPECT_CALL(canvas, willSaveLayer(expectedCOpacity, _)); + EXPECT_CALL(canvas, willSaveLayer(expectedDOpacity, _)); + EXPECT_CALL(canvas, onDrawRect(client2.rect(), Property(&SkPaint::getColor, client2.color()), _)); + } + + // Build an opacity effect tree with the following structure: + // _root_ + // | | + // 0.1 a c 0.3 + // | | + // 0.2 b d 0.4 + RefPtr<EffectPaintPropertyNode> opacityEffectA = EffectPaintPropertyNode::create(0.1); + RefPtr<EffectPaintPropertyNode> opacityEffectB = EffectPaintPropertyNode::create(0.2, opacityEffectA); + RefPtr<EffectPaintPropertyNode> opacityEffectC = EffectPaintPropertyNode::create(0.3); + RefPtr<EffectPaintPropertyNode> opacityEffectD = EffectPaintPropertyNode::create(0.4, opacityEffectC); + + // Build a two-chunk artifact directly. + // chunk1 references opacity node b, chunk2 references opacity node d. + PaintArtifact artifact; + artifact.displayItemList().allocateAndConstruct<DrawingDisplayItem>( + client1, DisplayItem::DrawingFirst, client1.makePicture()); + PaintChunk chunk1(0, 1, PaintChunkProperties()); + chunk1.properties.effect = opacityEffectB.get(); + artifact.paintChunks().append(chunk1); + + artifact.displayItemList().allocateAndConstruct<DrawingDisplayItem>( + client2, DisplayItem::DrawingFirst, client2.makePicture()); + PaintChunk chunk2(1, 2, PaintChunkProperties()); + chunk2.properties.effect = opacityEffectD.get(); + artifact.paintChunks().append(chunk2); + + paintArtifactToSkCanvas(artifact, &canvas); +} + } // namespace } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintChunkProperties.h b/third_party/WebKit/Source/platform/graphics/paint/PaintChunkProperties.h index 0e8bb4b..a30d33a2 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/PaintChunkProperties.h +++ b/third_party/WebKit/Source/platform/graphics/paint/PaintChunkProperties.h
@@ -5,6 +5,7 @@ #ifndef PaintChunkProperties_h #define PaintChunkProperties_h +#include "platform/graphics/paint/EffectPaintPropertyNode.h" #include "platform/graphics/paint/TransformPaintPropertyNode.h" #include <iosfwd> @@ -21,15 +22,17 @@ // This differs from |ObjectPaintProperties| because it only stores one property // for each type (e.g., either transform or perspective, but not both). struct PaintChunkProperties { - // TODO(pdr): Add clip, scroll, and effect properties. + // TODO(pdr): Add clip and scroll properties. RefPtr<TransformPaintPropertyNode> transform; + RefPtr<EffectPaintPropertyNode> effect; }; // Equality is based only on the pointers and is not 'deep' which would require // crawling the entire property tree to compute. inline bool operator==(const PaintChunkProperties& a, const PaintChunkProperties& b) { - return a.transform.get() == b.transform.get(); + return a.transform.get() == b.transform.get() + && a.effect.get() == b.effect.get(); } inline bool operator!=(const PaintChunkProperties& a, const PaintChunkProperties& b)
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintChunkerTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintChunkerTest.cpp index d1084c5..d1b0d67 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/PaintChunkerTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/PaintChunkerTest.cpp
@@ -104,7 +104,48 @@ PaintChunk(3, 4, anotherTransform))); } -TEST_F(PaintChunkerTest, BuildLinearChunksFromNestedTransforms) +TEST_F(PaintChunkerTest, BuildMultipleChunksWithDifferentPropertyChanges) +{ + PaintChunker chunker; + chunker.updateCurrentPaintChunkProperties(rootPaintChunkProperties()); + chunker.incrementDisplayItemIndex(); + + PaintChunkProperties simpleTransform; + simpleTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(0, 0, 0, 0, 0, 0), FloatPoint3D(9, 8, 7)); + chunker.updateCurrentPaintChunkProperties(simpleTransform); + chunker.incrementDisplayItemIndex(); + chunker.incrementDisplayItemIndex(); + + PaintChunkProperties simpleTransformAndEffect; + simpleTransformAndEffect.transform = simpleTransform.transform; + simpleTransformAndEffect.effect = EffectPaintPropertyNode::create(0.5f); + chunker.updateCurrentPaintChunkProperties(simpleTransformAndEffect); + chunker.incrementDisplayItemIndex(); + chunker.incrementDisplayItemIndex(); + + PaintChunkProperties simpleTransformAndEffectWithUpdatedTransform; + simpleTransformAndEffectWithUpdatedTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(1, 1, 0, 0, 0, 0), FloatPoint3D(9, 8, 7)); + simpleTransformAndEffectWithUpdatedTransform.effect = EffectPaintPropertyNode::create(simpleTransformAndEffect.effect->opacity()); + chunker.updateCurrentPaintChunkProperties(simpleTransformAndEffectWithUpdatedTransform); + chunker.incrementDisplayItemIndex(); + chunker.incrementDisplayItemIndex(); + + // Test that going back to a previous chunk property still creates a new chunk. + chunker.updateCurrentPaintChunkProperties(simpleTransformAndEffect); + chunker.incrementDisplayItemIndex(); + chunker.incrementDisplayItemIndex(); + + Vector<PaintChunk> chunks = chunker.releasePaintChunks(); + + EXPECT_THAT(chunks, ElementsAre( + PaintChunk(0, 1, rootPaintChunkProperties()), + PaintChunk(1, 3, simpleTransform), + PaintChunk(3, 5, simpleTransformAndEffect), + PaintChunk(5, 7, simpleTransformAndEffectWithUpdatedTransform), + PaintChunk(7, 9, simpleTransformAndEffect))); +} + +TEST_F(PaintChunkerTest, BuildChunksFromNestedTransforms) { // Test that "nested" transforms linearize using the following // sequence of transforms and display items: @@ -153,7 +194,5 @@ PaintChunk(1, 2, secondTransform))); } -// TODO(pdr): Add more tests once we have more paint properties. - } // namespace } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h index 76dbc34..0bef99e 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h +++ b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h
@@ -21,8 +21,10 @@ // for the root. class PLATFORM_EXPORT TransformPaintPropertyNode : public RefCounted<TransformPaintPropertyNode> { public: - static PassRefPtr<TransformPaintPropertyNode> create(const TransformationMatrix& matrix, const FloatPoint3D& origin, PassRefPtr<TransformPaintPropertyNode> parent = nullptr) { return adoptRef(new TransformPaintPropertyNode(matrix, origin, parent)); } - + static PassRefPtr<TransformPaintPropertyNode> create(const TransformationMatrix& matrix, const FloatPoint3D& origin, PassRefPtr<TransformPaintPropertyNode> parent = nullptr) + { + return adoptRef(new TransformPaintPropertyNode(matrix, origin, parent)); + } const TransformationMatrix& matrix() const { return m_matrix; } const FloatPoint3D& origin() const { return m_origin; }
diff --git a/third_party/WebKit/Source/platform/heap/StackFrameDepth.cpp b/third_party/WebKit/Source/platform/heap/StackFrameDepth.cpp index 345e71b..e53e6a3 100644 --- a/third_party/WebKit/Source/platform/heap/StackFrameDepth.cpp +++ b/third_party/WebKit/Source/platform/heap/StackFrameDepth.cpp
@@ -42,8 +42,11 @@ size_t stackSize = getUnderestimatedStackSize(); if (stackSize) { - size_t stackBase = reinterpret_cast<size_t>(getStackStart()); - s_stackFrameLimit = stackBase - stackSize + kStackRoomSize; + Address stackBase = reinterpret_cast<Address>(getStackStart()); + RELEASE_ASSERT(stackSize > static_cast<const size_t>(kStackRoomSize)); + size_t stackRoom = stackSize - kStackRoomSize; + RELEASE_ASSERT(stackBase > reinterpret_cast<Address>(stackRoom)); + s_stackFrameLimit = reinterpret_cast<uintptr_t>(stackBase - stackRoom); return; }
diff --git a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp index 06b149c..ee12184 100644 --- a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
@@ -39,7 +39,6 @@ #include "platform/image-decoders/jpeg/JPEGImageDecoder.h" #include "platform/PlatformInstrumentation.h" -#include "wtf/Partitions.h" #include "wtf/PassOwnPtr.h" #include "wtf/dtoa/utils.h" @@ -90,13 +89,17 @@ jmp_buf setjmp_buffer; // For handling catastropic errors }; +struct decoder_source_mgr { + struct jpeg_source_mgr pub; // "public" fields for IJG library + JPEGImageReader* decoder; +}; + enum jstate { JPEG_HEADER, // Reading JFIF headers JPEG_START_DECOMPRESS, JPEG_DECOMPRESS_PROGRESSIVE, // Output progressive pixels JPEG_DECOMPRESS_SEQUENTIAL, // Output sequential pixels - JPEG_DONE, - JPEG_ERROR + JPEG_DONE }; enum yuv_subsampling { @@ -116,14 +119,6 @@ void error_exit(j_common_ptr cinfo); void emit_message(j_common_ptr cinfo, int msg_level); -// Implementation of a JPEG src object that understands our state machine -struct decoder_source_mgr { - // public fields; must be first in this struct! - struct jpeg_source_mgr pub; - - JPEGImageReader* decoder; -}; - static unsigned readUint16(JOCTET* data, bool isBigEndian) { if (isBigEndian) @@ -320,22 +315,17 @@ // Allocate and initialize JPEG decompression object. jpeg_create_decompress(&m_info); - ASSERT(!m_info.src); - decoder_source_mgr* src = static_cast<decoder_source_mgr*>(WTF::Partitions::fastZeroedMalloc(sizeof(decoder_source_mgr))); - if (!src) { - m_state = JPEG_ERROR; - return; - } - - m_info.src = reinterpret_cast_ptr<jpeg_source_mgr*>(src); + // Initialize source manager. + memset(&m_src, 0, sizeof(decoder_source_mgr)); + m_info.src = reinterpret_cast_ptr<jpeg_source_mgr*>(&m_src); // Set up callback functions. - src->pub.init_source = init_source; - src->pub.fill_input_buffer = fill_input_buffer; - src->pub.skip_input_data = skip_input_data; - src->pub.resync_to_restart = jpeg_resync_to_restart; - src->pub.term_source = term_source; - src->decoder = this; + m_src.pub.init_source = init_source; + m_src.pub.fill_input_buffer = fill_input_buffer; + m_src.pub.skip_input_data = skip_input_data; + m_src.pub.resync_to_restart = jpeg_resync_to_restart; + m_src.pub.term_source = term_source; + m_src.decoder = this; #if USE(ICCJPEG) // Retain ICC color profile markers for color management. @@ -352,11 +342,6 @@ void close() { - decoder_source_mgr* src = reinterpret_cast_ptr<decoder_source_mgr*>(m_info.src); - if (src) - WTF::Partitions::fastFree(src); - m_info.src = 0; - #if USE(QCMSLIB) clearColorTransform(); #endif @@ -643,10 +628,6 @@ case JPEG_DONE: // Finish decompression. return jpeg_finish_decompress(&m_info); - - case JPEG_ERROR: - // We can get here if the constructor failed. - return m_decoder->setFailed(); } return true; @@ -720,6 +701,7 @@ jpeg_decompress_struct m_info; decoder_error_mgr m_err; + decoder_source_mgr m_src; jstate m_state; JSAMPARRAY m_samples;
diff --git a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.h b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.h index dd2c690c..f7cfc73e 100644 --- a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.h +++ b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.h
@@ -1,6 +1,5 @@ /* * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * Copyright (C) 2008-2009 Torch Mobile, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,14 +28,10 @@ #include "platform/image-decoders/ImageDecoder.h" -#include "wtf/Noncopyable.h" -#include "wtf/OwnPtr.h" - namespace blink { class JPEGImageReader; -// This class decodes the JPEG image format. class PLATFORM_EXPORT JPEGImageDecoder : public ImageDecoder { WTF_MAKE_NONCOPYABLE(JPEGImageDecoder); public:
diff --git a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp index 9f5ac596..f3c19b6 100644 --- a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp
@@ -39,8 +39,6 @@ #include "config.h" #include "platform/image-decoders/png/PNGImageDecoder.h" -#include "wtf/PassOwnPtr.h" - #include "png.h" #if !defined(PNG_LIBPNG_VER_MAJOR) || !defined(PNG_LIBPNG_VER_MINOR) #error version error: compile against a versioned libpng.
diff --git a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.h b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.h index 7f54c2e..672770b 100644 --- a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.h +++ b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.h
@@ -27,8 +27,6 @@ #define PNGImageDecoder_h #include "platform/image-decoders/ImageDecoder.h" -#include "wtf/Noncopyable.h" -#include "wtf/OwnPtr.h" namespace blink {
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 da99a625..41c58d6 100644 --- a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.h +++ b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.h
@@ -30,7 +30,6 @@ #define WEBPImageDecoder_h #include "platform/image-decoders/ImageDecoder.h" - #include "webp/decode.h" #include "webp/demux.h"
diff --git a/third_party/WebKit/Source/platform/platform.gni b/third_party/WebKit/Source/platform/platform.gni index 6d7d403..8941532d 100644 --- a/third_party/WebKit/Source/platform/platform.gni +++ b/third_party/WebKit/Source/platform/platform.gni
@@ -5,14 +5,16 @@ # This file is the GN version of blink_platform.gypi. We rebase most paths to # be absolute so these lists can be used by BUILD files in different directories # without worrying about the base directory. -_gypi = exec_script( - "//build/gypi_to_gn.py", - [ rebase_path("blink_platform.gypi") ], - "scope", - [ "blink_platform.gypi" ]) +_gypi = exec_script("//build/gypi_to_gn.py", + [ rebase_path("blink_platform.gypi") ], + "scope", + [ "blink_platform.gypi" ]) platform_files = _gypi.platform_files platform_test_files = get_path_info(_gypi.platform_test_files, "abspath") -platform_unittest_support_files = get_path_info(_gypi.platform_unittest_support_files, "abspath") -platform_web_unittest_files = get_path_info(_gypi.platform_web_unittest_files, "abspath") -platform_test_support_files = get_path_info(_gypi.platform_test_support_files, "abspath") +platform_unittest_support_files = + get_path_info(_gypi.platform_unittest_support_files, "abspath") +platform_web_unittest_files = + get_path_info(_gypi.platform_web_unittest_files, "abspath") +platform_test_support_files = + get_path_info(_gypi.platform_test_support_files, "abspath")
diff --git a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp index 6a12886..243b080 100644 --- a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp +++ b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp
@@ -216,13 +216,14 @@ if (m_compositorPlayer && timeline) { // Detach from old layer (if any). if (m_compositorAnimationAttachedToLayerId) { - ASSERT(m_compositorPlayer->isLayerAttached()); - m_compositorPlayer->detachLayer(); + if (m_compositorPlayer->isLayerAttached()) + m_compositorPlayer->detachLayer(); timeline->playerDestroyed(*this); } // Attach to new layer (if any). if (compositorAnimationAttachedToLayerId) { ASSERT(m_scrollableArea->layerForScrolling()); + ASSERT(!m_compositorPlayer->isLayerAttached()); timeline->playerAttached(*this); m_compositorPlayer->attachLayer(m_scrollableArea->layerForScrolling()->platformLayer()); }
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp index dc8b043..56965a8 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp
@@ -219,22 +219,21 @@ } -bool ScrollAnimator::PerAxisData::updateDataFromParameters(float step, float delta, float scrollableSize, double currentTime, Parameters* parameters) +bool ScrollAnimator::PerAxisData::updateDataFromParameters(float step, float delta, float minScrollPos, float maxScrollPos, double currentTime, Parameters* parameters) { float pixelDelta = step * delta; if (!m_startTime || !pixelDelta || (pixelDelta < 0) != (m_desiredPosition - *m_currentPosition < 0)) { m_desiredPosition = *m_currentPosition; m_startTime = 0; } - float newPosition = m_desiredPosition + pixelDelta; - if (newPosition < 0 || newPosition > scrollableSize) - newPosition = std::max(std::min(newPosition, scrollableSize), 0.0f); + float newPos = m_desiredPosition + pixelDelta; + float clampedPos = std::max(std::min(newPos, maxScrollPos), minScrollPos); - if (newPosition == m_desiredPosition) + if (clampedPos == m_desiredPosition) return false; - m_desiredPosition = newPosition; + m_desiredPosition = clampedPos; if (!m_startTime) { m_attackTime = parameters->m_attackTime; @@ -418,10 +417,11 @@ return ScrollAnimatorBase::userScroll(orientation, granularity, step, delta); // This is an animatable scroll. Set the animation in motion using the appropriate parameters. - float scrollableSize = static_cast<float>(m_scrollableArea->scrollSize(orientation)); + float minScrollPos = static_cast<float>(m_scrollableArea->minimumScrollPosition(orientation)); + float maxScrollPos = static_cast<float>(m_scrollableArea->maximumScrollPosition(orientation)); PerAxisData& data = (orientation == VerticalScrollbar) ? m_verticalData : m_horizontalData; - bool needToScroll = data.updateDataFromParameters(step, delta, scrollableSize, WTF::monotonicallyIncreasingTime(), ¶meters); + bool needToScroll = data.updateDataFromParameters(step, delta, minScrollPos, maxScrollPos, WTF::monotonicallyIncreasingTime(), ¶meters); float unusedDelta = needToScroll ? delta - (data.m_desiredPosition - *data.m_currentPosition) : delta; if (needToScroll && !animationTimerActive()) { m_startTime = data.m_startTime;
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h index ed898006..4db82e9 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h
@@ -96,7 +96,7 @@ struct PLATFORM_EXPORT PerAxisData { PerAxisData(float* currentPos, int visibleLength); void reset(); - bool updateDataFromParameters(float step, float delta, float scrollableSize, double currentTime, Parameters*); + bool updateDataFromParameters(float step, float delta, float minScrollPos, float maxScrollPos, double currentTime, Parameters*); bool animateScroll(double currentTime); void updateVisibleLength(int visibleLength);
diff --git a/third_party/WebKit/Source/platform/testing/PaintPrinters.cpp b/third_party/WebKit/Source/platform/testing/PaintPrinters.cpp index 7ef676ff..e9e81f01 100644 --- a/third_party/WebKit/Source/platform/testing/PaintPrinters.cpp +++ b/third_party/WebKit/Source/platform/testing/PaintPrinters.cpp
@@ -39,4 +39,9 @@ *os << ")"; } +void PrintTo(const EffectPaintPropertyNode& effect, std::ostream* os) +{ + *os << "EffectPaintPropertyNode(opacity=" << effect.opacity() << ")"; +} + } // namespace blink
diff --git a/third_party/WebKit/Source/platform/testing/PaintPrinters.h b/third_party/WebKit/Source/platform/testing/PaintPrinters.h index 34c88ef..35ce29e 100644 --- a/third_party/WebKit/Source/platform/testing/PaintPrinters.h +++ b/third_party/WebKit/Source/platform/testing/PaintPrinters.h
@@ -12,6 +12,7 @@ struct PaintChunk; struct PaintProperties; class TransformPaintPropertyNode; +class EffectPaintPropertyNode; // GTest print support for platform paint classes. // @@ -27,6 +28,7 @@ void PrintTo(const PaintChunk&, std::ostream*); void PrintTo(const PaintProperties&, std::ostream*); void PrintTo(const TransformPaintPropertyNode&, std::ostream*); +void PrintTo(const EffectPaintPropertyNode&, std::ostream*); } // namespace blink
diff --git a/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp b/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp index 9ed54cd..c670274a 100644 --- a/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp +++ b/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp
@@ -41,17 +41,16 @@ return m; } -static void assertLockHeld() -{ -#if ENABLE(ASSERT) - ASSERT(mutex().locked()); -#endif -} +// Defines static local variable after making sure that a lock is held. +// (We can't use DEFINE_STATIC_LOCAL for this because it asserts thread +// safety, which is externally guaranteed by the local mutex() lock) +#define DEFINE_STATIC_LOCAL_WITH_LOCK(type, name, arguments) \ + ASSERT(mutex().locked()); \ + static type& name = *new type arguments static URLSchemesSet& localURLSchemes() { - assertLockHeld(); - DEFINE_STATIC_LOCAL_NOASSERT(URLSchemesSet, localSchemes, ()); + DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, localSchemes, ()); if (localSchemes.isEmpty()) localSchemes.add("file"); @@ -61,15 +60,13 @@ static URLSchemesSet& displayIsolatedURLSchemes() { - assertLockHeld(); - DEFINE_STATIC_LOCAL_NOASSERT(URLSchemesSet, displayIsolatedSchemes, ()); + DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, displayIsolatedSchemes, ()); return displayIsolatedSchemes; } static URLSchemesSet& mixedContentRestrictingSchemes() { - assertLockHeld(); - DEFINE_STATIC_LOCAL_NOASSERT(URLSchemesSet, mixedContentRestrictingSchemes, ()); + DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, mixedContentRestrictingSchemes, ()); if (mixedContentRestrictingSchemes.isEmpty()) mixedContentRestrictingSchemes.add("https"); @@ -79,8 +76,7 @@ static URLSchemesSet& secureSchemes() { - assertLockHeld(); - DEFINE_STATIC_LOCAL_NOASSERT(URLSchemesSet, secureSchemes, ()); + DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, secureSchemes, ()); if (secureSchemes.isEmpty()) { secureSchemes.add("https"); @@ -94,8 +90,7 @@ static URLSchemesSet& schemesWithUniqueOrigins() { - assertLockHeld(); - DEFINE_STATIC_LOCAL_NOASSERT(URLSchemesSet, schemesWithUniqueOrigins, ()); + DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, schemesWithUniqueOrigins, ()); if (schemesWithUniqueOrigins.isEmpty()) { schemesWithUniqueOrigins.add("about"); @@ -110,8 +105,7 @@ static URLSchemesSet& emptyDocumentSchemes() { - assertLockHeld(); - DEFINE_STATIC_LOCAL_NOASSERT(URLSchemesSet, emptyDocumentSchemes, ()); + DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, emptyDocumentSchemes, ()); if (emptyDocumentSchemes.isEmpty()) emptyDocumentSchemes.add("about"); @@ -121,15 +115,13 @@ static HashSet<String>& schemesForbiddenFromDomainRelaxation() { - assertLockHeld(); - DEFINE_STATIC_LOCAL_NOASSERT(HashSet<String>, schemes, ()); + DEFINE_STATIC_LOCAL_WITH_LOCK(HashSet<String>, schemes, ()); return schemes; } static URLSchemesSet& notAllowingJavascriptURLsSchemes() { - assertLockHeld(); - DEFINE_STATIC_LOCAL_NOASSERT(URLSchemesSet, notAllowingJavascriptURLsSchemes, ()); + DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, notAllowingJavascriptURLsSchemes, ()); return notAllowingJavascriptURLsSchemes; } @@ -147,9 +139,7 @@ static URLSchemesSet& CORSEnabledSchemes() { - // FIXME: http://bugs.webkit.org/show_bug.cgi?id=77160 - assertLockHeld(); - DEFINE_STATIC_LOCAL_NOASSERT(URLSchemesSet, CORSEnabledSchemes, ()); + DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, CORSEnabledSchemes, ()); if (CORSEnabledSchemes.isEmpty()) { CORSEnabledSchemes.add("http"); @@ -162,8 +152,7 @@ static URLSchemesSet& serviceWorkerSchemes() { - assertLockHeld(); - DEFINE_STATIC_LOCAL_NOASSERT(URLSchemesSet, serviceWorkerSchemes, ()); + DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, serviceWorkerSchemes, ()); if (serviceWorkerSchemes.isEmpty()) { // HTTP is required because http://localhost is considered secure. @@ -178,8 +167,7 @@ static URLSchemesSet& fetchAPISchemes() { - assertLockHeld(); - DEFINE_STATIC_LOCAL_NOASSERT(URLSchemesSet, fetchAPISchemes, ()); + DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, fetchAPISchemes, ()); if (fetchAPISchemes.isEmpty()) { fetchAPISchemes.add("http"); @@ -191,22 +179,19 @@ static URLSchemesSet& firstPartyWhenTopLevelSchemes() { - assertLockHeld(); - DEFINE_STATIC_LOCAL_NOASSERT(URLSchemesSet, firstPartyWhenTopLevelSchemes, ()); + DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, firstPartyWhenTopLevelSchemes, ()); return firstPartyWhenTopLevelSchemes; } static URLSchemesMap<SchemeRegistry::PolicyAreas>& ContentSecurityPolicyBypassingSchemes() { - assertLockHeld(); - DEFINE_STATIC_LOCAL_NOASSERT(URLSchemesMap<SchemeRegistry::PolicyAreas>, schemes, ()); + DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesMap<SchemeRegistry::PolicyAreas>, schemes, ()); return schemes; } static URLSchemesSet& secureContextBypassingSchemes() { - assertLockHeld(); - DEFINE_STATIC_LOCAL_NOASSERT(URLSchemesSet, secureContextBypassingSchemes, ()); + DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, secureContextBypassingSchemes, ()); return secureContextBypassingSchemes; }
diff --git a/third_party/WebKit/Source/web/ChromeClientImpl.cpp b/third_party/WebKit/Source/web/ChromeClientImpl.cpp index 11f96db..499991c 100644 --- a/third_party/WebKit/Source/web/ChromeClientImpl.cpp +++ b/third_party/WebKit/Source/web/ChromeClientImpl.cpp
@@ -627,6 +627,7 @@ params.initialValue = params.selectedFiles[0]; params.useMediaCapture = fileChooser->settings().useMediaCapture; params.needLocalPath = fileChooser->settings().allowsDirectoryUpload; + params.requestor = frame->document()->url(); WebFileChooserCompletionImpl* chooserCompletion = new WebFileChooserCompletionImpl(fileChooser); if (client->runFileChooser(params, chooserCompletion))
diff --git a/third_party/WebKit/Source/web/LinkHighlightImpl.cpp b/third_party/WebKit/Source/web/LinkHighlightImpl.cpp index 2b6851ea..ce39f386 100644 --- a/third_party/WebKit/Source/web/LinkHighlightImpl.cpp +++ b/third_party/WebKit/Source/web/LinkHighlightImpl.cpp
@@ -102,7 +102,8 @@ LinkHighlightImpl::~LinkHighlightImpl() { if (m_compositorPlayer) { - m_compositorPlayer->detachLayer(); + if (m_compositorPlayer->isLayerAttached()) + m_compositorPlayer->detachLayer(); if (m_owningWebViewImpl->linkHighlightsTimeline()) m_owningWebViewImpl->linkHighlightsTimeline()->playerDestroyed(*this); m_compositorPlayer->setAnimationDelegate(nullptr);
diff --git a/third_party/WebKit/Source/web/LinkHighlightImplTest.cpp b/third_party/WebKit/Source/web/LinkHighlightImplTest.cpp index b528f71..1854d20 100644 --- a/third_party/WebKit/Source/web/LinkHighlightImplTest.cpp +++ b/third_party/WebKit/Source/web/LinkHighlightImplTest.cpp
@@ -169,6 +169,48 @@ Platform::current()->unitTestSupport()->unregisterAllMockedURLs(); } +// A lifetime test: delete LayerTreeView while running LinkHighlights. +TEST(LinkHighlightImplTest, resetLayerTreeView) +{ + OwnPtr<FakeCompositingWebViewClient> webViewClient = adoptPtr(new FakeCompositingWebViewClient()); + + const std::string baseURL("http://www.test.com/"); + const std::string fileName("test_touch_link_highlight.html"); + + URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(baseURL.c_str()), WebString::fromUTF8("test_touch_link_highlight.html")); + FrameTestHelpers::WebViewHelper webViewHelper; + WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(baseURL + fileName, true, 0, webViewClient.get()); + + int pageWidth = 640; + int pageHeight = 480; + webViewImpl->resize(WebSize(pageWidth, pageHeight)); + webViewImpl->updateAllLifecyclePhases(); + + WebGestureEvent touchEvent; + touchEvent.type = WebInputEvent::GestureShowPress; + touchEvent.sourceDevice = WebGestureDeviceTouchscreen; + touchEvent.x = 20; + touchEvent.y = 20; + + GestureEventWithHitTestResults targetedEvent = getTargetedEvent(webViewImpl, touchEvent); + Node* touchNode = webViewImpl->bestTapNode(targetedEvent); + ASSERT_TRUE(touchNode); + + webViewImpl->enableTapHighlightAtPoint(targetedEvent); + ASSERT_TRUE(webViewImpl->linkHighlight(0)); + + GraphicsLayer* highlightLayer = webViewImpl->linkHighlight(0)->currentGraphicsLayerForTesting(); + ASSERT_TRUE(highlightLayer); + EXPECT_TRUE(highlightLayer->linkHighlight(0)); + + // Mimic the logic from RenderWidget::Close: + webViewImpl->willCloseLayerTreeView(); + webViewClient.clear(); + webViewHelper.reset(); + + Platform::current()->unitTestSupport()->unregisterAllMockedURLs(); +} + TEST(LinkHighlightImplTest, multipleHighlights) { FrameTestHelpers::UseMockScrollbarSettings m_mockScrollbarSettings;
diff --git a/third_party/WebKit/Source/web/WebCSSParser.cpp b/third_party/WebKit/Source/web/WebCSSParser.cpp index ae13da3..39b5e81 100644 --- a/third_party/WebKit/Source/web/WebCSSParser.cpp +++ b/third_party/WebKit/Source/web/WebCSSParser.cpp
@@ -10,9 +10,12 @@ namespace blink { -bool WebCSSParser::parseColor(WebColor* color, const WebString& colorString) +bool WebCSSParser::parseColor(WebColor* webColor, const WebString& colorString) { - return CSSParser::parseColor(*color, colorString, true); + Color color = Color(*webColor); + bool success = CSSParser::parseColor(color, colorString, true); + *webColor = color.rgb(); + return success; } } // namespace blink
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp index 4e16751..0114670 100644 --- a/third_party/WebKit/Source/web/WebViewImpl.cpp +++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -2681,10 +2681,14 @@ void WebViewImpl::willCloseLayerTreeView() { if (m_linkHighlightsTimeline) { + m_linkHighlights.clear(); detachCompositorAnimationTimeline(m_linkHighlightsTimeline.get()); m_linkHighlightsTimeline.clear(); } + if (page()) + page()->willCloseLayerTreeView(); + setRootGraphicsLayer(nullptr); m_layerTreeView = nullptr; }
diff --git a/third_party/WebKit/Source/web/tests/ScrollAnimatorTest.cpp b/third_party/WebKit/Source/web/tests/ScrollAnimatorTest.cpp index 192702f..d691c95 100644 --- a/third_party/WebKit/Source/web/tests/ScrollAnimatorTest.cpp +++ b/third_party/WebKit/Source/web/tests/ScrollAnimatorTest.cpp
@@ -127,7 +127,6 @@ OwnPtrWillBeRawPtr<MockScrollableArea> scrollableArea = MockScrollableArea::create(true); OwnPtr<MockScrollAnimatorNone> scrollAnimatorNone = MockScrollAnimatorNone::create(scrollableArea.get()); - EXPECT_CALL(*scrollableArea, scrollSize(_)).Times(AtLeast(1)).WillRepeatedly(Return(1000)); EXPECT_CALL(*scrollableArea, minimumScrollPosition()).Times(AtLeast(1)).WillRepeatedly(Return(IntPoint())); EXPECT_CALL(*scrollableArea, maximumScrollPosition()).Times(AtLeast(1)).WillRepeatedly(Return(IntPoint(1000, 1000))); EXPECT_CALL(*scrollableArea, setScrollOffset(_, _)).Times(4); @@ -236,6 +235,7 @@ } void reset(); + bool updateDataFromParameters(float step, float multiplier, float minScrollPos, float maxScrollPos, double currentTime, ScrollAnimator::Parameters*); bool updateDataFromParameters(float step, float multiplier, float scrollableSize, double currentTime, ScrollAnimator::Parameters*); bool animateScroll(double currentTime); @@ -273,7 +273,7 @@ m_scrollingDown = true; } -bool ScrollAnimatorTest::updateDataFromParameters(float step, float multiplier, float scrollableSize, double currentTime, ScrollAnimator::Parameters* parameters) +bool ScrollAnimatorTest::updateDataFromParameters(float step, float multiplier, float minScrollPos, float maxScrollPos, double currentTime, ScrollAnimator::Parameters* parameters) { if (step * multiplier) m_scrollingDown = (step * multiplier > 0); @@ -281,7 +281,7 @@ double oldVelocity = m_data->m_currentVelocity; double oldDesiredVelocity = m_data->m_desiredVelocity; double oldTimeLeft = m_data->m_animationTime - (m_data->m_lastAnimationTime - m_data->m_startTime); - bool result = m_data->updateDataFromParameters(step, multiplier, scrollableSize, currentTime, parameters); + bool result = m_data->updateDataFromParameters(step, multiplier, minScrollPos, maxScrollPos, currentTime, parameters); if (m_scrollingDown) EXPECT_LE(oldVelocity, m_data->m_currentVelocity); else @@ -310,6 +310,11 @@ return result; } +bool ScrollAnimatorTest::updateDataFromParameters(float step, float multiplier, float scrollableSize, double currentTime, ScrollAnimator::Parameters* parameters) +{ + return updateDataFromParameters(step, multiplier, 0, scrollableSize, currentTime, parameters); +} + bool ScrollAnimatorTest::animateScroll(double currentTime) { double oldPosition = *m_data->m_currentPosition; @@ -804,6 +809,29 @@ result = result && animateScroll(t); } +TEST_F(ScrollAnimatorTest, ScrollRightToBumperRTL) +{ + // Tests that scrolling works for a negative scroll bound. This is the case + // for RTL pages where the scroll position is always negative. + m_currentPosition = 0; + ScrollAnimator::Parameters parameters(true, 10 * kTickTime, 7 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 0); + + EXPECT_TRUE(updateDataFromParameters(1, -20, -200, 0, kStartTime, ¶meters)); + bool result = true; + double t = kStartTime; + for (int i = 0; i < 10; ++i) { + t += kAnimationTime; + result = result && animateScroll(t); + updateDataFromParameters(1, -20, -200, 0, t, ¶meters); + } + checkDesiredPosition(-200); + + t += kAnimationTime; + for (; result && t < kEndTime; t += kAnimationTime) + result = result && animateScroll(t); + checkSoftLanding(-200); +} + TEST_F(ScrollAnimatorTest, ScrollDownToBumper) { ScrollAnimator::Parameters parameters(true, 10 * kTickTime, 7 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 0);
diff --git a/third_party/WebKit/Source/web/tests/sim/SimDisplayItemList.cpp b/third_party/WebKit/Source/web/tests/sim/SimDisplayItemList.cpp index 4b2636f..8965281 100644 --- a/third_party/WebKit/Source/web/tests/sim/SimDisplayItemList.cpp +++ b/third_party/WebKit/Source/web/tests/sim/SimDisplayItemList.cpp
@@ -29,11 +29,11 @@ bool SimDisplayItemList::contains(SimCanvas::CommandType type, const String& colorString) const { - RGBA32 color = 0; + Color color = 0; if (!colorString.isNull()) RELEASE_ASSERT(CSSParser::parseColor(color, colorString, true)); for (auto& command : m_commands) { - if (command.type == type && (colorString.isNull() || command.color == color)) + if (command.type == type && (colorString.isNull() || command.color == color.rgb())) return true; } return false;
diff --git a/third_party/WebKit/Source/web/web_tests.gyp b/third_party/WebKit/Source/web/web_tests.gyp index f036b66..98807e31 100644 --- a/third_party/WebKit/Source/web/web_tests.gyp +++ b/third_party/WebKit/Source/web/web_tests.gyp
@@ -153,13 +153,16 @@ 'conditions': [ ['v8_use_external_startup_data==1', { 'additional_input_paths': [ - '<(asset_location)/natives_blob.bin', - '<(asset_location)/snapshot_blob.bin', + '<(asset_location)/natives_blob_<(arch_suffix).bin', + '<(asset_location)/snapshot_blob_<(arch_suffix).bin', ], }], ], }, - 'includes': [ '../../../../build/apk_test.gypi' ], + 'includes': [ + '../../../../build/apk_test.gypi', + '../../../../build/android/v8_external_startup_data_arch_suffix.gypi', + ], }], }], ['test_isolation_mode != "noop"', {
diff --git a/third_party/WebKit/Source/wtf/StdLibExtras.h b/third_party/WebKit/Source/wtf/StdLibExtras.h index 0729d6c..62acd85 100644 --- a/third_party/WebKit/Source/wtf/StdLibExtras.h +++ b/third_party/WebKit/Source/wtf/StdLibExtras.h
@@ -72,11 +72,6 @@ static type& name = *new type arguments #endif -// Does the same as DEFINE_STATIC_LOCAL but without assertions. -// Use this when you are absolutely sure that it is safe but above -// assertions fail (e.g. called on multiple thread with a local lock). -#define DEFINE_STATIC_LOCAL_NOASSERT(type, name, arguments) \ - static type& name = *new type arguments #endif
diff --git a/third_party/WebKit/Source/wtf/text/AtomicString.cpp b/third_party/WebKit/Source/wtf/text/AtomicString.cpp index d3888ec..6ab4ab1f 100644 --- a/third_party/WebKit/Source/wtf/text/AtomicString.cpp +++ b/third_party/WebKit/Source/wtf/text/AtomicString.cpp
@@ -110,6 +110,11 @@ return atomicStringTable().table(); } +void AtomicString::reserveTableCapacity(size_t size) +{ + atomicStringTable().table().reserveCapacityForSize(size); +} + template<typename T, typename HashTranslator> static inline PassRefPtr<StringImpl> addToStringTable(const T& value) {
diff --git a/third_party/WebKit/Source/wtf/text/AtomicString.h b/third_party/WebKit/Source/wtf/text/AtomicString.h index 9cab9f5..3a7c995 100644 --- a/third_party/WebKit/Source/wtf/text/AtomicString.h +++ b/third_party/WebKit/Source/wtf/text/AtomicString.h
@@ -33,6 +33,7 @@ class WTF_EXPORT AtomicString { public: static void init(); + static void reserveTableCapacity(size_t); AtomicString() { } AtomicString(const LChar* s) : m_string(add(s)) { }
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py index c36e98cf..8fddcf4 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py
@@ -661,17 +661,27 @@ def add_expectation_line(self, expectation_line, model_all_expectations=False): - """Returns a list of warnings encountered while matching specifiers.""" - if expectation_line.is_invalid(): return for test in expectation_line.matching_tests: - if self._already_seen_better_match(test, expectation_line): - continue + lines_involve_rebaseline = False + prev_expectation_line = self.get_expectation_line(test) - if model_all_expectations: - expectation_line = TestExpectationLine.merge_expectation_lines(self.get_expectation_line(test), expectation_line, model_all_expectations) + if prev_expectation_line: + # The previous path matched more of the test. + if len(prev_expectation_line.path) > len(expectation_line.path): + continue + + if self._lines_conflict(prev_expectation_line, expectation_line): + continue + + lines_involve_rebaseline = self._expects_rebaseline(prev_expectation_line) or self._expects_rebaseline(expectation_line) + + # Exact path matches that conflict should be merged, e.g. + # [ Pass Timeout ] + [ NeedsRebaseline ] ==> [ Pass Timeout NeedsRebaseline ]. + if model_all_expectations or lines_involve_rebaseline: + expectation_line = TestExpectationLine.merge_expectation_lines(prev_expectation_line, expectation_line, model_all_expectations) self._clear_expectations_for_test(test) self._test_to_expectation_line[test] = expectation_line @@ -725,41 +735,20 @@ if test in set_of_tests: set_of_tests.remove(test) - def _already_seen_better_match(self, test, expectation_line): - """Returns whether we've seen a better match already in the file. + def _expects_rebaseline(self, expectation_line): + expectations = expectation_line.parsed_expectations + return REBASELINE in expectations or NEEDS_REBASELINE in expectations or NEEDS_MANUAL_REBASELINE in expectations - Returns True if we've already seen a expectation_line.name that matches more of the test - than this path does - """ - # FIXME: See comment below about matching test configs and specificity. - if not self.has_test(test): - # We've never seen this test before. + def _lines_conflict(self, prev_expectation_line, expectation_line): + if prev_expectation_line.path != expectation_line.path: return False - prev_expectation_line = self._test_to_expectation_line[test] - - if prev_expectation_line.filename != expectation_line.filename: - # We've moved on to a new expectation file, which overrides older ones. + if PASS in expectation_line.parsed_expectations and self._expects_rebaseline(prev_expectation_line): return False - if len(prev_expectation_line.path) > len(expectation_line.path): - # The previous path matched more of the test. - return True - - if len(prev_expectation_line.path) < len(expectation_line.path): - # This path matches more of the test. + if PASS in prev_expectation_line.parsed_expectations and self._expects_rebaseline(expectation_line): return False - # At this point we know we have seen a previous exact match on this - # base path, so we need to check the two sets of specifiers. - - # FIXME: This code was originally designed to allow lines that matched - # more specifiers to override lines that matched fewer specifiers. - # However, we currently view these as errors. - # - # To use the "more specifiers wins" policy, change the errors for overrides - # to be warnings and return False". - if prev_expectation_line.matching_configurations == expectation_line.matching_configurations: expectation_line.warnings.append('Duplicate or ambiguous entry lines %s:%s and %s:%s.' % ( self._shorten_filename(prev_expectation_line.filename), prev_expectation_line.line_numbers,
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py index feabaa9..702620b 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py
@@ -465,6 +465,10 @@ Bug(exp) failures/expected/text.html [ Failure ] Bug(exp) failures/expected/text.html [ Timeout ]""", is_lint_mode=True) + self.assertRaises(ParseError, self.parse_exp, """ +Bug(exp) failures/expected/text.html [ Failure ] +Bug(exp) failures/expected/text.html [ NeedsRebaseline ]""", is_lint_mode=True) + self.assertRaises(ParseError, self.parse_exp, self.get_basic_expectations(), overrides=""" Bug(override) failures/expected/text.html [ Failure ] @@ -476,6 +480,51 @@ Bug(exp) [ Debug ] failures/expected/text.html [ Failure ] """) + def test_duplicates_rebaseline_no_conflict(self): + # Rebaseline throws in lint mode, so only test it in non-lint mode. + # Check Rebaseline + self.parse_exp(""" +Bug(exp) failures/expected/text.html [ Rebaseline ] +Bug(exp) failures/expected/text.html [ Pass Failure ] +""", is_lint_mode=False) + self.assert_exp_list('failures/expected/text.html', [PASS, FAIL, REBASELINE]) + + # Check NeedsRebaseline. + self.parse_exp(""" +Bug(exp) failures/expected/text.html [ Pass Failure ] +Bug(exp) failures/expected/text.html [ NeedsRebaseline ] +""", is_lint_mode=False) + self.assert_exp_list('failures/expected/text.html', [PASS, FAIL, NEEDS_REBASELINE]) + + # Check NeedsManualRebaseline + self.parse_exp(""" +Bug(exp) failures/expected/text.html [ Pass Failure ] +Bug(exp) failures/expected/text.html [ NeedsManualRebaseline ] +""", is_lint_mode=False) + self.assert_exp_list('failures/expected/text.html', [PASS, FAIL, NEEDS_MANUAL_REBASELINE]) + + def test_duplicates_rebaseline_no_conflict_linting(self): + # Check NeedsRebaseline + self.parse_exp(""" +Bug(exp) failures/expected/text.html [ NeedsRebaseline ] +Bug(exp) failures/expected/text.html [ Pass Failure ] +""", is_lint_mode=True) + self.assert_exp_list('failures/expected/text.html', [PASS, FAIL, NEEDS_REBASELINE]) + + # Check lines in reverse order. + self.parse_exp(""" +Bug(exp) failures/expected/text.html [ Pass Failure ] +Bug(exp) failures/expected/text.html [ NeedsRebaseline ] +""", is_lint_mode=True) + self.assert_exp_list('failures/expected/text.html', [PASS, FAIL, NEEDS_REBASELINE]) + + # Check NeedsManualRebaseline + self.parse_exp(""" +Bug(exp) failures/expected/text.html [ Pass Failure ] +Bug(exp) failures/expected/text.html [ NeedsManualRebaseline ] +""", is_lint_mode=True) + self.assert_exp_list('failures/expected/text.html', [PASS, FAIL, NEEDS_MANUAL_REBASELINE]) + def test_missing_file(self): self.parse_exp('Bug(test) missing_file.html [ Failure ]') self.assertTrue(self._exp.has_warnings(), 1)
diff --git a/third_party/WebKit/public/platform/WebExternalTextureMailbox.h b/third_party/WebKit/public/platform/WebExternalTextureMailbox.h index f51d8e8d..7bc91af2 100644 --- a/third_party/WebKit/public/platform/WebExternalTextureMailbox.h +++ b/third_party/WebKit/public/platform/WebExternalTextureMailbox.h
@@ -35,16 +35,18 @@ struct WebExternalTextureMailbox { signed char name[64]; - unsigned syncPoint; + signed char syncToken[24]; + bool validSyncToken; bool allowOverlay; bool nearestNeighbor; WebExternalTextureMailbox() - : syncPoint(0) + : validSyncToken(false) , allowOverlay(false) , nearestNeighbor(false) { memset(name, 0, sizeof(name)); + memset(syncToken, 0, sizeof(syncToken)); } };
diff --git a/third_party/WebKit/public/platform/WebGraphicsContext3D.h b/third_party/WebKit/public/platform/WebGraphicsContext3D.h index 5e0521e8..b1362df1 100644 --- a/third_party/WebKit/public/platform/WebGraphicsContext3D.h +++ b/third_party/WebKit/public/platform/WebGraphicsContext3D.h
@@ -148,8 +148,8 @@ virtual void discardBackbufferCHROMIUM() { } virtual void ensureBackbufferCHROMIUM() { } - virtual unsigned insertSyncPoint() { return 0; } - virtual void waitSyncPoint(unsigned) { } + virtual bool insertSyncPoint(WGC3Dbyte*) { return false; } + virtual void waitSyncToken(const WGC3Dbyte*) {} // Copies the contents of the off-screen render target used by the WebGL // context to the corresponding texture used by the compositor.
diff --git a/third_party/WebKit/public/web/WebFileChooserParams.h b/third_party/WebKit/public/web/WebFileChooserParams.h index eaef311..8924f2f 100644 --- a/third_party/WebKit/public/web/WebFileChooserParams.h +++ b/third_party/WebKit/public/web/WebFileChooserParams.h
@@ -32,6 +32,7 @@ #define WebFileChooserParams_h #include "../platform/WebString.h" +#include "../platform/WebURL.h" #include "../platform/WebVector.h" #include "WebFileChooserCompletion.h" @@ -76,6 +77,9 @@ // WebFileChooserCompletion that can handle files without local paths, // 'false' should be specified to the flag. bool needLocalPath; + // If non-empty, represents the URL of the requestor if the request was + // initiated by a document. + WebURL requestor; WebFileChooserParams() : multiSelect(false)
diff --git a/third_party/closure_compiler/compiled_resources.gyp b/third_party/closure_compiler/compiled_resources.gyp index b98f3a1..614026dc 100644 --- a/third_party/closure_compiler/compiled_resources.gyp +++ b/third_party/closure_compiler/compiled_resources.gyp
@@ -29,7 +29,6 @@ '../../chrome/browser/resources/settings/compiled_resources.gyp:*', '../../chrome/browser/resources/uber/compiled_resources.gyp:*', '../../remoting/remoting_webapp_compile.gypi:*', - '../../ui/file_manager/audio_player/elements/compiled_resources.gyp:*', '../../ui/file_manager/audio_player/js/compiled_resources.gyp:*', '../../ui/file_manager/file_manager/background/js/compiled_resources.gyp:*', '../../ui/file_manager/file_manager/foreground/js/compiled_resources.gyp:*',
diff --git a/third_party/closure_compiler/externs/language_settings_private.js b/third_party/closure_compiler/externs/language_settings_private.js index 4d1cc7de..0b3d8e0 100644 --- a/third_party/closure_compiler/externs/language_settings_private.js +++ b/third_party/closure_compiler/externs/language_settings_private.js
@@ -46,7 +46,8 @@ * id: string, * displayName: string, * languageCodes: !Array<string>, - * enabled: boolean + * enabled: (boolean|undefined), + * hasOptionsPage: (boolean|undefined) * }} * @see https://developer.chrome.com/extensions/languageSettingsPrivate#type-InputMethod */ @@ -54,9 +55,8 @@ /** * @typedef {{ - * inputMethods: !Array<!chrome.languageSettingsPrivate.InputMethod>, - * componentExtensionIMEs: !Array<!chrome.languageSettingsPrivate.InputMethod>, - * thirdPartyExtensionIMEs: !Array<!chrome.languageSettingsPrivate.InputMethod> + * componentExtensionImes: !Array<!chrome.languageSettingsPrivate.InputMethod>, + * thirdPartyExtensionImes: !Array<!chrome.languageSettingsPrivate.InputMethod> * }} * @see https://developer.chrome.com/extensions/languageSettingsPrivate#type-InputMethodLists */ @@ -113,7 +113,7 @@ chrome.languageSettingsPrivate.getTranslateTargetLanguage = function(callback) {}; /** - * Gets all supported input methods, including IMEs. Chrome OS only. + * Gets all supported input methods, including third-party IMEs. Chrome OS only. * @param {function(!chrome.languageSettingsPrivate.InputMethodLists):void} callback * @see https://developer.chrome.com/extensions/languageSettingsPrivate#method-getInputMethodLists */
diff --git a/third_party/libjingle/README.chromium b/third_party/libjingle/README.chromium index f3c238b..300342aa 100644 --- a/third_party/libjingle/README.chromium +++ b/third_party/libjingle/README.chromium
@@ -1,7 +1,7 @@ Name: libjingle URL: http://code.google.com/p/webrtc/ Version: unknown -Revision: 10467 +Revision: 10491 License: BSD License File: source/talk/COPYING Security Critical: yes
diff --git a/third_party/libjingle/overrides/init_webrtc.cc b/third_party/libjingle/overrides/init_webrtc.cc index e1a73ea..8c1490de 100644 --- a/third_party/libjingle/overrides/init_webrtc.cc +++ b/third_party/libjingle/overrides/init_webrtc.cc
@@ -12,9 +12,9 @@ #include "base/native_library.h" #include "base/path_service.h" #include "base/trace_event/trace_event.h" -#include "third_party/webrtc_overrides/webrtc/base/logging.h" +#include "third_party/webrtc/base/event_tracer.h" #include "third_party/webrtc/system_wrappers/include/cpu_info.h" -#include "third_party/webrtc/system_wrappers/include/event_tracer.h" +#include "third_party/webrtc_overrides/webrtc/base/logging.h" const unsigned char* GetCategoryGroupEnabled(const char* category_group) { return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group);
diff --git a/third_party/mojo/src/mojo/public/c/gles2/BUILD.gn b/third_party/mojo/src/mojo/public/c/gles2/BUILD.gn index 0ac7e0f..892b21bc 100644 --- a/third_party/mojo/src/mojo/public/c/gles2/BUILD.gn +++ b/third_party/mojo/src/mojo/public/c/gles2/BUILD.gn
@@ -13,9 +13,6 @@ public_deps = [ ":headers", ] - deps = [ - "../../platform/native:gles2", - ] } mojo_sdk_source_set("headers") {
diff --git a/third_party/mojo/src/mojo/public/c/gpu/GLES2/gl2extmojo.h b/third_party/mojo/src/mojo/public/c/gpu/GLES2/gl2extmojo.h index a330ed8..929cb080 100644 --- a/third_party/mojo/src/mojo/public/c/gpu/GLES2/gl2extmojo.h +++ b/third_party/mojo/src/mojo/public/c/gpu/GLES2/gl2extmojo.h
@@ -644,10 +644,17 @@ #define GL_CHROMIUM_sync_point 1 #ifdef GL_GLEXT_PROTOTYPES GL_APICALL GLuint GL_APIENTRY glInsertSyncPointCHROMIUM(); -GL_APICALL void GL_APIENTRY glWaitSyncPointCHROMIUM(GLuint sync_point); +GL_APICALL GLuint64 GL_APIENTRY glInsertFenceSyncCHROMIUM(); +GL_APICALL void GL_APIENTRY glGenSyncTokenCHROMIUM(GLuint64 fence_sync, + GLbyte* sync_token); +GL_APICALL void GL_APIENTRY glWaitSyncTokenCHROMIUM(const GLbyte* sync_token); #endif typedef GLuint (GL_APIENTRYP PFNGLINSERTSYNCPOINTCHROMIUMPROC) (); -typedef void (GL_APIENTRYP PFNGLWAITSYNCPOINTCHROMIUMPROC) (GLuint sync_point); +typedef GLuint64 (GL_APIENTRYP PFNGLINSERTFENCESYNCCHROMIUMPROC) (); +typedef void (GL_APIENTRYP PFNGLGENSYNCTOKENCHROMIUMPROC) (GLuint64 fence_sync, + GLbyte* sync_token); +typedef void (GL_APIENTRYP PFNGLWAITSYNCTOKENCHROMIUM) ( + const GLbyte* sync_tokens); #endif /* GL_CHROMIUM_sync_point */ #ifndef GL_CHROMIUM_color_buffer_float_rgba
diff --git a/tools/android/eclipse/.classpath b/tools/android/eclipse/.classpath index 61d05012..d286aaf 100644 --- a/tools/android/eclipse/.classpath +++ b/tools/android/eclipse/.classpath
@@ -176,6 +176,7 @@ <classpathentry kind="lib" path="third_party/findbugs/lib/findbugs.jar"/> <classpathentry kind="lib" path="third_party/junit/src/lib/hamcrest-core-1.1.jar"/> <classpathentry kind="lib" path="third_party/robolectric/lib/robolectric-2.4-jar-with-dependencies.jar"/> + <classpathentry kind="lib" path="out/Debug/gen/chrome/android/chrome_public_apk/chrome_public_apk.jar"/> <classpathentry kind="lib" path="out/Debug/lib.java/cacheinvalidation_proto_java.jar"/> <classpathentry kind="lib" path="out/Debug/lib.java/content_java.jar"/> <classpathentry kind="lib" path="out/Debug/lib.java/jsr_305_javalib.jar"/>
diff --git a/tools/cr/cr/actions/gn.py b/tools/cr/cr/actions/gn.py index 5c683bd8..34b045b 100644 --- a/tools/cr/cr/actions/gn.py +++ b/tools/cr/cr/actions/gn.py
@@ -32,6 +32,10 @@ gn_args += (' is_debug=%s' % ('true' if cr.context['CR_BUILDTYPE'] == 'Debug' else 'false')) + arch = cr.context.Find('CR_ENVSETUP_ARCH') or '' + if arch: + gn_args += ' target_cpu="%s"' % ('x86' if arch == 'ia32' else arch) + # Detect goma. goma_binaries = cr.Host.SearchPath('gomacc', [ '{GOMA_DIR}',
diff --git a/tools/ipc_fuzzer/fuzzer/fuzzer.cc b/tools/ipc_fuzzer/fuzzer/fuzzer.cc index 51c5c059..193bd92 100644 --- a/tools/ipc_fuzzer/fuzzer/fuzzer.cc +++ b/tools/ipc_fuzzer/fuzzer/fuzzer.cc
@@ -1199,13 +1199,38 @@ }; template <> +struct FuzzTraits<gpu::SyncToken> { + static bool Fuzz(gpu::SyncToken* p, Fuzzer* fuzzer) { + bool verified_flush = false; + gpu::CommandBufferNamespace namespace_id = + gpu::CommandBufferNamespace::INVALID; + uint64_t command_buffer_id = 0; + uint64_t release_count = 0; + + if (!FuzzParam(&verified_flush, fuzzer)) + return false; + if (!FuzzParam(&namespace_id, fuzzer)) + return false; + if (!FuzzParam(&command_buffer_id, fuzzer)) + return false; + if (!FuzzParam(&release_count, fuzzer)) + return false; + + p->Clear(); + p->Set(namespace_id, command_buffer_id, release_count); + if (verified_flush) + p->SetVerifyFlush(); + } +}; + +template <> struct FuzzTraits<gpu::MailboxHolder> { static bool Fuzz(gpu::MailboxHolder* p, Fuzzer* fuzzer) { if (!FuzzParam(&p->mailbox, fuzzer)) return false; - if (!FuzzParam(&p->texture_target, fuzzer)) + if (!FuzzParam(&p->sync_token, fuzzer)) return false; - if (!FuzzParam(&p->sync_point, fuzzer)) + if (!FuzzParam(&p->texture_target, fuzzer)) return false; return true; }
diff --git a/tools/licenses.py b/tools/licenses.py index d8799e53..1b07310 100755 --- a/tools/licenses.py +++ b/tools/licenses.py
@@ -309,11 +309,12 @@ metadata[key] = line[len(field):] # Check that all expected metadata is present. + errors = [] for key, value in metadata.iteritems(): if not value: - raise LicenseError("couldn't find '" + key + "' line " - "in README.chromium or licences.py " - "SPECIAL_CASES") + errors.append("couldn't find '" + key + "' line " + "in README.chromium or licences.py " + "SPECIAL_CASES") # Special-case modules that aren't in the shipping product, so don't need # their license in about:credits. @@ -325,13 +326,15 @@ break if require_license_file and not license_path: - raise LicenseError("License file not found. " - "Either add a file named LICENSE, " - "import upstream's COPYING if available, " - "or add a 'License File:' line to " - "README.chromium with the appropriate path.") + errors.append("License file not found. " + "Either add a file named LICENSE, " + "import upstream's COPYING if available, " + "or add a 'License File:' line to " + "README.chromium with the appropriate path.") metadata["License File"] = license_path + if errors: + raise LicenseError(";\n".join(errors)) return metadata
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 847e093..834418e 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -430,6 +430,8 @@ 'chromium.fyi': { 'CrWinClang64(dbg)': 'win_clang_debug_bot', 'Libfuzzer Upload Linux': 'libfuzzer_upload_bot', + 'Site Isolation Linux': 'gn_release_trybot', + 'Site Isolation Win': 'gyp_release_trybot', }, 'chromium.webrtc.fyi': { 'Android GN': 'android_gn_release_bot', @@ -465,7 +467,7 @@ 'tryserver.chromium.linux': { 'linux_chromium_asan_rel_ng': 'swarming_asan_lsan_gyp_release_trybot', 'linux_full_bisect_builder': 'swarming_gyp_release_bot', - 'linux_site_isolation': 'gyp_release_trybot', + 'linux_site_isolation': 'gn_release_trybot', 'linux_chromium_compile_rel_ng': 'swarming_gn_release_trybot', 'linux_chromium_rel_ng': 'swarming_gpu_tests_gn_release_trybot', 'linux_chromium_gn_rel': 'gn_release_trybot',
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 399bb33..20361438 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -8873,6 +8873,22 @@ </description> </action> +<action name="OfflinePages.ViewingOffline.EditButtonClicked"> + <owner>jianli@chromium.org</owner> + <description> + Recorded when a user clicks on the "Edit" button on a snackbar + that shown when viewing offline page with no network. + </description> +</action> + +<action name="OfflinePages.ViewingOffline.EditButtonNotClicked"> + <owner>jianli@chromium.org</owner> + <description> + Recorded when a snackbar shown when viewing an offline page with no network + is dismissed without "Edit" button being clicked. + </description> +</action> + <action name="Omnibox.ServerSuggestDelete.Failure"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description> @@ -10986,6 +11002,16 @@ </description> </action> +<action name="PhysicalWeb.NotificationPressed"> + <owner>Please list the metric's owners. Add more owner tags as needed.</owner> + <description>Please enter the description of the metric.</description> +</action> + +<action name="PhysicalWeb.UrlSelected"> + <owner>Please list the metric's owners. Add more owner tags as needed.</owner> + <description>Please enter the description of the metric.</description> +</action> + <action name="PlatformVerificationAccepted"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 5c3f6eaa..a5b6f8f4 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -14858,6 +14858,99 @@ </summary> </histogram> +<histogram name="History.InMemoryDBItemCount"> + <owner>gab@chromium.org</owner> + <summary> + The number of typed URLs in the history database that are read into the + "in memory" history database. This in memory copy of the typed + URLs is used for synchronous inline autocomplete on the UI thread, while the + larger slower service is run off of disk on a background thread. + </summary> +</histogram> + +<histogram name="History.InMemoryDBKeywordTermsCount"> + <owner>gab@chromium.org</owner> + <summary>Number of items in in-memory keyword_search_terms table.</summary> +</histogram> + +<histogram name="History.InMemoryDBKeywordTermsPopulate" units="milliseconds"> + <owner>gab@chromium.org</owner> + <summary> + Time to load in-memory keyword_search_terms table from disk. + </summary> +</histogram> + +<histogram name="History.InMemoryDBKeywordURLItemCount"> + <owner>gab@chromium.org</owner> + <summary>Number of items in in-memory urls table.</summary> +</histogram> + +<histogram name="History.InMemoryDBKeywordURLPopulate" units="milliseconds"> + <owner>gab@chromium.org</owner> + <summary>Time to load in-memory urls table from disk urls table.</summary> +</histogram> + +<histogram name="History.InMemoryDBPopulate"> + <owner>gab@chromium.org</owner> + <summary> + The time it takes to read the typed URLs from the main history database into + the "in memory" history database. This in memory copy of the typed + URLs is used for synchronous inline autocomplete on the UI thread, while the + larger slower service is run off of disk on a background thread. + </summary> +</histogram> + +<histogram name="History.InMemoryTypedUrlVisitCount"> + <owner>gab@chromium.org</owner> + <summary> + The sum of the visit_count fields for all URLs in the "in memory" + history database. This corresponds to the number of times the user has + visited the typed URLs in the last 30 days (excluding page reloads, since + the history database does not increment the visit_count in that case). + </summary> +</histogram> + +<histogram name="History.InMemoryURLCacheSize" units="bytes"> + <owner>mpearson@chromium.org</owner> + <summary>Size of on-disk cache for in-memory url index.</summary> +</histogram> + +<histogram name="History.InMemoryURLChars"> + <owner>mpearson@chromium.org</owner> + <summary> + Size of in-memory url index char_word_map_ read from disk cache. + </summary> +</histogram> + +<histogram name="History.InMemoryURLHistoryItems"> + <owner>mpearson@chromium.org</owner> + <summary> + Number of history items read when loading in-memory url index disk cache. + </summary> +</histogram> + +<histogram name="History.InMemoryURLIndexingTime" units="milliseconds"> + <owner>mpearson@chromium.org</owner> + <summary> + Time to rebuild in-memory url index from main history database. + </summary> +</histogram> + +<histogram name="History.InMemoryURLIndexRestoreCacheTime" units="milliseconds"> + <owner>mpearson@chromium.org</owner> + <summary>Time to restore the in-memory url index from disk cache.</summary> +</histogram> + +<histogram name="History.InMemoryURLIndexSaveCacheTime" units="milliseconds"> + <owner>mpearson@chromium.org</owner> + <summary>Time to write in-memory url index to disk cache.</summary> +</histogram> + +<histogram name="History.InMemoryURLWords"> + <owner>mpearson@chromium.org</owner> + <summary>Size of in-memory url index word_map_ read from disk cache.</summary> +</histogram> + <histogram name="History.MonthlyHostCount"> <owner>shess@chromium.org</owner> <summary> @@ -29748,6 +29841,26 @@ </summary> </histogram> +<histogram name="Omnibox.ProgressBarBreakPointUpdateCount" + units="break point updates"> + <owner>kkimlabs@chromium.org</owner> + <summary> + The number of progress bar break point updates from page load started to + page load finished. + </summary> +</histogram> + +<histogram name="Omnibox.ProgressBarUpdateCount" units="frame updates"> + <owner>kkimlabs@chromium.org</owner> + <summary> + The number of progress bar frame updates from page load started to page load + finished. If there is no animation, this matches + Omnibox.ProgressBarBreakPointUpdateCount. Note that there can be additional + updates after page load finished, animating to 100%, but this histogram + doesn't include them. + </summary> +</histogram> + <histogram name="Omnibox.ProviderTime" units="milliseconds"> <obsolete> Deprecated 2015-06-12. Replaced by Omnibox.ProviderTime2. @@ -38587,6 +38700,28 @@ </summary> </histogram> +<histogram name="SafeBrowsing.UnverifiedDownloads.AllowedByWhitelist" + enum="SBClientDownloadExtensions"> + <owner>asanka@chromium.org</owner> + <summary> + File types that were allowed to be downloaded without verifying their + content nor their source URLs with Safe Browsing due to the requestor URL + being on the Safe Browsing whitelist. Each sample recorded on this histogram + is also recorded in SafeBrowsing.UnverifiedDownloads.Allowed. + </summary> +</histogram> + +<histogram name="SafeBrowsing.UnverifiedDownloads.AllowedDueToDisabledService" + enum="SBClientDownloadExtensions"> + <owner>asanka@chromium.org</owner> + <summary> + File types that were allowed to be downloaded without verifying their + content nor their source URLs with Safe Browsing due to the SafeBrowsing + service being disabled. Each sample recorded on this histogram is also + recorded in SafeBrowsing.UnverifiedDownloads.Allowed. + </summary> +</histogram> + <histogram name="SafeBrowsing.UnverifiedDownloads.Blocked" enum="SBClientDownloadExtensions"> <owner>asanka@chromium.org</owner> @@ -42356,6 +42491,14 @@ </summary> </histogram> +<histogram name="ShortcutsProvider.DatabaseSize"> + <owner>mpearson@chromium.org</owner> + <summary> + The number of entries in shortcuts backend's database when initialized, + which happens during profile load. + </summary> +</histogram> + <histogram name="ShortcutsProvider.QueryIndexTime" units="milliseconds"> <owner>davidben@chromium.org</owner> <summary> @@ -49468,6 +49611,18 @@ <summary>Time spent doing incremental marking steps during GC.</summary> </histogram> +<histogram name="V8.GCIncrementalMarkingFinalize" units="milliseconds"> + <owner>jochen@chromium.org</owner> + <owner>hpayer@chromium.org</owner> + <summary>Time spent in finalizing incremental marking.</summary> +</histogram> + +<histogram name="V8.GCIncrementalMarkingStart" units="milliseconds"> + <owner>jochen@chromium.org</owner> + <owner>hpayer@chromium.org</owner> + <summary>Time spent in starting incremental marking.</summary> +</histogram> + <histogram name="V8.GCLowMemoryNotification" units="milliseconds"> <owner>jochen@chromium.org</owner> <owner>hpayer@chromium.org</owner> @@ -65133,6 +65288,7 @@ <int value="-1319688939" label="ignore-gpu-blacklist"/> <int value="-1302904242" label="enable-navigation-tracing"/> <int value="-1285021473" label="save-page-as-mhtml"/> + <int value="-1271563519" label="enable-appcontainer"/> <int value="-1268836676" label="disable-out-of-process-pdf"/> <int value="-1267958145" label="disable-pdf-material-ui"/> <int value="-1251411236" label="disable-new-md-input-view"/> @@ -65283,6 +65439,7 @@ Command-line flag doesn't start with two dashes. </int> <int value="7533886" label="disable-offer-store-unmasked-wallet-cards"/> + <int value="10458238" label="disable-print-preview-simplify"/> <int value="11698808" label="enable-dom-distiller-button-animation"/> <int value="27507364" label="apps-keep-chrome-alive"/> <int value="37024318" label="disable-affiliation-based-matching"/> @@ -65331,6 +65488,7 @@ <int value="460475728" label="wake-on-wifi-packet"/> <int value="466248382" label="disable-push-api-background-mode"/> <int value="474743272" label="material-design-ink-drop"/> + <int value="493903641" label="disable-appcontainer"/> <int value="494733611" label="disable-drop-sync-credential"/> <int value="503245473" label="disable-translate-new-ux"/> <int value="535976218" label="enable-plugin-power-saver"/> @@ -80206,6 +80364,7 @@ <suffix name="4" label="N = 4"/> <suffix name="5" label="N = 5"/> <affected-histogram name="Omnibox.QueryTime"/> + <affected-histogram name="Omnibox.QueryTime2"/> <affected-histogram name="ShortcutsProvider.QueryIndexTime"/> </histogram_suffixes>
diff --git a/tools/perf/benchmarks/benchmark_smoke_unittest.py b/tools/perf/benchmarks/benchmark_smoke_unittest.py index e8e7bd9c..7955921 100644 --- a/tools/perf/benchmarks/benchmark_smoke_unittest.py +++ b/tools/perf/benchmarks/benchmark_smoke_unittest.py
@@ -18,6 +18,7 @@ from telemetry.testing import options_for_unittests from telemetry.testing import progress_reporter +from benchmarks import chrome_signin_startup from benchmarks import image_decoding from benchmarks import indexeddb_perf from benchmarks import jetstream @@ -83,6 +84,7 @@ octane, # Often fails & take long time to timeout on cq bot. rasterize_and_record_micro, # Always fails on cq bot. repaint, # Often fails & takes long time to timeout on cq bot. + chrome_signin_startup, # Failed on linux swarming bot (crbug.com/551236) spaceport, # Takes 451 seconds. speedometer, # Takes 101 seconds. jetstream, # Take 206 seconds.
diff --git a/tools/perf/perf.isolate b/tools/perf/perf.isolate new file mode 100644 index 0000000..520864fd --- /dev/null +++ b/tools/perf/perf.isolate
@@ -0,0 +1,19 @@ +# Copyright (c) 2015 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. +{ + 'includes': [ + './chrome_telemetry_build/telemetry_chrome_test.isolate', + ], + 'conditions': [ + ['OS=="android" or OS=="linux" or OS=="mac" or OS=="win"', { + 'variables': { + 'files': [ + './', + # Field trial configs + '../variations/', + ], + }, + }], + ] +}
diff --git a/tools/telemetry/telemetry.isolate b/tools/telemetry/telemetry.isolate index fc922e3..44bea2c 100644 --- a/tools/telemetry/telemetry.isolate +++ b/tools/telemetry/telemetry.isolate
@@ -8,6 +8,7 @@ 'files': [ '../../build/android/pylib/', '../../build/android/devil/', + '../../third_party/catapult/', './', # For Telemetry's screenshot support. '<(PRODUCT_DIR)/bitmaptools<(EXECUTABLE_SUFFIX)',
diff --git a/tools/telemetry/telemetry/internal/backends/chrome/desktop_browser_finder.py b/tools/telemetry/telemetry/internal/backends/chrome/desktop_browser_finder.py index 8cde4ae..10fbf61c 100644 --- a/tools/telemetry/telemetry/internal/backends/chrome/desktop_browser_finder.py +++ b/tools/telemetry/telemetry/internal/backends/chrome/desktop_browser_finder.py
@@ -5,7 +5,6 @@ import logging import os -import subprocess import sys from telemetry.core import exceptions @@ -14,7 +13,8 @@ from telemetry.internal.browser import browser from telemetry.internal.browser import possible_browser from telemetry.internal.platform import desktop_device -from telemetry.internal.util import path +# This is a workaround for https://goo.gl/1tGNgd +from telemetry.internal.util import path as path_module class PossibleDesktopBrowser(possible_browser.PossibleBrowser): @@ -183,7 +183,7 @@ if app_name in chromium_app_names or app_name == content_shell_app_name: normalized_executable = os.path.expanduser( finder_options.browser_executable) - if path.IsExecutable(normalized_executable): + if path_module.IsExecutable(normalized_executable): browser_directory = os.path.dirname(finder_options.browser_executable) browsers.append(PossibleDesktopBrowser( 'exact', finder_options, normalized_executable, flash_path, @@ -191,7 +191,8 @@ browser_directory)) else: raise exceptions.PathMissingError( - '%s specified by --browser-executable does not exist' % + '%s specified by --browser-executable does not exist or is not ' + 'executable' % normalized_executable) def AddIfFound(browser_type, build_dir, type_dir, app_name, content_shell): @@ -200,7 +201,7 @@ browser_directory = os.path.join(finder_options.chrome_root, build_dir, type_dir) app = os.path.join(browser_directory, app_name) - if path.IsExecutable(app): + if path_module.IsExecutable(app): is_64 = browser_type.endswith('_x64') browsers.append(PossibleDesktopBrowser( browser_type, finder_options, app, @@ -210,7 +211,7 @@ return False # Add local builds - for build_dir, build_type in path.GetBuildDirectories(): + for build_dir, build_type in path_module.GetBuildDirectories(): for chromium_app_name in chromium_app_names: AddIfFound(build_type.lower(), build_dir, build_type, chromium_app_name, False) @@ -229,12 +230,12 @@ mac_canary = mac_canary_root + 'Contents/MacOS/Google Chrome Canary' mac_system_root = '/Applications/Google Chrome.app' mac_system = mac_system_root + '/Contents/MacOS/Google Chrome' - if path.IsExecutable(mac_canary): + if path_module.IsExecutable(mac_canary): browsers.append(PossibleDesktopBrowser('canary', finder_options, mac_canary, None, False, mac_canary_root)) - if path.IsExecutable(mac_system): + if path_module.IsExecutable(mac_system): browsers.append(PossibleDesktopBrowser('system', finder_options, mac_system, None, False, mac_system_root)) @@ -242,7 +243,7 @@ mac_reference_root = ( reference_build_root + '/chrome_mac/Google Chrome.app/') mac_reference = mac_reference_root + 'Contents/MacOS/Google Chrome' - if path.IsExecutable(mac_reference): + if path_module.IsExecutable(mac_reference): browsers.append(PossibleDesktopBrowser('reference', finder_options, mac_reference, None, False, mac_reference_root)) @@ -250,28 +251,21 @@ # Linux specific options. if sys.platform.startswith('linux'): versions = { - 'system': ('google-chrome', - os.path.split(os.path.realpath('google-chrome'))[0]), - 'stable': ('google-chrome-stable', '/opt/google/chrome'), - 'beta': ('google-chrome-beta', '/opt/google/chrome-beta'), - 'dev': ('google-chrome-unstable', '/opt/google/chrome-unstable') + 'system': os.path.split(os.path.realpath('/usr/bin/google-chrome'))[0], + 'stable': '/opt/google/chrome', + 'beta': '/opt/google/chrome-beta', + 'dev': '/opt/google/chrome-unstable' } - for version, (name, root) in versions.iteritems(): - found = False - try: - with open(os.devnull, 'w') as devnull: - found = subprocess.call([name, '--version'], - stdout=devnull, stderr=devnull) == 0 - except OSError: - pass - if found: - browsers.append(PossibleDesktopBrowser(version, finder_options, name, - None, False, root)) + for version, root in versions.iteritems(): + browser_path = os.path.join(root, 'chrome') + if path_module.IsExecutable(browser_path): + browsers.append(PossibleDesktopBrowser(version, finder_options, + browser_path, None, False, root)) if reference_build_root: linux_reference_root = os.path.join(reference_build_root, 'chrome_linux') linux_reference = os.path.join(linux_reference_root, 'chrome') - if path.IsExecutable(linux_reference): + if path_module.IsExecutable(linux_reference): browsers.append(PossibleDesktopBrowser('reference', finder_options, linux_reference, None, False, linux_reference_root)) @@ -289,7 +283,7 @@ for browser_name, app_path in app_paths: for chromium_app_name in chromium_app_names: app_path = os.path.join(app_path, chromium_app_name) - app_path = path.FindInstalledWindowsApplication(app_path) + app_path = path_module.FindInstalledWindowsApplication(app_path) if app_path: browsers.append(PossibleDesktopBrowser( browser_name, finder_options, app_path,
diff --git a/tools/telemetry/telemetry/internal/backends/chrome/desktop_browser_finder_unittest.py b/tools/telemetry/telemetry/internal/backends/chrome/desktop_browser_finder_unittest.py index 746deb27..4227fb7 100644 --- a/tools/telemetry/telemetry/internal/backends/chrome/desktop_browser_finder_unittest.py +++ b/tools/telemetry/telemetry/internal/backends/chrome/desktop_browser_finder_unittest.py
@@ -1,8 +1,13 @@ # Copyright 2013 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 os +import stat import unittest +from pyfakefs import fake_filesystem_unittest + +from telemetry.core import platform from telemetry.internal.backends.chrome import desktop_browser_finder from telemetry.internal.browser import browser_options from telemetry.internal.platform import desktop_device @@ -21,7 +26,7 @@ self._finder_options.chrome_root = '../../../' self._finder_stubs = system_stub.Override(desktop_browser_finder, ['os', 'subprocess', 'sys']) - self._path_stubs = system_stub.Override(desktop_browser_finder.path, + self._path_stubs = system_stub.Override(desktop_browser_finder.path_module, ['os', 'sys']) def tearDown(self): @@ -140,98 +145,79 @@ 'canary', 'system'])) -class LinuxFindTest(FindTestBase): +class LinuxFindTest(fake_filesystem_unittest.TestCase): + def setUp(self): - super(LinuxFindTest, self).setUp() + if not platform.GetHostPlatform().GetOSName() == 'linux': + self.skipTest('Not running on Linux') + self.setUpPyfakefs() - self._finder_stubs.sys.platform = 'linux2' - self._path_stubs.sys.platform = 'linux2' - self._files.append('/foo/chrome') - self._files.append('../../../out/Release/chrome') - self._files.append('../../../out/Debug/chrome') - self._files.append('../../../out/Release/content_shell') - self._files.append('../../../out/Debug/content_shell') + self._finder_options = browser_options.BrowserFinderOptions() + self._finder_options.chrome_root = '/src/' - self.has_google_chrome_on_path = False - self.chrome_beta_is_google_chrome = False - this = self - def call_hook(*args, **kwargs): # pylint: disable=W0613 - if this.has_google_chrome_on_path: - return 0 - raise OSError('Not found') - self._finder_stubs.subprocess.call = call_hook + def CreateBrowser(self, path): + self.fs.CreateFile(path) + os.chmod(path, stat.S_IXUSR) - def realpath_hook(*unused_args, **unused_kwargs): - if this.chrome_beta_is_google_chrome: - return '/opt/google/chrome-beta/google-chrome-beta' - return '/opt/google/chrome/google-chrome' - self._finder_stubs.os.path.realpath = realpath_hook + def DoFindAll(self): + return desktop_browser_finder.FindAllAvailableBrowsers( + self._finder_options, desktop_device.DesktopDevice()) - def testFindAllWithExact(self): - if not self.CanFindAvailableBrowsers(): - return + def DoFindAllTypes(self): + return [b.browser_type for b in self.DoFindAll()] - types = self.DoFindAllTypes() + def testFindAllWithCheckout(self): + for target in ['Release', 'Debug']: + for browser in ['chrome', 'content_shell']: + self.CreateBrowser('/src/out/%s/%s' % (target, browser)) + self.assertEquals( - set(types), - set(['debug', 'release', - 'content-shell-debug', 'content-shell-release'])) + set(self.DoFindAllTypes()), + {'debug', 'release', 'content-shell-debug', 'content-shell-release'}) + + def testFindAllFailsIfNotExecutable(self): + self.fs.CreateFile('/src/out/Release/chrome') + + self.assertFalse(self.DoFindAllTypes()) def testFindWithProvidedExecutable(self): - if not self.CanFindAvailableBrowsers(): - return - + self.CreateBrowser('/foo/chrome') self._finder_options.browser_executable = '/foo/chrome' self.assertIn('exact', self.DoFindAllTypes()) def testFindWithProvidedApk(self): - if not self.CanFindAvailableBrowsers(): - return - self._finder_options.browser_executable = '/foo/chrome.apk' self.assertNotIn('exact', self.DoFindAllTypes()) - def testNoErrorWithUnrecognizedExecutableName(self): - if not self.CanFindAvailableBrowsers(): - return - - self._files.append('/foo/mandoline') + def testNoErrorWithNonChromeExecutableName(self): + self.fs.CreateFile('/foo/mandoline') self._finder_options.browser_executable = '/foo/mandoline' self.assertNotIn('exact', self.DoFindAllTypes()) - def testFindUsingDefaults(self): - if not self.CanFindAvailableBrowsers(): - return + def testFindAllWithInstalled(self): + official_names = ['chrome', 'chrome-beta', 'chrome-unstable'] - self.has_google_chrome_on_path = True - self.assertIn('release', self.DoFindAllTypes()) + for name in official_names: + self.CreateBrowser('/opt/google/%s/chrome' % name) - del self._files[1] - self.has_google_chrome_on_path = True - self.assertIn('system', self.DoFindAllTypes()) - self.assertIn('stable', self.DoFindAllTypes()) - self.assertIn('beta', self.DoFindAllTypes()) - self.assertIn('dev', self.DoFindAllTypes()) + self.assertEquals(set(self.DoFindAllTypes()), {'stable', 'beta', 'dev'}) - self.has_google_chrome_on_path = False - del self._files[1] - self.assertEquals(['content-shell-debug', 'content-shell-release'], - self.DoFindAllTypes()) + def testFindAllSystem(self): + self.CreateBrowser('/opt/google/chrome/chrome') + os.symlink('/opt/google/chrome/chrome', '/usr/bin/google-chrome') - self.has_google_chrome_on_path = True - self.chrome_beta_is_google_chrome = True + self.assertEquals(set(self.DoFindAllTypes()), {'system', 'stable'}) + + def testFindAllSystemIsBeta(self): + self.CreateBrowser('/opt/google/chrome/chrome') + self.CreateBrowser('/opt/google/chrome-beta/chrome') + os.symlink('/opt/google/chrome-beta/chrome', '/usr/bin/google-chrome') google_chrome = [browser for browser in self.DoFindAll() - if browser._local_executable == 'google-chrome'][0] + if browser.browser_type == 'system'][0] self.assertEquals('/opt/google/chrome-beta', google_chrome._browser_directory) - def testFindUsingRelease(self): - if not self.CanFindAvailableBrowsers(): - return - - self.assertIn('release', self.DoFindAllTypes()) - class WinFindTest(FindTestBase): def setUp(self):
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt index 9b478189..d89435e9 100644 --- a/tools/valgrind/memcheck/suppressions.txt +++ b/tools/valgrind/memcheck/suppressions.txt
@@ -3435,10 +3435,3 @@ fun:_ZN7content21RenderProcessHostImpl4InitEv fun:_ZN7content22RenderFrameHostManager14InitRenderViewEPNS_18RenderViewHostImplEPNS_20RenderFrameProxyHostE } -{ - bug_550566 - Memcheck:Leak - fun:_Znw* - fun:_ZN4base19SequencedWorkerPool* - fun:_ZN4base12_GLOBAL__N_158SequencedTaskRunnerHandleTest_FromSequencedWorkerPool_Test8TestBody* -}
diff --git a/ui/android/java/src/org/chromium/ui/resources/ResourceManager.java b/ui/android/java/src/org/chromium/ui/resources/ResourceManager.java index 9897728a..0cf00b1b 100644 --- a/ui/android/java/src/org/chromium/ui/resources/ResourceManager.java +++ b/ui/android/java/src/org/chromium/ui/resources/ResourceManager.java
@@ -129,7 +129,10 @@ CrushedSpriteResource crushedResource = (CrushedSpriteResource) resource; nativeOnCrushedSpriteResourceReady(mNativeResourceManagerPtr, resId, crushedResource.getBitmap(), crushedResource.getFrameRectangles(), - crushedResource.getSpriteWidth(), crushedResource.getSpriteHeight()); + crushedResource.getUnscaledSpriteWidth(), + crushedResource.getUnscaledSpriteHeight(), + crushedResource.getScaledSpriteWidth(), + crushedResource.getScaledSpriteHeight()); } return; } @@ -197,7 +200,8 @@ int paddingBottom, int apertureLeft, int apertureTop, int apertureRight, int apertureBottom); private native void nativeOnCrushedSpriteResourceReady(long nativeResourceManagerImpl, - int bitmapResId, Bitmap bitmap, int[][] frameRects, int spriteWidth, int spriteHeight); + int bitmapResId, Bitmap bitmap, int[][] frameRects, int unscaledSpriteWidth, + int unscaledSpriteHeight, float scaledSpriteWidth, float scaledSpriteHeight); private native void nativeOnCrushedSpriteResourceReloaded(long nativeResourceManagerImpl, int bitmapResId, Bitmap bitmap);
diff --git a/ui/android/java/src/org/chromium/ui/resources/sprites/CrushedSpriteResource.java b/ui/android/java/src/org/chromium/ui/resources/sprites/CrushedSpriteResource.java index 38e7fa51..3c435b9 100644 --- a/ui/android/java/src/org/chromium/ui/resources/sprites/CrushedSpriteResource.java +++ b/ui/android/java/src/org/chromium/ui/resources/sprites/CrushedSpriteResource.java
@@ -30,8 +30,10 @@ private Bitmap mBitmap; private final Rect mBitmapSize = new Rect(); - private int mSpriteWidth; - private int mSpriteHeight; + private float mScaledSpriteWidth; + private float mScaledSpriteHeight; + private int mUnscaledSpriteWidth; + private int mUnscaledSpriteHeight; private int[][] mRectangles; /** @@ -90,17 +92,31 @@ } /** + * @return The scaled width of an individual sprite in px. + */ + public float getScaledSpriteWidth() { + return mScaledSpriteWidth; + } + + /** + * @return The scaled height of an individual sprite in px. + */ + public float getScaledSpriteHeight() { + return mScaledSpriteHeight; + } + + /** * @return The unscaled width of an individual sprite in px. */ - public int getSpriteWidth() { - return mSpriteWidth; + public int getUnscaledSpriteWidth() { + return mUnscaledSpriteWidth; } /** * @return The unscaled height of an individual sprite in px. */ - public int getSpriteHeight() { - return mSpriteHeight; + public int getUnscaledSpriteHeight() { + return mUnscaledSpriteHeight; } /** @@ -121,12 +137,14 @@ * in this format: * { * "apiVersion": <version number (string)>, + * "scaledSpriteWidthDp": <scaled sprite width in dp (int)>, + * "scaledSpriteHeightDp": <scaled sprite width in dp (int)>, * "densities": * [ * { * "density": <density (int)>, - * "width": <unscaled sprite width (int)>, - * "height": <unscaled sprite height (int)>, + * "width": <unscaled sprite width in px (int)>, + * "height": <unscaled sprite height in px (int)>, * "rectangles": [ * [<list of ints for frame 0>], * [<list of ints for frame 1>], @@ -135,8 +153,8 @@ * }, * { * "density": <density (int)>, - * "width": <unscaled sprite width (int)>, - * "height": <unscaled sprite height (int)>, + * "width": <unscaled sprite width in px (int)>, + * "height": <unscaled sprite height in px (int)>, * "rectangles": [ * [<list of ints for frame 0>], * [<list of ints for frame 1>], @@ -166,6 +184,15 @@ String version = reader.nextString(); assert version.equals("1.0"); + // Get scaled sprite dimensions. + float dpToPx = resources.getDisplayMetrics().density; + name = reader.nextName(); + assert name.equals("scaledSpriteWidthDp"); + mScaledSpriteWidth = reader.nextInt() * dpToPx; + name = reader.nextName(); + assert name.equals("scaledSpriteHeightDp"); + mScaledSpriteHeight = reader.nextInt() * dpToPx; + // Parse array of densities. name = reader.nextName(); assert name.equals("densities"); @@ -212,11 +239,11 @@ name = reader.nextName(); assert name.equals("width"); - mSpriteWidth = reader.nextInt(); + mUnscaledSpriteWidth = reader.nextInt(); name = reader.nextName(); assert name.equals("height"); - mSpriteHeight = reader.nextInt(); + mUnscaledSpriteHeight = reader.nextInt(); name = reader.nextName(); assert name.equals("rectangles");
diff --git a/ui/android/javatests/src/org/chromium/ui/resources/sprites/CrushedSpriteResourceTest.java b/ui/android/javatests/src/org/chromium/ui/resources/sprites/CrushedSpriteResourceTest.java index 2635a487..f7e2bb0 100644 --- a/ui/android/javatests/src/org/chromium/ui/resources/sprites/CrushedSpriteResourceTest.java +++ b/ui/android/javatests/src/org/chromium/ui/resources/sprites/CrushedSpriteResourceTest.java
@@ -34,9 +34,12 @@ int[][] expectedRectangles = {{35, 30, 38, 165, 18, 12, 0, 70, 0, 146, 72, 2}, {}, {0, 0, 73, 0, 72, 72}}; int[][] actualRectangles = crushedSpriteResource.getFrameRectangles(); + float dpToPx = mockResources.getDisplayMetrics().density; - assertEquals(108, crushedSpriteResource.getSpriteWidth()); - assertEquals(108, crushedSpriteResource.getSpriteHeight()); + assertEquals(108, crushedSpriteResource.getUnscaledSpriteWidth()); + assertEquals(108, crushedSpriteResource.getUnscaledSpriteHeight()); + assertEquals(36 * dpToPx, crushedSpriteResource.getScaledSpriteWidth()); + assertEquals(36 * dpToPx, crushedSpriteResource.getScaledSpriteHeight()); assertEquals(expectedRectangles.length, actualRectangles.length); for (int i = 0; i < expectedRectangles.length; i++) { assertEquals(expectedRectangles[i].length, actualRectangles[i].length); @@ -61,37 +64,50 @@ } } - private static final String METADATA = "{\"apiVersion\": \"1.0\", \"densities\": [" - + "{" - + " \"density\": 160," - + " \"width\": 36," - + " \"height\": 36," - + " \"rectangles\": [" - + " [17, 14, 47, 69, 10, 8, 0, 34, 37, 0, 36, 2]," - + " []," - + " [0, 0, 0, 0, 36, 36]" + @Override + public DisplayMetrics getDisplayMetrics() { + DisplayMetrics metrics = new DisplayMetrics(); + metrics.density = 2; + return metrics; + } + + private static final String METADATA = + "{" + + "\"apiVersion\": \"1.0\"," + + "\"scaledSpriteWidthDp\": 36," + + "\"scaledSpriteHeightDp\": 36," + + "\"densities\":" + + "[" + + " {" + + " \"density\": 160," + + " \"width\": 36," + + " \"height\": 36," + + " \"rectangles\": [" + + " [17, 14, 47, 69, 10, 8, 0, 34, 37, 0, 36, 2]," + + " []," + + " [0, 0, 0, 0, 36, 36]" + " ]" - + "}," - + "{" - + " \"density\": 480," - + " \"width\": 108," - + " \"height\": 108," - + " \"rectangles\": [" - + " [35, 30, 38, 165, 18, 12, 0, 70, 0, 146, 72, 2]," - + " []," - + " [0, 0, 73, 0, 72, 72]" + + " }," + + " {" + + " \"density\": 480," + + " \"width\": 108," + + " \"height\": 108," + + " \"rectangles\": [" + + " [35, 30, 38, 165, 18, 12, 0, 70, 0, 146, 72, 2]," + + " []," + + " [0, 0, 73, 0, 72, 72]" + " ]" - + "}," - + "{" - + " \"density\": 640," - + " \"width\": 144," - + " \"height\": 144," - + " \"rectangles\": [" - + " [71, 62, 820, 3, 34, 21, 0, 142, 725, 0, 144, 2]," - + " []," - + " [0, 0, 145, 0, 144, 144]" + + " }," + + " {" + + " \"density\": 640," + + " \"width\": 144," + + " \"height\": 144," + + " \"rectangles\": [" + + " [71, 62, 820, 3, 34, 21, 0, 142, 725, 0, 144, 2]," + + " []," + + " [0, 0, 145, 0, 144, 144]" + " ]" - + "}" + + " }" + "]}"; }
diff --git a/ui/android/resources/crushed_sprite_resource.cc b/ui/android/resources/crushed_sprite_resource.cc index becc0db0..ee6a6d1 100644 --- a/ui/android/resources/crushed_sprite_resource.cc +++ b/ui/android/resources/crushed_sprite_resource.cc
@@ -13,9 +13,11 @@ CrushedSpriteResource::CrushedSpriteResource( const SkBitmap& bitmap, const SrcDstRects& src_dst_rects, - gfx::Size sprite_size) + gfx::Size unscaled_sprite_size, + gfx::Size scaled_sprite_size) : src_dst_rects_(src_dst_rects), - sprite_size_(sprite_size) { + unscaled_sprite_size_(unscaled_sprite_size), + scaled_sprite_size_(scaled_sprite_size) { SetBitmap(bitmap); } @@ -46,8 +48,12 @@ return src_dst_rects_[frame]; } -gfx::Size CrushedSpriteResource::GetSpriteSize() { - return sprite_size_; +gfx::Size CrushedSpriteResource::GetUnscaledSpriteSize() { + return unscaled_sprite_size_; +} + +gfx::Size CrushedSpriteResource::GetScaledSpriteSize() { + return scaled_sprite_size_; } int CrushedSpriteResource::GetFrameCount() {
diff --git a/ui/android/resources/crushed_sprite_resource.h b/ui/android/resources/crushed_sprite_resource.h index 12eb868..bf3ce85 100644 --- a/ui/android/resources/crushed_sprite_resource.h +++ b/ui/android/resources/crushed_sprite_resource.h
@@ -38,10 +38,13 @@ // Creates a new CrushedSpriteResource. |bitmap_res_id| is the id for the // for the source bitmap, |java_bitmap| is the source bitmap for the crushed // sprite, |src_dst_rects| is a list of rectangles to draw for each frame, and - // |sprite_size| is the size of an individual sprite. + // |unscaled_sprite_size| is the size of an individual sprite unscaled. The + // sprite should be drawn at its unscaled size then scaled to + // |scaled_sprite_size|. CrushedSpriteResource(const SkBitmap& bitmap, const SrcDstRects& src_dst_rects, - gfx::Size sprite_size); + gfx::Size unscaled_sprite_size, + gfx::Size scaled_sprite_size); ~CrushedSpriteResource(); // Sets the source bitmap. @@ -59,8 +62,11 @@ // Returns a list of rectangles to be drawn for |frame|. FrameSrcDstRects GetRectanglesForFrame(int frame); - // Returns the size of an individual sprite. - gfx::Size GetSpriteSize(); + // Returns the unscaled size of an individual sprite. + gfx::Size GetUnscaledSpriteSize(); + + // Returns the scaled size of an individual sprite. + gfx::Size GetScaledSpriteSize(); // Returns the total number of frames in the sprite animation. int GetFrameCount(); @@ -69,7 +75,8 @@ SkBitmap bitmap_; scoped_ptr<cc::ScopedUIResource> last_frame_resource_; SrcDstRects src_dst_rects_; - gfx::Size sprite_size_; + gfx::Size unscaled_sprite_size_; + gfx::Size scaled_sprite_size_; DISALLOW_COPY_AND_ASSIGN(CrushedSpriteResource); };
diff --git a/ui/android/resources/resource_manager_impl.cc b/ui/android/resources/resource_manager_impl.cc index 3c1f1a8..a4f2373 100644 --- a/ui/android/resources/resource_manager_impl.cc +++ b/ui/android/resources/resource_manager_impl.cc
@@ -140,8 +140,10 @@ jint bitmap_res_id, jobject bitmap, jobjectArray frame_rects, - jint sprite_width, - jint sprite_height) { + jint unscaled_sprite_width, + jint unscaled_sprite_height, + jfloat scaled_sprite_width, + jfloat scaled_sprite_height) { // Construct source and destination rectangles for each frame from // |frame_rects|. @@ -156,7 +158,8 @@ CrushedSpriteResource* resource = new CrushedSpriteResource( skbitmap, src_dst_rects, - gfx::Size(sprite_width, sprite_height)); + gfx::Size(unscaled_sprite_width, unscaled_sprite_height), + gfx::Size(scaled_sprite_width, scaled_sprite_height)); if (crushed_sprite_resources_.Lookup(bitmap_res_id)) { crushed_sprite_resources_.Replace(bitmap_res_id, resource);
diff --git a/ui/android/resources/resource_manager_impl.h b/ui/android/resources/resource_manager_impl.h index 0c6e1279..04d59cc 100644 --- a/ui/android/resources/resource_manager_impl.h +++ b/ui/android/resources/resource_manager_impl.h
@@ -48,8 +48,10 @@ jint bitmap_res_id, jobject bitmap, jobjectArray frame_rects, - jint sprite_width, - jint sprite_height); + jint unscaled_sprite_width, + jint unscaled_sprite_height, + jfloat scaled_sprite_width, + jfloat scaled_sprite_height); void OnCrushedSpriteResourceReloaded(JNIEnv* env, jobject jobj, jint bitmap_res_id,
diff --git a/ui/aura/bench/bench_main.cc b/ui/aura/bench/bench_main.cc index ce85572..573e23e 100644 --- a/ui/aura/bench/bench_main.cc +++ b/ui/aura/bench/bench_main.cc
@@ -142,10 +142,10 @@ void ReturnMailbox(scoped_refptr<cc::ContextProvider> context_provider, GLuint texture, - GLuint sync_point, + const gpu::SyncToken& sync_token, bool is_lost) { gpu::gles2::GLES2Interface* gl = context_provider->ContextGL(); - gl->WaitSyncPointCHROMIUM(sync_point); + gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); gl->DeleteTextures(1, &texture); gl->ShallowFlushCHROMIUM(); } @@ -227,7 +227,7 @@ GLuint sync_point = gl->InsertSyncPointCHROMIUM(); webgl_.SetTextureMailbox( - cc::TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), + cc::TextureMailbox(mailbox, gpu::SyncToken(sync_point), GL_TEXTURE_2D), cc::SingleReleaseCallback::Create( base::Bind(ReturnMailbox, context_provider_, texture)), bounds.size());
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index d68d043..36d56f26 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc
@@ -553,7 +553,7 @@ frame_size_in_dip_ = gfx::Size(); } if (mailbox_release_callback_) - mailbox_release_callback_->Run(0, false); + mailbox_release_callback_->Run(gpu::SyncToken(), false); mailbox_release_callback_ = release_callback.Pass(); mailbox_ = mailbox; SetTextureSize(texture_size_in_dip); @@ -623,7 +623,7 @@ mailbox_ = cc::TextureMailbox(); if (mailbox_release_callback_) { - mailbox_release_callback_->Run(0, false); + mailbox_release_callback_->Run(gpu::SyncToken(), false); mailbox_release_callback_.reset(); } RecomputeDrawsContentAndUVRect();
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc index 7b96199a..935bfa7 100644 --- a/ui/compositor/layer_unittest.cc +++ b/ui/compositor/layer_unittest.cc
@@ -707,7 +707,7 @@ EXPECT_EQ(name, roundtrip); } -void ReturnMailbox(bool* run, uint32 sync_point, bool is_lost) { +void ReturnMailbox(bool* run, const gpu::SyncToken& sync_token, bool is_lost) { *run = true; } @@ -728,7 +728,7 @@ cc::Layer* before_layer = l1->cc_layer_for_testing(); bool callback1_run = false; - cc::TextureMailbox mailbox(gpu::Mailbox::Generate(), 0, 0); + cc::TextureMailbox mailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), 0); l1->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create( base::Bind(ReturnMailbox, &callback1_run)), gfx::Size(10, 10)); @@ -744,7 +744,7 @@ EXPECT_FALSE(callback1_run); bool callback2_run = false; - mailbox = cc::TextureMailbox(gpu::Mailbox::Generate(), 0, 0); + mailbox = cc::TextureMailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), 0); l1->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create( base::Bind(ReturnMailbox, &callback2_run)), gfx::Size(10, 10)); @@ -765,7 +765,7 @@ // Back to a texture, without changing the bounds of the layer or the texture. bool callback3_run = false; - mailbox = cc::TextureMailbox(gpu::Mailbox::Generate(), 0, 0); + mailbox = cc::TextureMailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), 0); l1->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create( base::Bind(ReturnMailbox, &callback3_run)), gfx::Size(10, 10));
diff --git a/ui/events/OWNERS b/ui/events/OWNERS index d9d3b1f..f14df80fd 100644 --- a/ui/events/OWNERS +++ b/ui/events/OWNERS
@@ -1,4 +1,5 @@ sadrul@chromium.org +per-file latency_info*=tdresser@chromium.org per-file latency_info*=jbauman@chromium.org per-file latency_info*=miletus@chromium.org
diff --git a/ui/file_manager/audio_player/elements/compiled_resources.gyp b/ui/file_manager/audio_player/elements/compiled_resources.gyp deleted file mode 100644 index 8ff70cd..0000000 --- a/ui/file_manager/audio_player/elements/compiled_resources.gyp +++ /dev/null
@@ -1,45 +0,0 @@ -# Copyright 2015 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. -{ - 'targets': [ - { - 'target_name': 'track_list', - 'variables': { - 'depends': [], - 'externs': [ - '../../externs/es7_workaround.js' - ] - }, - 'includes': [ - '../../compile_js.gypi' - ] - }, - { - 'target_name': 'control_panel', - 'variables': { - 'depends': [], - 'externs': [] - }, - 'includes': [ - '../../compile_js.gypi' - ] - }, - { - 'target_name': 'audio_player', - 'variables': { - 'depends': [ - '../js/audio_player_model.js', - 'track_list.js', - ], - 'externs': [ - '<(EXTERNS_DIR)/chrome_extensions.js', - '../../externs/es7_workaround.js', - ] - }, - 'includes': [ - '../../compile_js.gypi' - ] - } - ], -}
diff --git a/ui/file_manager/audio_player/js/compiled_resources.gyp b/ui/file_manager/audio_player/js/compiled_resources.gyp index 232d181..4c4486d 100644 --- a/ui/file_manager/audio_player/js/compiled_resources.gyp +++ b/ui/file_manager/audio_player/js/compiled_resources.gyp
@@ -77,6 +77,9 @@ '../../file_manager/foreground/js/metadata/thumbnail_model.js', '../../file_manager/background/js/volume_manager.js', '../../file_manager/foreground/js/volume_manager_wrapper.js', + '../elements/control_panel.js', + '../elements/track_list.js', + '../elements/audio_player.js', 'audio_player_model.js', ], 'externs': [ @@ -89,7 +92,6 @@ '../../externs/chrome_test.js', '../../externs/es6_workaround.js', '../../externs/es7_workaround.js', - '../../externs/files_elements.js', '../../externs/platform.js', ], },
diff --git a/ui/file_manager/file_manager/foreground/elements/files_toast.js b/ui/file_manager/file_manager/foreground/elements/files_toast.js index 2a539a6e..32e047fd 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_toast.js +++ b/ui/file_manager/file_manager/foreground/elements/files_toast.js
@@ -31,7 +31,7 @@ */ created: function() { /** - * @private {{text: string, callback: function()}} + * @private {?{text: string, callback: function()}} */ this.action_ = null;
diff --git a/ui/file_manager/file_manager/foreground/js/actions_controller.js b/ui/file_manager/file_manager/foreground/js/actions_controller.js index 13212be..5311315 100644 --- a/ui/file_manager/file_manager/foreground/js/actions_controller.js +++ b/ui/file_manager/file_manager/foreground/js/actions_controller.js
@@ -78,12 +78,8 @@ /** * @private {ActionsController.Context} */ - this.focusContext_ = ActionsController.Context.FILE_LIST; + this.menuContext_ = ActionsController.Context.UNKNOWN; - this.updateContext_(document.activeElement); - - document.addEventListener( - 'focus', this.onDocumentFocus_.bind(this), true); this.ui_.directoryTree.addEventListener( 'change', this.onNavigationListSelectionChanged_.bind(this), true); this.selectionHandler_.addEventListener( @@ -130,7 +126,7 @@ * @private */ ActionsController.prototype.updateUI_ = function() { - var actionsModel = this.getActionsModelForContext(this.focusContext_); + var actionsModel = this.getActionsModelForContext(this.menuContext_); // TODO(mtomasz): Prevent flickering somehow. this.ui_.actionsSubmenu.setActionsModel(actionsModel); }; @@ -139,32 +135,9 @@ * @param {!Event} event * @private */ -ActionsController.prototype.onDocumentFocus_ = function(event) { - if (!this.updateContext_(document.activeElement)) - return; - - // Update UI with the model for the focused context. - this.updateUI_(); -}; - -/** - * @param {!Event} event - * @private - */ ActionsController.prototype.onContextMenuShow_ = function(event) { - if (this.updateContext_(event.element)) - this.updateUI_(); -}; - -/** - * @param {!HTMLElement} element - * @return {boolean} Whether the context has changed. - * @private - */ -ActionsController.prototype.updateContext_ = function(element) { - var previousContext = this.focusContext_; - this.focusContext_ = this.getContextFor_(element); - return this.focusContext_ != previousContext; + this.menuContext_ = this.getContextFor_(event.element); + this.updateUI_(); }; /**
diff --git a/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp b/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp index f1cd7896..44f50c2 100644 --- a/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp +++ b/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp
@@ -69,6 +69,7 @@ '../../background/js/background.js', '../../../image_loader/image_loader_client.js', '../elements/files_ripple.js', + '../elements/files_toggle_ripple.js', '../elements/files_tooltip.js', './metrics_start.js', './ui/combobutton.js', @@ -160,7 +161,6 @@ '../../../externs/connection.js', '../../../externs/css_rule.js', '../../../externs/es6_workaround.js', - '../../../externs/files_elements.js', '../../../externs/html_menu_item_element.js', '../../../externs/launcher_search_provider.js', '../../../externs/webview_tag.js',
diff --git a/ui/file_manager/gallery/js/dimmable_ui_controller.js b/ui/file_manager/gallery/js/dimmable_ui_controller.js index 5fb5f30..840e17e0 100644 --- a/ui/file_manager/gallery/js/dimmable_ui_controller.js +++ b/ui/file_manager/gallery/js/dimmable_ui_controller.js
@@ -31,9 +31,14 @@ this.isCursorInTools_ = false; /** - * @private {boolean} + * @private {Gallery.Mode|undefined} */ - this.isInAvailableMode_ = false; + this.mode_ = undefined; + + /** + * @private {Gallery.SubMode|undefined} + */ + this.subMode_ = undefined; /** * @private {boolean} @@ -87,15 +92,35 @@ DimmableUIController.MIN_OPERATION_INTERVAL = 500; // ms /** + * Returns true if this controller should be disabled. + * @param {Gallery.Mode|undefined} mode + * @param {Gallery.SubMode|undefined} subMode + * @param {boolean} loading + * @param {boolean} spokenFeedbackEnabled + * @return {boolean} + */ +DimmableUIController.shouldBeDisabled = function( + mode, subMode, loading, spokenFeedbackEnabled) { + return spokenFeedbackEnabled || + mode === undefined || + subMode === undefined || + mode === Gallery.Mode.THUMBNAIL || + (mode === Gallery.Mode.SLIDE && subMode === Gallery.SubMode.EDIT) || + (mode === Gallery.Mode.SLIDE && subMode === Gallery.SubMode.BROWSE && + loading); +}; + +/** * Sets current mode of Gallery. * @param {Gallery.Mode} mode * @param {Gallery.SubMode} subMode */ DimmableUIController.prototype.setCurrentMode = function(mode, subMode) { - this.isInAvailableMode_ = mode === Gallery.Mode.SLIDE && - (subMode === Gallery.SubMode.BROWSE || - subMode === Gallery.SubMode.SLIDESHOW); + if (this.mode_ === mode && this.subMode_ === subMode) + return; + this.mode_ = mode; + this.subMode_ = subMode; this.updateAvailability_(); }; @@ -309,9 +334,8 @@ * @private */ DimmableUIController.prototype.updateAvailability_ = function() { - var disabled = !this.isInAvailableMode_ || - this.spokenFeedbackEnabled_ || - this.loading_; + var disabled = DimmableUIController.shouldBeDisabled( + this.mode_, this.subMode_, this.loading_, this.spokenFeedbackEnabled_); if (this.disabled_ === disabled) return;
diff --git a/ui/file_manager/gallery/js/dimmable_ui_controller_unittest.html b/ui/file_manager/gallery/js/dimmable_ui_controller_unittest.html new file mode 100644 index 0000000..84009af3 --- /dev/null +++ b/ui/file_manager/gallery/js/dimmable_ui_controller_unittest.html
@@ -0,0 +1,28 @@ +<!DOCTYPE html> +<!-- Copyright 2015 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 type="text/javascript"> + var ContentMetadataProvider = {}; + var chrome = { + fileManagerPrivate: { + getStrings: function(/* ignore */) {} + }, + runtime: { + getBackgroundPage: function(/* ignore */) {} + } + }; +</script> + +<script src="../../../webui/resources/js/cr.js"></script> +<script src="../../../webui/resources/js/cr/event_target.js"></script> +<script src="../../../webui/resources/js/cr/ui/array_data_model.js"></script> +<script src="../../file_manager/common/js/async_util.js"></script> +<script src="../../file_manager/foreground/js/volume_manager_wrapper.js"></script> +<script src="gallery.js"></script> + +<script src="dimmable_ui_controller.js"></script> + +<script src="dimmable_ui_controller_unittest.js"></script>
diff --git a/ui/file_manager/gallery/js/dimmable_ui_controller_unittest.js b/ui/file_manager/gallery/js/dimmable_ui_controller_unittest.js new file mode 100644 index 0000000..5390a26 --- /dev/null +++ b/ui/file_manager/gallery/js/dimmable_ui_controller_unittest.js
@@ -0,0 +1,35 @@ +// Copyright 2015 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. + +function testShouldBeDisabled() { + // Disabled when mode is not set. + assertTrue(DimmableUIController.shouldBeDisabled( + undefined /* mode */, undefined /* subMode */, false /* loading */, + false /* spokenFeedbackEnabled */)); + + // Disabled in thumbnail mode. + assertTrue(DimmableUIController.shouldBeDisabled( + Gallery.Mode.THUMBNAIL, Gallery.SubMode.BROWSE, false /* loading */, + false /* spokenFeedbackEnabled */)); + + // Disabled in edit mode. + assertTrue(DimmableUIController.shouldBeDisabled( + Gallery.Mode.SLIDE, Gallery.SubMode.EDIT, false /* loading*/, + false /* spokenFeedbackEnabled */)); + + // Shouldn't be disabled while browsing in slide mode. + assertFalse(DimmableUIController.shouldBeDisabled( + Gallery.Mode.SLIDE, Gallery.SubMode.BROWSE, false /* loading */, + false /* spokenFeedbackEnabled */)); + + // Disabled while loading an image in slide mode. + assertTrue(DimmableUIController.shouldBeDisabled( + Gallery.Mode.SLIDE, Gallery.SubMode.BROWSE, true /* loading */, + false /* spokenFeedbackEnabled */)); + + // Disabled when spoken feedback is enabled. + assertTrue(DimmableUIController.shouldBeDisabled( + Gallery.Mode.SLIDE, Gallery.SubMode.BROWSE, false /* loading */, + true /* spokenFeedbackEnabled */)); +}
diff --git a/ui/file_manager/gallery/js/slide_mode.js b/ui/file_manager/gallery/js/slide_mode.js index 0018021..56175de 100644 --- a/ui/file_manager/gallery/js/slide_mode.js +++ b/ui/file_manager/gallery/js/slide_mode.js
@@ -977,6 +977,7 @@ */ SlideMode.prototype.loadItem_ = function( item, effect, displayCallback, loadCallback) { + this.dimmableUIController_.setLoading(true); this.showProgressBar_(item); var loadDone = this.itemLoaded_.bind(this, item, loadCallback); @@ -1009,6 +1010,7 @@ var entry = item.getEntry(); this.hideProgressBar_(); + this.dimmableUIController_.setLoading(false); if (loadType === ImageView.LoadType.ERROR) { // if we have a specific error, then display it @@ -1699,7 +1701,6 @@ * @private */ SlideMode.prototype.showProgressBar_ = function(item) { - this.dimmableUIController_.setLoading(true); this.loadingItemUrl_ = item.getEntry().toURL(); if (this.progressBarTimer_ !== 0) { @@ -1719,8 +1720,6 @@ * @private */ SlideMode.prototype.hideProgressBar_ = function() { - this.dimmableUIController_.setLoading(false); - if (this.progressBarTimer_ !== 0) { clearTimeout(this.progressBarTimer_); this.progressBarTimer_ = 0;
diff --git a/ui/gfx/geometry/size.cc b/ui/gfx/geometry/size.cc index e58bb22..7b5b522 100644 --- a/ui/gfx/geometry/size.cc +++ b/ui/gfx/geometry/size.cc
@@ -45,9 +45,13 @@ #endif int Size::GetArea() const { + return GetCheckedArea().ValueOrDie(); +} + +base::CheckedNumeric<int> Size::GetCheckedArea() const { base::CheckedNumeric<int> checked_area = width(); checked_area *= height(); - return checked_area.ValueOrDie(); + return checked_area; } void Size::Enlarge(int grow_width, int grow_height) {
diff --git a/ui/gfx/geometry/size.h b/ui/gfx/geometry/size.h index 27face1..de1df59 100644 --- a/ui/gfx/geometry/size.h +++ b/ui/gfx/geometry/size.h
@@ -9,6 +9,7 @@ #include <string> #include "base/compiler_specific.h" +#include "base/numerics/safe_math.h" #include "ui/gfx/gfx_export.h" #if defined(OS_WIN) @@ -49,6 +50,8 @@ // This call will CHECK if the area of this size would overflow int. int GetArea() const; + // Returns a checked numeric representation of the area. + base::CheckedNumeric<int> GetCheckedArea() const; void SetSize(int width, int height) { set_width(width);
diff --git a/ui/gfx/icon_util.h b/ui/gfx/icon_util.h index 1a48304..46ac3f9 100644 --- a/ui/gfx/icon_util.h +++ b/ui/gfx/icon_util.h
@@ -64,11 +64,11 @@ // default for historical reasons. enum WriteType { ATOMIC_WRITE, NORMAL_WRITE }; // The size of the large icon entries in .ico files on Windows Vista+. - static const int kLargeIconSize = 256; + enum { kLargeIconSize = 256 }; // The size of icons in the medium icons view on Windows Vista+. This is the // maximum size Windows will display an icon that does not have a 256x256 // image, even at the large or extra large icons views. - static const int kMediumIconSize = 48; + enum { kMediumIconSize = 48 }; // The dimensions for icon images in Windows icon files. All sizes are square; // that is, the value 48 means a 48x48 pixel image. Sizes are listed in
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc index 778cdd03..27c9e5ad 100644 --- a/ui/gfx/render_text.cc +++ b/ui/gfx/render_text.cc
@@ -153,10 +153,8 @@ colors.push_back(colors.back()); } - SkPoint points[2]; - points[0].iset(text_rect.x(), text_rect.y()); - points[1].iset(text_rect.right(), text_rect.y()); - + const SkPoint points[2] = { PointToSkPoint(text_rect.origin()), + PointToSkPoint(text_rect.top_right()) }; return skia::AdoptRef( SkGradientShader::CreateLinear(&points[0], &colors[0], &positions[0], colors.size(), SkShader::kClamp_TileMode));
diff --git a/ui/gfx/skia_util.cc b/ui/gfx/skia_util.cc index 696dea3..d3a1ac8 100644 --- a/ui/gfx/skia_util.cc +++ b/ui/gfx/skia_util.cc
@@ -20,10 +20,22 @@ namespace gfx { +SkPoint PointToSkPoint(const Point& point) { + return SkPoint::Make(SkIntToScalar(point.x()), SkIntToScalar(point.y())); +} + +SkIPoint PointToSkIPoint(const Point& point) { + return SkIPoint::Make(point.x(), point.y()); +} + +SkPoint PointFToSkPoint(const PointF& point) { + return SkPoint::Make(SkFloatToScalar(point.x()), SkFloatToScalar(point.y())); +} + SkRect RectToSkRect(const Rect& rect) { - SkRect r; - r.iset(rect.x(), rect.y(), rect.right(), rect.bottom()); - return r; + return SkRect::MakeXYWH( + SkIntToScalar(rect.x()), SkIntToScalar(rect.y()), + SkIntToScalar(rect.width()), SkIntToScalar(rect.height())); } SkIRect RectToSkIRect(const Rect& rect) { @@ -205,10 +217,10 @@ } void QuadFToSkPoints(const gfx::QuadF& quad, SkPoint points[4]) { - points[0] = SkPoint::Make(quad.p1().x(), quad.p1().y()); - points[1] = SkPoint::Make(quad.p2().x(), quad.p2().y()); - points[2] = SkPoint::Make(quad.p3().x(), quad.p3().y()); - points[3] = SkPoint::Make(quad.p4().x(), quad.p4().y()); + points[0] = PointFToSkPoint(quad.p1()); + points[1] = PointFToSkPoint(quad.p2()); + points[2] = PointFToSkPoint(quad.p3()); + points[3] = PointFToSkPoint(quad.p4()); } } // namespace gfx
diff --git a/ui/gfx/skia_util.h b/ui/gfx/skia_util.h index c550203..25c96d03 100644 --- a/ui/gfx/skia_util.h +++ b/ui/gfx/skia_util.h
@@ -22,12 +22,17 @@ namespace gfx { class ImageSkiaRep; +class Point; +class PointF; class Rect; class RectF; class ShadowValue; class Transform; -// Convert between Skia and gfx rect types. +// Convert between Skia and gfx types. +GFX_EXPORT SkPoint PointToSkPoint(const Point& point); +GFX_EXPORT SkIPoint PointToSkIPoint(const Point& point); +GFX_EXPORT SkPoint PointFToSkPoint(const PointF& point); GFX_EXPORT SkRect RectToSkRect(const Rect& rect); GFX_EXPORT SkIRect RectToSkIRect(const Rect& rect); GFX_EXPORT Rect SkIRectToRect(const SkIRect& rect);
diff --git a/ui/mojo/init/screen_mojo.cc b/ui/mojo/init/screen_mojo.cc index 2590b6a1..8839effb 100644 --- a/ui/mojo/init/screen_mojo.cc +++ b/ui/mojo/init/screen_mojo.cc
@@ -13,17 +13,17 @@ ScreenMojo::~ScreenMojo() {} gfx::Point ScreenMojo::GetCursorScreenPoint() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return gfx::Point(); } gfx::NativeWindow ScreenMojo::GetWindowUnderCursor() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return nullptr; } gfx::NativeWindow ScreenMojo::GetWindowAtScreenPoint(const gfx::Point& point) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return nullptr; }
diff --git a/ui/native_theme/native_theme_base.cc b/ui/native_theme/native_theme_base.cc index 18156a3..a5784e27 100644 --- a/ui/native_theme/native_theme_base.cc +++ b/ui/native_theme/native_theme_base.cc
@@ -682,9 +682,7 @@ const gfx::Rect& rect, const ButtonExtraParams& button) const { SkPaint paint; - const int kRight = rect.right(); - const int kBottom = rect.bottom(); - SkRect skrect = SkRect::MakeLTRB(rect.x(), rect.y(), kRight, kBottom); + SkRect skrect = gfx::RectToSkRect(rect); SkColor base_color = button.background_color; color_utils::HSL base_hsl; @@ -702,14 +700,13 @@ } paint.setColor(SK_ColorBLACK); - const int kLightEnd = state == kPressed ? 1 : 0; - const int kDarkEnd = !kLightEnd; - SkPoint gradient_bounds[2]; - gradient_bounds[kLightEnd].iset(rect.x(), rect.y()); - gradient_bounds[kDarkEnd].iset(rect.x(), kBottom - 1); - SkColor colors[2]; - colors[0] = light_color; - colors[1] = base_color; + SkPoint gradient_bounds[2] = { + gfx::PointToSkPoint(rect.origin()), + gfx::PointToSkPoint(rect.bottom_left() - gfx::Vector2d(0, 1)) + }; + if (state == kPressed) + std::swap(gradient_bounds[0], gradient_bounds[1]); + SkColor colors[2] = { light_color, base_color }; skia::RefPtr<SkShader> shader = skia::AdoptRef( SkGradientShader::CreateLinear(
diff --git a/ui/ozone/platform/drm/common/drm_util.cc b/ui/ozone/platform/drm/common/drm_util.cc index 5e100873..eb98ea0 100644 --- a/ui/ozone/platform/drm/common/drm_util.cc +++ b/ui/ozone/platform/drm/common/drm_util.cc
@@ -150,13 +150,19 @@ "Full aspect"); } +int ConnectorIndex(int device_index, int display_index) { + DCHECK_LT(device_index, 16); + DCHECK_LT(display_index, 16); + return ((device_index << 4) + display_index) & 0xFF; +} + } // namespace HardwareDisplayControllerInfo::HardwareDisplayControllerInfo( ScopedDrmConnectorPtr connector, - ScopedDrmCrtcPtr crtc) - : connector_(connector.Pass()), crtc_(crtc.Pass()) { -} + ScopedDrmCrtcPtr crtc, + size_t index) + : connector_(connector.Pass()), crtc_(crtc.Pass()), index_(index) {} HardwareDisplayControllerInfo::~HardwareDisplayControllerInfo() { } @@ -181,7 +187,7 @@ ScopedDrmCrtcPtr crtc(drmModeGetCrtc(fd, crtc_id)); displays.push_back( - new HardwareDisplayControllerInfo(connector.Pass(), crtc.Pass())); + new HardwareDisplayControllerInfo(connector.Pass(), crtc.Pass(), i)); } return displays.Pass(); @@ -209,10 +215,11 @@ DisplaySnapshot_Params CreateDisplaySnapshotParams( HardwareDisplayControllerInfo* info, int fd, - size_t display_index, + size_t device_index, const gfx::Point& origin) { DisplaySnapshot_Params params; - params.display_id = display_index; + int64 connector_index = ConnectorIndex(device_index, info->index()); + params.display_id = connector_index; params.origin = origin; params.physical_size = gfx::Size(info->connector()->mmWidth, info->connector()->mmHeight); @@ -228,9 +235,8 @@ static_cast<uint8_t*>(edid_blob->data), static_cast<uint8_t*>(edid_blob->data) + edid_blob->length); - if (!GetDisplayIdFromEDID(edid, display_index, ¶ms.display_id, - ¶ms.product_id)) - params.display_id = display_index; + GetDisplayIdFromEDID(edid, connector_index, ¶ms.display_id, + ¶ms.product_id); ParseOutputDeviceData(edid, nullptr, nullptr, ¶ms.display_name, nullptr, nullptr);
diff --git a/ui/ozone/platform/drm/common/drm_util.h b/ui/ozone/platform/drm/common/drm_util.h index a79700e9..ca13fa4e 100644 --- a/ui/ozone/platform/drm/common/drm_util.h +++ b/ui/ozone/platform/drm/common/drm_util.h
@@ -20,19 +20,23 @@ namespace ui { // Representation of the information required to initialize and configure a -// native display. +// native display. |index| is the position of the connection and will be +// used to generate a unique identifier for the display. class HardwareDisplayControllerInfo { public: HardwareDisplayControllerInfo(ScopedDrmConnectorPtr connector, - ScopedDrmCrtcPtr crtc); + ScopedDrmCrtcPtr crtc, + size_t index); ~HardwareDisplayControllerInfo(); drmModeConnector* connector() const { return connector_.get(); } drmModeCrtc* crtc() const { return crtc_.get(); } + size_t index() const { return index_; } private: ScopedDrmConnectorPtr connector_; ScopedDrmCrtcPtr crtc_; + size_t index_; DISALLOW_COPY_AND_ASSIGN(HardwareDisplayControllerInfo); }; @@ -47,13 +51,11 @@ DisplayMode_Params CreateDisplayModeParams(const drmModeModeInfo& mode); // |info| provides the DRM information related to the display, |fd| is the -// connection to the DRM device and |index| provides a unique identifier for the -// display. |index| will be used to generate the display id (it may be the id if -// the monitor's EDID lacks the necessary identifiers). +// connection to the DRM device. DisplaySnapshot_Params CreateDisplaySnapshotParams( HardwareDisplayControllerInfo* info, int fd, - size_t display_index, + size_t device_index, const gfx::Point& origin); int GetFourCCFormatFromBufferFormat(gfx::BufferFormat format);
diff --git a/ui/ozone/platform/drm/gpu/drm_display.cc b/ui/ozone/platform/drm/gpu/drm_display.cc index 4e949ec..2595b7a 100644 --- a/ui/ozone/platform/drm/gpu/drm_display.cc +++ b/ui/ozone/platform/drm/gpu/drm_display.cc
@@ -86,9 +86,9 @@ } DisplaySnapshot_Params DrmDisplay::Update(HardwareDisplayControllerInfo* info, - size_t display_index) { + size_t device_index) { DisplaySnapshot_Params params = - CreateDisplaySnapshotParams(info, drm_->get_fd(), display_index, origin_); + CreateDisplaySnapshotParams(info, drm_->get_fd(), device_index, origin_); crtc_ = info->crtc()->crtc_id; connector_ = info->connector()->connector_id; display_id_ = params.display_id;
diff --git a/ui/ozone/platform/drm/gpu/drm_display.h b/ui/ozone/platform/drm/gpu/drm_display.h index 40cd3439..7d3f1875 100644 --- a/ui/ozone/platform/drm/gpu/drm_display.h +++ b/ui/ozone/platform/drm/gpu/drm_display.h
@@ -35,7 +35,7 @@ const std::vector<drmModeModeInfo>& modes() const { return modes_; } DisplaySnapshot_Params Update(HardwareDisplayControllerInfo* info, - size_t display_index); + size_t device_index); bool Configure(const drmModeModeInfo* mode, const gfx::Point& origin); bool GetHDCPState(HDCPState* state);
diff --git a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc index 7d7bba4..4a678d9 100644 --- a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc +++ b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
@@ -70,8 +70,7 @@ std::vector<DisplaySnapshot_Params> params_list; const DrmDeviceVector& devices = drm_device_manager_->GetDrmDevices(); - // Unique identifier used to create the display id. - size_t index = 0; + size_t device_index = 0; for (const auto& drm : devices) { ScopedVector<HardwareDisplayControllerInfo> display_infos = GetAvailableDisplayControllerInfos(drm->get_fd()); @@ -86,9 +85,10 @@ } else { displays_.push_back(new DrmDisplay(screen_manager_, drm)); } - - params_list.push_back(displays_.back()->Update(display_info, index++)); + params_list.push_back( + displays_.back()->Update(display_info, device_index)); } + device_index++; } NotifyScreenManager(displays_.get(), old_displays.get());
diff --git a/ui/ozone/platform/drm/host/drm_display_host_manager.cc b/ui/ozone/platform/drm/host/drm_display_host_manager.cc index 41db371..0809e04 100644 --- a/ui/ozone/platform/drm/host/drm_display_host_manager.cc +++ b/ui/ozone/platform/drm/host/drm_display_host_manager.cc
@@ -141,7 +141,7 @@ for (size_t i = 0; i < display_infos.size(); ++i) { displays_.push_back(new DrmDisplayHost( proxy_, CreateDisplaySnapshotParams(display_infos[i], - primary_drm_device_handle_->fd(), i, + primary_drm_device_handle_->fd(), 0, gfx::Point()), true /* is_dummy */)); }
diff --git a/ui/views/mus/BUILD.gn b/ui/views/mus/BUILD.gn index 0a8ee1977..fa6741f 100644 --- a/ui/views/mus/BUILD.gn +++ b/ui/views/mus/BUILD.gn
@@ -47,7 +47,6 @@ "//mojo/converters/input_events", "//mojo/converters/network", "//mojo/converters/surfaces", - "//third_party/mojo/src/mojo/public/c/gles2", "//third_party/mojo/src/mojo/public/cpp/bindings", "//third_party/icu", "//ui/aura",
diff --git a/ui/views/mus/native_widget_mus.cc b/ui/views/mus/native_widget_mus.cc index 01f63fd..b035a18 100644 --- a/ui/views/mus/native_widget_mus.cc +++ b/ui/views/mus/native_widget_mus.cc
@@ -68,10 +68,12 @@ NativeWidgetMus::NativeWidgetMus(internal::NativeWidgetDelegate* delegate, mojo::Shell* shell, - mus::Window* window) + mus::Window* window, + mus::mojom::SurfaceType surface_type) : window_(window), shell_(shell), native_widget_delegate_(delegate), + surface_type_(surface_type), show_state_before_fullscreen_(mus::mojom::SHOW_STATE_RESTORED), content_(new aura::Window(this)) {} NativeWidgetMus::~NativeWidgetMus() {} @@ -92,7 +94,8 @@ // NativeWidgetMus, internal::NativeWidgetPrivate implementation: void NativeWidgetMus::InitNativeWidget(const Widget::InitParams& params) { - window_tree_host_.reset(new WindowTreeHostMus(shell_, window_)); + window_tree_host_.reset( + new WindowTreeHostMus(shell_, window_, surface_type_)); window_tree_host_->InitHost(); focus_client_.reset(new wm::FocusController(new FocusRulesImpl)); @@ -109,27 +112,30 @@ content_->SetType(ui::wm::WINDOW_TYPE_NORMAL); content_->Init(ui::LAYER_TEXTURED); + content_->SetTransparent(true); + content_->SetFillsBoundsCompletely(false); + window_tree_host_->window()->AddChild(content_); // TODO(beng): much else, see [Desktop]NativeWidgetAura. } NonClientFrameView* NativeWidgetMus::CreateNonClientFrameView() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return nullptr; } bool NativeWidgetMus::ShouldUseNativeFrame() const { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return false; } bool NativeWidgetMus::ShouldWindowContentsBeTransparent() const { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return true; } void NativeWidgetMus::FrameTypeChanged() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } Widget* NativeWidgetMus::GetWidget() { @@ -137,7 +143,7 @@ } const Widget* NativeWidgetMus::GetWidget() const { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return native_widget_delegate_->AsWidget(); } @@ -162,26 +168,26 @@ } void NativeWidgetMus::ReorderNativeViews() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::ViewRemoved(View* view) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::SetNativeWindowProperty(const char* name, void* value) { // TODO(beng): push properties to mus::Window. - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void* NativeWidgetMus::GetNativeWindowProperty(const char* name) const { // TODO(beng): pull properties to mus::Window. - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return nullptr; } TooltipManager* NativeWidgetMus::GetTooltipManager() const { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return nullptr; } @@ -209,36 +215,36 @@ void NativeWidgetMus::GetWindowPlacement( gfx::Rect* bounds, ui::WindowShowState* maximized) const { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } bool NativeWidgetMus::SetWindowTitle(const base::string16& title) { // TODO(beng): push title to window manager. - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return false; } void NativeWidgetMus::SetWindowIcons(const gfx::ImageSkia& window_icon, const gfx::ImageSkia& app_icon) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::InitModalType(ui::ModalType modal_type) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } gfx::Rect NativeWidgetMus::GetWindowBoundsInScreen() const { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return gfx::Rect(); } gfx::Rect NativeWidgetMus::GetClientAreaBoundsInScreen() const { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return gfx::Rect(); } gfx::Rect NativeWidgetMus::GetRestoredBounds() const { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return gfx::Rect(); } @@ -251,27 +257,27 @@ } void NativeWidgetMus::StackAbove(gfx::NativeView native_view) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::StackAtTop() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::StackBelow(gfx::NativeView native_view) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::SetShape(SkRegion* shape) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::Close() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::CloseNow() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::Show() { @@ -285,7 +291,7 @@ void NativeWidgetMus::ShowMaximizedWithBounds( const gfx::Rect& restored_bounds) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::ShowWithWindowState(ui::WindowShowState state) { @@ -294,34 +300,34 @@ } bool NativeWidgetMus::IsVisible() const { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return true; } void NativeWidgetMus::Activate() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::Deactivate() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } bool NativeWidgetMus::IsActive() const { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return true; } void NativeWidgetMus::SetAlwaysOnTop(bool always_on_top) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } bool NativeWidgetMus::IsAlwaysOnTop() const { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return false; } void NativeWidgetMus::SetVisibleOnAllWorkspaces(bool always_visible) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::Maximize() { @@ -358,15 +364,15 @@ } void NativeWidgetMus::SetOpacity(unsigned char opacity) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::SetUseDragFrame(bool use_drag_frame) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::FlashFrame(bool flash_frame) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::RunShellDrag( @@ -375,28 +381,28 @@ const gfx::Point& location, int operation, ui::DragDropTypes::DragEventSource source) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::SchedulePaintInRect(const gfx::Rect& rect) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::SetCursor(gfx::NativeCursor cursor) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } bool NativeWidgetMus::IsMouseEventsEnabled() const { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return true; } void NativeWidgetMus::ClearNativeFocus() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } gfx::Rect NativeWidgetMus::GetWorkAreaBoundsInScreen() const { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return gfx::Rect(); } @@ -404,26 +410,26 @@ const gfx::Vector2d& drag_offset, Widget::MoveLoopSource source, Widget::MoveLoopEscapeBehavior escape_behavior) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return Widget::MOVE_LOOP_CANCELED; } void NativeWidgetMus::EndMoveLoop() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::SetVisibilityChangedAnimationsEnabled(bool value) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::SetVisibilityAnimationDuration( const base::TimeDelta& duration) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::SetVisibilityAnimationTransition( Widget::VisibilityTransition transition) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } ui::NativeTheme* NativeWidgetMus::GetNativeTheme() const { @@ -431,20 +437,20 @@ } void NativeWidgetMus::OnRootViewLayout() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } bool NativeWidgetMus::IsTranslucentWindowOpacitySupported() const { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return true; } void NativeWidgetMus::OnSizeConstraintsChanged() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void NativeWidgetMus::RepostNativeEvent(gfx::NativeEvent native_event) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } ////////////////////////////////////////////////////////////////////////////////
diff --git a/ui/views/mus/native_widget_mus.h b/ui/views/mus/native_widget_mus.h index 916d37d..61df1cc 100644 --- a/ui/views/mus/native_widget_mus.h +++ b/ui/views/mus/native_widget_mus.h
@@ -43,7 +43,8 @@ public: NativeWidgetMus(internal::NativeWidgetDelegate* delegate, mojo::Shell* shell, - mus::Window* window); + mus::Window* window, + mus::mojom::SurfaceType surface_type); ~NativeWidgetMus() override; private: @@ -167,6 +168,8 @@ internal::NativeWidgetDelegate* native_widget_delegate_; + const mus::mojom::SurfaceType surface_type_; + mus::mojom::ShowState show_state_before_fullscreen_; // Aura configuration.
diff --git a/ui/views/mus/native_widget_view_manager.cc b/ui/views/mus/native_widget_view_manager.cc index 89704391..5b3b14b 100644 --- a/ui/views/mus/native_widget_view_manager.cc +++ b/ui/views/mus/native_widget_view_manager.cc
@@ -94,7 +94,8 @@ mojo::Shell* shell, mus::Window* window) : NativeWidgetAura(delegate), window_(window) { - window_tree_host_.reset(new WindowTreeHostMus(shell, window_)); + window_tree_host_.reset( + new WindowTreeHostMus(shell, window_, mus::mojom::SURFACE_TYPE_DEFAULT)); window_tree_host_->InitHost(); focus_client_.reset(new wm::FocusController(new FocusRulesImpl));
diff --git a/ui/views/mus/surface_binding.cc b/ui/views/mus/surface_binding.cc index c53eb4e..2c6220b 100644 --- a/ui/views/mus/surface_binding.cc +++ b/ui/views/mus/surface_binding.cc
@@ -44,7 +44,9 @@ static PerConnectionState* Get(mojo::Shell* shell, mus::WindowTreeConnection* connection); - scoped_ptr<cc::OutputSurface> CreateOutputSurface(mus::Window* window); + scoped_ptr<cc::OutputSurface> CreateOutputSurface( + mus::Window* window, + mus::mojom::SurfaceType type); private: typedef std::map<mus::WindowTreeConnection*, PerConnectionState*> @@ -91,7 +93,9 @@ } scoped_ptr<cc::OutputSurface> -SurfaceBinding::PerConnectionState::CreateOutputSurface(mus::Window* window) { +SurfaceBinding::PerConnectionState::CreateOutputSurface( + mus::Window* window, + mus::mojom::SurfaceType surface_type) { // TODO(sky): figure out lifetime here. Do I need to worry about the return // value outliving this? mus::mojom::CommandBufferPtr cb; @@ -99,8 +103,8 @@ scoped_refptr<cc::ContextProvider> context_provider( new mus::ContextProvider(cb.PassInterface().PassHandle())); - return make_scoped_ptr( - new mus::OutputSurface(context_provider, window->RequestSurface())); + return make_scoped_ptr(new mus::OutputSurface( + context_provider, window->RequestSurface(surface_type))); } SurfaceBinding::PerConnectionState::PerConnectionState( @@ -131,14 +135,17 @@ // SurfaceBinding -------------------------------------------------------------- -SurfaceBinding::SurfaceBinding(mojo::Shell* shell, mus::Window* window) +SurfaceBinding::SurfaceBinding(mojo::Shell* shell, + mus::Window* window, + mus::mojom::SurfaceType surface_type) : window_(window), + surface_type_(surface_type), state_(PerConnectionState::Get(shell, window->connection())) {} SurfaceBinding::~SurfaceBinding() {} scoped_ptr<cc::OutputSurface> SurfaceBinding::CreateOutputSurface() { - return state_->CreateOutputSurface(window_); + return state_->CreateOutputSurface(window_, surface_type_); } } // namespace views
diff --git a/ui/views/mus/surface_binding.h b/ui/views/mus/surface_binding.h index 3fd0c60..3ae2ed9 100644 --- a/ui/views/mus/surface_binding.h +++ b/ui/views/mus/surface_binding.h
@@ -7,6 +7,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "components/mus/public/interfaces/window_tree.mojom.h" namespace cc { class OutputSurface; @@ -25,11 +26,13 @@ // SurfaceBinding is responsible for managing the connections necessary to // bind a Window to the surfaces service. // Internally SurfaceBinding manages one connection (and related structures) per -// ViewTreeConnection. That is, all Views from a particular ViewTreeConnection -// share the same connection. +// WindowTree. That is, all Windows from a particular WindowTree share the same +// connection. class SurfaceBinding { public: - SurfaceBinding(mojo::Shell* shell, mus::Window* window); + SurfaceBinding(mojo::Shell* shell, + mus::Window* window, + mus::mojom::SurfaceType surface_type); ~SurfaceBinding(); // Creates an OutputSurface that renders to the Window supplied to the @@ -39,8 +42,8 @@ private: class PerConnectionState; - mojo::Shell* shell_; mus::Window* window_; + const mus::mojom::SurfaceType surface_type_; scoped_refptr<PerConnectionState> state_; DISALLOW_COPY_AND_ASSIGN(SurfaceBinding);
diff --git a/ui/views/mus/surface_context_factory.cc b/ui/views/mus/surface_context_factory.cc index 4ed3da6..298f1fd1 100644 --- a/ui/views/mus/surface_context_factory.cc +++ b/ui/views/mus/surface_context_factory.cc
@@ -25,37 +25,40 @@ }; } -SurfaceContextFactory::SurfaceContextFactory(mojo::Shell* shell, - mus::Window* window) - : surface_binding_(shell, window), next_surface_id_namespace_(1u) {} +SurfaceContextFactory::SurfaceContextFactory( + mojo::Shell* shell, + mus::Window* window, + mus::mojom::SurfaceType surface_type) + : surface_binding_(shell, window, surface_type), + next_surface_id_namespace_(1u) {} SurfaceContextFactory::~SurfaceContextFactory() {} void SurfaceContextFactory::CreateOutputSurface( base::WeakPtr<ui::Compositor> compositor) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); compositor->SetOutputSurface(surface_binding_.CreateOutputSurface()); } scoped_ptr<ui::Reflector> SurfaceContextFactory::CreateReflector( ui::Compositor* mirroed_compositor, ui::Layer* mirroring_layer) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return make_scoped_ptr(new FakeReflector); } void SurfaceContextFactory::RemoveReflector(ui::Reflector* reflector) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } scoped_refptr<cc::ContextProvider> SurfaceContextFactory::SharedMainThreadContextProvider() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return nullptr; } void SurfaceContextFactory::RemoveCompositor(ui::Compositor* compositor) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } bool SurfaceContextFactory::DoesCreateTestContexts() { @@ -69,7 +72,7 @@ } cc::SharedBitmapManager* SurfaceContextFactory::GetSharedBitmapManager() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return nullptr; } @@ -90,7 +93,7 @@ void SurfaceContextFactory::ResizeDisplay(ui::Compositor* compositor, const gfx::Size& size) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } } // namespace views
diff --git a/ui/views/mus/surface_context_factory.h b/ui/views/mus/surface_context_factory.h index e20e83ac..c9f71bb 100644 --- a/ui/views/mus/surface_context_factory.h +++ b/ui/views/mus/surface_context_factory.h
@@ -7,6 +7,7 @@ #include "components/mus/gles2/mojo_gpu_memory_buffer_manager.h" #include "components/mus/gles2/raster_thread_helper.h" +#include "components/mus/public/interfaces/window_tree.mojom.h" #include "ui/compositor/compositor.h" #include "ui/views/mus/surface_binding.h" @@ -22,7 +23,9 @@ class SurfaceContextFactory : public ui::ContextFactory { public: - SurfaceContextFactory(mojo::Shell* shell, mus::Window* window); + SurfaceContextFactory(mojo::Shell* shell, + mus::Window* window, + mus::mojom::SurfaceType surface_type); ~SurfaceContextFactory() override; private:
diff --git a/ui/views/mus/window_manager_connection.cc b/ui/views/mus/window_manager_connection.cc index c57b20e..fbcae827 100644 --- a/ui/views/mus/window_manager_connection.cc +++ b/ui/views/mus/window_manager_connection.cc
@@ -128,7 +128,8 @@ internal::NativeWidgetDelegate* delegate) { return new NativeWidgetMus( delegate, app_->shell(), - CreateWindow(std::map<std::string, std::vector<uint8_t>>())); + CreateWindow(std::map<std::string, std::vector<uint8_t>>()), + mus::mojom::SURFACE_TYPE_DEFAULT); } void WindowManagerConnection::OnBeforeWidgetInit(
diff --git a/ui/views/mus/window_tree_host_mus.cc b/ui/views/mus/window_tree_host_mus.cc index aef5df5..fd7e1f1 100644 --- a/ui/views/mus/window_tree_host_mus.cc +++ b/ui/views/mus/window_tree_host_mus.cc
@@ -29,11 +29,14 @@ //////////////////////////////////////////////////////////////////////////////// // WindowTreeHostMus, public: -WindowTreeHostMus::WindowTreeHostMus(mojo::Shell* shell, mus::Window* window) +WindowTreeHostMus::WindowTreeHostMus(mojo::Shell* shell, + mus::Window* window, + mus::mojom::SurfaceType surface_type) : mus_window_(window) { mus_window_->AddObserver(this); - context_factory_.reset(new SurfaceContextFactory(shell, mus_window_)); + context_factory_.reset( + new SurfaceContextFactory(shell, mus_window_, surface_type)); // WindowTreeHost creates the compositor using the ContextFactory from // aura::Env. Install |context_factory_| there so that |context_factory_| is // picked up. @@ -41,6 +44,7 @@ aura::Env::GetInstance()->context_factory(); aura::Env::GetInstance()->set_context_factory(context_factory_.get()); CreateCompositor(); + compositor()->SetHostHasTransparentBackground(true); OnAcceleratedWidgetAvailable(); aura::Env::GetInstance()->set_context_factory(default_context_factory); DCHECK_EQ(context_factory_.get(), compositor()->context_factory()); @@ -95,23 +99,23 @@ } void WindowTreeHostMus::SetCapture() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void WindowTreeHostMus::ReleaseCapture() { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void WindowTreeHostMus::SetCursorNative(gfx::NativeCursor cursor) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void WindowTreeHostMus::MoveCursorToNative(const gfx::Point& location) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } void WindowTreeHostMus::OnCursorVisibilityChangedNative(bool show) { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); } ////////////////////////////////////////////////////////////////////////////////
diff --git a/ui/views/mus/window_tree_host_mus.h b/ui/views/mus/window_tree_host_mus.h index f1af068..6f4d9ad 100644 --- a/ui/views/mus/window_tree_host_mus.h +++ b/ui/views/mus/window_tree_host_mus.h
@@ -30,7 +30,9 @@ class WindowTreeHostMus : public aura::WindowTreeHost, public mus::WindowObserver { public: - WindowTreeHostMus(mojo::Shell* shell, mus::Window* window); + WindowTreeHostMus(mojo::Shell* shell, + mus::Window* window, + mus::mojom::SurfaceType surface_type); ~WindowTreeHostMus() override; mus::Window* mus_window() { return mus_window_; }
diff --git a/ui/webui/resources/js/polymer_config.js b/ui/webui/resources/js/polymer_config.js index 3b20eae..6b432d9 100644 --- a/ui/webui/resources/js/polymer_config.js +++ b/ui/webui/resources/js/polymer_config.js
@@ -2,4 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -Polymer = {dom: 'shadow'}; +if (typeof Polymer == 'undefined') + Polymer = {dom: 'shadow'}; +else + console.error('Polymer is already defined.');