Merge from Chromium at DEPS revision 37.0.2062.52
This commit was generated by merge_to_master.py.
Change-Id: Id79fecbf12a48cc7a1916e0a244695cbc1d298cf
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 def834f..8c5a157 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -2385,8 +2385,10 @@
// Return true if the GeolocationPermissionAPI should be used.
@CalledByNative
private boolean useLegacyGeolocationPermissionAPI() {
- // TODO (michaelbai): Need to verify whether this is correct when release.
- return mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.KITKAT;
+ // Always return true since we are not ready to swap the geolocation yet.
+ // TODO: If we decide not to migrate the geolocation, there are some unreachable
+ // code need to remove. http://crbug.com/396184.
+ return true;
}
//--------------------------------------------------------------------------------------------
diff --git a/apps/app_window.cc b/apps/app_window.cc
index 814d2e0..427cdc6 100644
--- a/apps/app_window.cc
+++ b/apps/app_window.cc
@@ -245,7 +245,8 @@
has_been_shown_(false),
can_send_events_(false),
is_hidden_(false),
- cached_always_on_top_(false) {
+ cached_always_on_top_(false),
+ requested_transparent_background_(false) {
extensions::ExtensionsBrowserClient* client =
extensions::ExtensionsBrowserClient::Get();
CHECK(!client->IsGuestSession(context) || context->IsOffTheRecord())
@@ -284,6 +285,8 @@
if (new_params.state == ui::SHOW_STATE_FULLSCREEN)
new_params.always_on_top = false;
+ requested_transparent_background_ = new_params.transparent_background;
+
native_app_window_.reset(delegate_->CreateNativeAppWindow(this, new_params));
// Prevent the browser process from shutting down while this window exists.
@@ -751,6 +754,9 @@
properties->SetBoolean("maximized", native_app_window_->IsMaximized());
properties->SetBoolean("alwaysOnTop", IsAlwaysOnTop());
properties->SetBoolean("hasFrameColor", native_app_window_->HasFrameColor());
+ properties->SetBoolean("alphaEnabled",
+ requested_transparent_background_ &&
+ native_app_window_->CanHaveAlphaEnabled());
// These properties are undocumented and are to enable testing. Alpha is
// removed to
diff --git a/apps/app_window.h b/apps/app_window.h
index f2e0e98..216ee3c 100644
--- a/apps/app_window.h
+++ b/apps/app_window.h
@@ -362,6 +362,11 @@
// app.
void WindowEventsReady();
+ // Whether the app window wants a transparent background.
+ bool requested_transparent_background() const {
+ return requested_transparent_background_;
+ }
+
protected:
virtual ~AppWindow();
@@ -558,6 +563,9 @@
// taskbar.
bool cached_always_on_top_;
+ // Whether |transparent_background| was set in the CreateParams.
+ bool requested_transparent_background_;
+
DISALLOW_COPY_AND_ASSIGN(AppWindow);
};
diff --git a/apps/ui/native_app_window.h b/apps/ui/native_app_window.h
index cde4c1d..fd0cc26 100644
--- a/apps/ui/native_app_window.h
+++ b/apps/ui/native_app_window.h
@@ -87,6 +87,10 @@
virtual void SetContentSizeConstraints(const gfx::Size& min_size,
const gfx::Size& max_size) = 0;
+ // Returns false if the underlying native window ignores alpha transparency
+ // when compositing.
+ virtual bool CanHaveAlphaEnabled() const = 0;
+
virtual ~NativeAppWindow() {}
};
diff --git a/apps/ui/views/native_app_window_views.cc b/apps/ui/views/native_app_window_views.cc
index 62b941d..da84d8a 100644
--- a/apps/ui/views/native_app_window_views.cc
+++ b/apps/ui/views/native_app_window_views.cc
@@ -27,14 +27,12 @@
web_view_(NULL),
widget_(NULL),
frameless_(false),
- transparent_background_(false),
resizable_(false) {}
void NativeAppWindowViews::Init(AppWindow* app_window,
const AppWindow::CreateParams& create_params) {
app_window_ = app_window;
frameless_ = create_params.frame == AppWindow::FRAME_NONE;
- transparent_background_ = create_params.transparent_background;
resizable_ = create_params.resizable;
size_constraints_.set_minimum_size(
create_params.GetContentMinimumSize(gfx::Insets()));
@@ -53,6 +51,10 @@
web_view_->SetWebContents(NULL);
}
+void NativeAppWindowViews::OnCanHaveAlphaEnabledChanged() {
+ app_window_->OnNativeWindowChanged();
+}
+
void NativeAppWindowViews::InitializeWindow(
AppWindow* app_window,
const AppWindow::CreateParams& create_params) {
@@ -260,7 +262,8 @@
void NativeAppWindowViews::RenderViewCreated(
content::RenderViewHost* render_view_host) {
- if (transparent_background_) {
+ if (app_window_->requested_transparent_background() &&
+ CanHaveAlphaEnabled()) {
content::RenderWidgetHostView* view = render_view_host->GetView();
DCHECK(view);
view->SetBackgroundOpaque(false);
@@ -398,4 +401,8 @@
size_constraints_.set_maximum_size(max_size);
}
+bool NativeAppWindowViews::CanHaveAlphaEnabled() const {
+ return widget_->IsTranslucentWindowOpacitySupported();
+}
+
} // namespace apps
diff --git a/apps/ui/views/native_app_window_views.h b/apps/ui/views/native_app_window_views.h
index bdebfde..917feca 100644
--- a/apps/ui/views/native_app_window_views.h
+++ b/apps/ui/views/native_app_window_views.h
@@ -52,6 +52,9 @@
void Init(AppWindow* app_window,
const AppWindow::CreateParams& create_params);
+ // Signal that CanHaveTransparentBackground has changed.
+ void OnCanHaveAlphaEnabledChanged();
+
views::Widget* widget() { return widget_; }
void set_window_for_testing(views::Widget* window) { widget_ = window; }
@@ -156,6 +159,7 @@
virtual gfx::Size GetContentMaximumSize() const OVERRIDE;
virtual void SetContentSizeConstraints(const gfx::Size& min_size,
const gfx::Size& max_size) OVERRIDE;
+ virtual bool CanHaveAlphaEnabled() const OVERRIDE;
// web_modal::WebContentsModalDialogHost implementation.
virtual gfx::NativeView GetHostView() const OVERRIDE;
@@ -177,7 +181,6 @@
scoped_ptr<SkRegion> draggable_region_;
bool frameless_;
- bool transparent_background_;
bool resizable_;
apps::SizeConstraints size_constraints_;
diff --git a/base/debug/dump_without_crashing.h b/base/debug/dump_without_crashing.h
index c46f446..b8ed174 100644
--- a/base/debug/dump_without_crashing.h
+++ b/base/debug/dump_without_crashing.h
@@ -14,6 +14,9 @@
namespace debug {
// Handler to silently dump the current process without crashing.
+// Before calling this function, call SetDumpWithoutCrashingFunction to pass a
+// function pointer, typically chrome!DumpProcessWithoutCrash. See example code
+// in chrome_main.cc that does this for chrome.dll.
BASE_EXPORT void DumpWithoutCrashing();
// Sets a function that'll be invoked to dump the current process when
diff --git a/build/util/LASTCHANGE b/build/util/LASTCHANGE
index af4f2f7..2627e6a 100644
--- a/build/util/LASTCHANGE
+++ b/build/util/LASTCHANGE
@@ -1 +1 @@
-LASTCHANGE=284645
+LASTCHANGE=286032
diff --git a/build/util/LASTCHANGE.blink b/build/util/LASTCHANGE.blink
index e37d81a..835ce02 100644
--- a/build/util/LASTCHANGE.blink
+++ b/build/util/LASTCHANGE.blink
@@ -1 +1 @@
-LASTCHANGE=178617
+LASTCHANGE=179070
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index e06cadf..6dd4b3e 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2090,6 +2090,7 @@
UpdateInnerViewportContainerSize();
client_->OnCanDrawStateChanged(CanDraw());
SetFullRootLayerDamage();
+ active_tree_->set_needs_update_draw_properties();
}
void LayerTreeHostImpl::SetOverdrawBottomHeight(float overdraw_bottom_height) {
diff --git a/chrome/VERSION b/chrome/VERSION
index 5d4cbde..ddf8350 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
MAJOR=37
MINOR=0
BUILD=2062
-PATCH=34
+PATCH=52
diff --git a/chrome/android/java/res/drawable/btn_infobar_blue.xml b/chrome/android/java/res/drawable/btn_infobar_blue.xml
index 73e7e0b..dafefd5 100644
--- a/chrome/android/java/res/drawable/btn_infobar_blue.xml
+++ b/chrome/android/java/res/drawable/btn_infobar_blue.xml
@@ -11,13 +11,13 @@
android:state_selected="false">
<shape>
<solid android:color="@color/infobar_accent_blue" />
- <corners android:radius="1dp" />
+ <corners android:radius="2dp" />
</shape>
</item>
<item>
<shape>
<solid android:color="@color/infobar_accent_blue_pressed" />
- <corners android:radius="1dp" />
+ <corners android:radius="2dp" />
</shape>
</item>
</selector>
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index 9a54044..0f27a76 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -31,7 +31,7 @@
<!-- Text size of the infobar message. -->
<dimen name="infobar_text_size">16sp</dimen>
<!-- Text size of text inside infobar buttons. -->
- <dimen name="infobar_button_text_size">12sp</dimen>
+ <dimen name="infobar_button_text_size">14sp</dimen>
<!-- Minimum width of an infobar. -->
<dimen name="infobar_min_width">220dp</dimen>
<!-- Margin between items in an infobar. -->
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/NewTabPagePrefs.java b/chrome/android/java/src/org/chromium/chrome/browser/NewTabPagePrefs.java
index f2fdf3f..21e80f8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/NewTabPagePrefs.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/NewTabPagePrefs.java
@@ -31,67 +31,90 @@
}
/**
- * Set snapshot document list collapsed or uncollapsed state in preferences.
- * @param isCollapsed {@code True} Whether we want the snapshot documents list to be collapsed.
+ * Sets whether the list of currently open tabs is collapsed (vs expanded) on the Recent Tabs
+ * page.
+ * @param isCollapsed Whether we want the currently open tabs list to be collapsed.
+ */
+ public void setCurrentlyOpenTabsCollapsed(boolean isCollapsed) {
+ nativeSetCurrentlyOpenTabsCollapsed(mNativeNewTabPagePrefs, isCollapsed);
+ }
+
+ /**
+ * Gets whether the list of currently open tabs is collapsed (vs expanded) on Recent Tabs page.
+ * @return Whether the list of currently open tabs is collapsed (vs expanded) on
+ * the Recent Tabs page.
+ */
+ public boolean getCurrentlyOpenTabsCollapsed() {
+ return nativeGetCurrentlyOpenTabsCollapsed(mNativeNewTabPagePrefs);
+ }
+
+ /**
+ * Sets whether the list of snapshot documents is collapsed (vs expanded) on the Recent Tabs
+ * page.
+ * @param isCollapsed Whether we want the snapshot documents list to be collapsed.
*/
public void setSnapshotDocumentCollapsed(boolean isCollapsed) {
nativeSetSnapshotDocumentCollapsed(mNativeNewTabPagePrefs, isCollapsed);
}
/**
- * Get the snapshot document list collapsed or uncollapsed state in preferences.
- * @return {@code True} Whether the snapshot documnets list is collapsed.
+ * Gets whether the list of snapshot documents is collapsed (vs expanded) on
+ * the Recent Tabs page.
+ * @return Whether the list of snapshot documents is collapsed (vs expanded) on
+ * the Recent Tabs page.
*/
public boolean getSnapshotDocumentCollapsed() {
return nativeGetSnapshotDocumentCollapsed(mNativeNewTabPagePrefs);
}
/**
- * Set recently closed tabs list collapsed or uncollapsed state in preferences.
- * @param isCollapsed {@code True} Whether we want the recently closed tabs list to be
- * collapsed.
+ * Sets whether the list of recently closed tabs is collapsed (vs expanded) on the Recent Tabs
+ * page.
+ * @param isCollapsed Whether we want the recently closed tabs list to be collapsed.
*/
public void setRecentlyClosedTabsCollapsed(boolean isCollapsed) {
nativeSetRecentlyClosedTabsCollapsed(mNativeNewTabPagePrefs, isCollapsed);
}
/**
- * Get the recently closed document list collapsed or uncollapsed state in preferences.
- * @return {@code True} Whether the recently closed list is collapsed.
+ * Gets whether the list of recently closed tabs is collapsed (vs expanded) on
+ * the Recent Tabs page.
+ * @return Whether the list of recently closed tabs is collapsed (vs expanded) on
+ * the Recent Tabs page.
*/
public boolean getRecentlyClosedTabsCollapsed() {
return nativeGetRecentlyClosedTabsCollapsed(mNativeNewTabPagePrefs);
}
/**
- * Set sync promo collapsed or uncollapsed state in preferences.
- * @param isCollapsed {@code True} Whether we want the sync promo to be collapsed.
+ * Sets whether sync promo is collapsed (vs expanded) on the Recent Tabs page.
+ * @param isCollapsed Whether we want the sync promo to be collapsed.
*/
public void setSyncPromoCollapsed(boolean isCollapsed) {
nativeSetSyncPromoCollapsed(mNativeNewTabPagePrefs, isCollapsed);
}
/**
- * Get the sync promo collapsed or uncollapsed state in preferences.
- * @return {@code True} Whether the snapshot documnets list is collapsed.
+ * Gets whether sync promo is collapsed (vs expanded) on the Recent Tabs page.
+ * @return Whether the sync promo is collapsed (vs expanded) on the Recent Tabs page.
*/
public boolean getSyncPromoCollapsed() {
return nativeGetSyncPromoCollapsed(mNativeNewTabPagePrefs);
}
/**
- * Set the given session collapsed or uncollapsed in preferences.
- * @param session Session to set collapsed or uncollapsed.
- * @param isCollapsed {@code True} iff we want the session to be collapsed.
+ * Sets whether the given foreign session is collapsed (vs expanded) on the Recent Tabs page.
+ * @param session Session to set collapsed or expanded.
+ * @param isCollapsed Whether we want the foreign session to be collapsed.
*/
public void setForeignSessionCollapsed(ForeignSession session, boolean isCollapsed) {
nativeSetForeignSessionCollapsed(mNativeNewTabPagePrefs, session.tag, isCollapsed);
}
/**
- * Get the given session collapsed or uncollapsed state in preferences.
+ * Gets whether the given foreign session is collapsed (vs expanded) on the Recent Tabs page.
* @param session Session to fetch collapsed state.
- * @return {@code True} if the session is collapsed, false if expanded.
+ * @return Whether the given foreign session is collapsed (vs expanded) on the Recent Tabs page.
*/
public boolean getForeignSessionCollapsed(ForeignSession session) {
return nativeGetForeignSessionCollapsed(mNativeNewTabPagePrefs, session.tag);
@@ -99,6 +122,10 @@
private static native long nativeInit(Profile profile);
private static native void nativeDestroy(long nativeNewTabPagePrefs);
+ private static native void nativeSetCurrentlyOpenTabsCollapsed(
+ long nativeNewTabPagePrefs, boolean isCollapsed);
+ private static native boolean nativeGetCurrentlyOpenTabsCollapsed(
+ long nativeNewTabPagePrefs);
private static native void nativeSetSnapshotDocumentCollapsed(
long nativeNewTabPagePrefs, boolean isCollapsed);
private static native boolean nativeGetSnapshotDocumentCollapsed(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
index 6bf7f43..d31dcf4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
@@ -206,7 +206,11 @@
}
private void setupImageButton(ImageButton button, final MenuItem item) {
+ // Store and recover the level of image as button.setimageDrawable
+ // resets drawable to default level.
+ int currentLevel = item.getIcon().getLevel();
button.setImageDrawable(item.getIcon());
+ item.getIcon().setLevel(currentLevel);
button.setContentDescription(item.getTitle());
button.setEnabled(item.isEnabled());
button.setFocusable(item.isEnabled());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCheckBox.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCheckBox.java
index 4cf4f85..fdd246a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCheckBox.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCheckBox.java
@@ -14,6 +14,8 @@
* A check box used to determine if a page should always be translated.
*/
public class TranslateCheckBox extends CheckBox implements OnCheckedChangeListener {
+ private static final int TEXT_SIZE_SP = 13;
+
private final SubPanelListener mListener;
private final TranslateOptions mOptions;
@@ -24,6 +26,8 @@
setId(R.id.infobar_extra_check);
setText(context.getString(R.string.translate_always_text, mOptions.sourceLanguage()));
+ setTextColor(context.getResources().getColor(R.color.infobar_text));
+ setTextSize(TEXT_SIZE_SP);
setChecked(mOptions.alwaysTranslateLanguageState());
setOnCheckedChangeListener(this);
}
diff --git a/chrome/app/chrome_main.cc b/chrome/app/chrome_main.cc
index c1cf145..80cd0fb 100644
--- a/chrome/app/chrome_main.cc
+++ b/chrome/app/chrome_main.cc
@@ -7,7 +7,9 @@
#include "content/public/app/content_main.h"
#if defined(OS_WIN)
+#include "base/debug/dump_without_crashing.h"
#include "base/win/win_util.h"
+#include "chrome/common/chrome_constants.h"
#define DLLEXPORT __declspec(dllexport)
@@ -38,6 +40,15 @@
base::win::SetAbortBehaviorForCrashReporting();
params.instance = instance;
params.sandbox_info = sandbox_info;
+
+ // SetDumpWithoutCrashingFunction must be passed the DumpProcess function
+ // from the EXE and not from the DLL in order for DumpWithoutCrashing to
+ // function correctly.
+ typedef void (__cdecl *DumpProcessFunction)();
+ DumpProcessFunction DumpProcess = reinterpret_cast<DumpProcessFunction>(
+ ::GetProcAddress(::GetModuleHandle(chrome::kBrowserProcessExecutableName),
+ "DumpProcessWithoutCrash"));
+ base::debug::SetDumpWithoutCrashingFunction(DumpProcess);
#else
params.argc = argc;
params.argv = argv;
diff --git a/chrome/browser/android/new_tab_page_prefs.cc b/chrome/browser/android/new_tab_page_prefs.cc
index 0358fb0..616beb0 100644
--- a/chrome/browser/android/new_tab_page_prefs.cc
+++ b/chrome/browser/android/new_tab_page_prefs.cc
@@ -33,6 +33,19 @@
NewTabPagePrefs::~NewTabPagePrefs() {
}
+jboolean NewTabPagePrefs::GetCurrentlyOpenTabsCollapsed(JNIEnv* env,
+ jobject obj) {
+ PrefService* prefs = profile_->GetPrefs();
+ return prefs->GetBoolean(prefs::kNtpCollapsedCurrentlyOpenTabs);
+}
+
+void NewTabPagePrefs::SetCurrentlyOpenTabsCollapsed(JNIEnv* env,
+ jobject obj,
+ jboolean is_collapsed) {
+ PrefService* prefs = profile_->GetPrefs();
+ prefs->SetBoolean(prefs::kNtpCollapsedCurrentlyOpenTabs, is_collapsed);
+}
+
jboolean NewTabPagePrefs::GetSnapshotDocumentCollapsed(JNIEnv* env,
jobject obj) {
return profile_->GetPrefs()->GetBoolean(prefs::kNtpCollapsedSnapshotDocument);
@@ -96,6 +109,10 @@
void NewTabPagePrefs::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterBooleanPref(
+ prefs::kNtpCollapsedCurrentlyOpenTabs,
+ false,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterBooleanPref(
prefs::kNtpCollapsedSnapshotDocument,
false,
user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
diff --git a/chrome/browser/android/new_tab_page_prefs.h b/chrome/browser/android/new_tab_page_prefs.h
index 99b6a09..7d4333d 100644
--- a/chrome/browser/android/new_tab_page_prefs.h
+++ b/chrome/browser/android/new_tab_page_prefs.h
@@ -14,6 +14,11 @@
explicit NewTabPagePrefs(Profile* profile);
void Destroy(JNIEnv* env, jobject obj);
+ jboolean GetCurrentlyOpenTabsCollapsed(JNIEnv* env, jobject obj);
+ void SetCurrentlyOpenTabsCollapsed(JNIEnv* env,
+ jobject obj,
+ jboolean is_collapsed);
+
jboolean GetSnapshotDocumentCollapsed(JNIEnv* env, jobject obj);
void SetSnapshotDocumentCollapsed(JNIEnv* env,
jobject obj,
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index b0260a6..03c947b 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -388,9 +388,9 @@
RegisterRecoveryComponent(cus, g_browser_process->local_state());
RegisterPepperFlashComponent(cus);
RegisterSwiftShaderComponent(cus);
+ RegisterWidevineCdmComponent(cus);
g_browser_process->pnacl_component_installer()->RegisterPnaclComponent(
cus, command_line);
- RegisterWidevineCdmComponent(cus);
#endif
#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc b/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc
index ac6546f..99cda7a 100644
--- a/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc
+++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc
@@ -21,22 +21,11 @@
#include "chromeos/dbus/dbus_method_call_status.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/session_manager_client.h"
-#include "components/policy/core/common/cloud/enterprise_metrics.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/google_service_auth_error.h"
namespace chromeos {
-namespace {
-
-void UMA(int sample) {
- UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollment,
- sample,
- policy::kMetricEnrollmentSize);
-}
-
-} // namespace
-
EnrollmentScreen::EnrollmentScreen(
ScreenObserver* observer,
EnrollmentScreenActor* actor)
@@ -74,6 +63,7 @@
actor_->ShowEnrollmentSpinnerScreen();
actor_->FetchOAuthToken();
} else {
+ UMA(policy::kMetricEnrollmentTriggered);
actor_->ResetAuth(base::Bind(&EnrollmentScreen::ShowSigninScreen,
weak_ptr_factory_.GetWeakPtr()));
}
@@ -91,15 +81,18 @@
void EnrollmentScreen::OnLoginDone(const std::string& user) {
user_ = gaia::CanonicalizeEmail(user);
- UMA(is_auto_enrollment() ? policy::kMetricEnrollmentAutoRetried
- : policy::kMetricEnrollmentStarted);
+ if (is_auto_enrollment())
+ UMA(policy::kMetricEnrollmentAutoRetried);
+ else if (enrollment_failed_once_)
+ UMA(policy::kMetricEnrollmentRetried);
+ else
+ UMA(policy::kMetricEnrollmentStarted);
actor_->ShowEnrollmentSpinnerScreen();
actor_->FetchOAuthToken();
}
-void EnrollmentScreen::OnAuthError(
- const GoogleServiceAuthError& error) {
+void EnrollmentScreen::OnAuthError(const GoogleServiceAuthError& error) {
enrollment_failed_once_ = true;
actor_->ShowAuthError(error);
@@ -145,7 +138,8 @@
}
void EnrollmentScreen::OnCancel() {
- if (enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_FORCED) {
+ if (enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_FORCED ||
+ enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_RECOVERY) {
actor_->ResetAuth(
base::Bind(&ScreenObserver::OnExit,
base::Unretained(get_screen_observer()),
@@ -303,7 +297,17 @@
UMAFailure(policy::kMetricEnrollmentOtherFailed);
}
-void EnrollmentScreen::UMAFailure(int sample) {
+void EnrollmentScreen::UMA(policy::MetricEnrollment sample) {
+ if (enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_RECOVERY) {
+ UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollmentRecovery, sample,
+ policy::kMetricEnrollmentSize);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollment, sample,
+ policy::kMetricEnrollmentSize);
+ }
+}
+
+void EnrollmentScreen::UMAFailure(policy::MetricEnrollment sample) {
if (is_auto_enrollment())
sample = policy::kMetricEnrollmentAutoFailed;
UMA(sample);
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen.h b/chrome/browser/chromeos/login/enrollment/enrollment_screen.h
index f88384f..0002d88 100644
--- a/chrome/browser/chromeos/login/enrollment/enrollment_screen.h
+++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen.h
@@ -14,6 +14,7 @@
#include "chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h"
#include "chrome/browser/chromeos/login/screens/wizard_screen.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
+#include "components/policy/core/common/cloud/enterprise_metrics.h"
namespace chromeos {
@@ -69,10 +70,15 @@
// operations are completed.
void ShowEnrollmentStatusOnSuccess(const policy::EnrollmentStatus& status);
- // Logs a UMA event in the kMetricEnrollment histogram. If auto-enrollment is
- // on |sample| is ignored and a kMetricEnrollmentAutoFailed sample is logged
+ // Logs an UMA event in the kMetricEnrollment or the kMetricEnrollmentRecovery
+ // histogram, depending on |enrollment_mode_|.
+ void UMA(policy::MetricEnrollment sample);
+
+ // Logs an UMA event in the kMetricEnrollment or the kMetricEnrollmentRecovery
+ // histogram, depending on |enrollment_mode_|. If auto-enrollment is on,
+ // |sample| is ignored and a kMetricEnrollmentAutoFailed sample is logged
// instead.
- void UMAFailure(int sample);
+ void UMAFailure(policy::MetricEnrollment sample);
// Shows the signin screen. Used as a callback to run after auth reset.
void ShowSigninScreen();
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h b/chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h
index 84a4863..74f4ffe 100644
--- a/chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h
+++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h
@@ -29,11 +29,14 @@
UI_ERROR_FATAL,
};
- // Describes the enrollment mode.
+ // Describes the enrollment mode. Must be kept in sync with
+ // |kEnrollmentModes| in enrollment_screen_handler.cc.
enum EnrollmentMode {
- ENROLLMENT_MODE_MANUAL, // Manually triggered enrollment.
- ENROLLMENT_MODE_FORCED, // Forced enrollment, user can't skip.
- ENROLLMENT_MODE_AUTO, // Auto-enrollment during first sign-in.
+ ENROLLMENT_MODE_MANUAL, // Manually triggered enrollment.
+ ENROLLMENT_MODE_FORCED, // Forced enrollment, user can't skip.
+ ENROLLMENT_MODE_AUTO, // Auto-enrollment during first sign-in.
+ ENROLLMENT_MODE_RECOVERY, // Recover from "spontaneous unenrollment".
+ ENROLLMENT_MODE_COUNT // Counter must be last. Not an enrollment mode.
};
// This defines the interface for controllers which will be called back when
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index 5332ecf..94bad1c 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -54,6 +54,7 @@
#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/timezone/timezone_provider.h"
+#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/options/options_util.h"
@@ -173,6 +174,7 @@
oobe_display_(oobe_display),
usage_statistics_reporting_(true),
skip_update_enroll_after_eula_(false),
+ enrollment_recovery_(ShouldRecoverEnrollment()),
login_screen_started_(false),
user_image_screen_return_to_previous_hack_(false),
timezone_resolved_(false),
@@ -446,15 +448,18 @@
EnrollmentScreenActor::EnrollmentMode mode =
EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL;
- if (is_auto_enrollment)
- mode = EnrollmentScreenActor::ENROLLMENT_MODE_AUTO;
- else if (ShouldAutoStartEnrollment() && !CanExitEnrollment())
- mode = EnrollmentScreenActor::ENROLLMENT_MODE_FORCED;
- else if (ShouldRecoverEnrollment())
- mode = EnrollmentScreenActor::ENROLLMENT_MODE_FORCED;
-
EnrollmentScreen* screen = GetEnrollmentScreen();
- screen->SetParameters(mode, GetForcedEnrollmentDomain(), user);
+ std::string enrollment_domain = GetForcedEnrollmentDomain();
+ if (is_auto_enrollment) {
+ mode = EnrollmentScreenActor::ENROLLMENT_MODE_AUTO;
+ } else if (enrollment_recovery_) {
+ mode = EnrollmentScreenActor::ENROLLMENT_MODE_RECOVERY;
+ enrollment_domain = GetEnrollmentRecoveryDomain();
+ } else if (ShouldAutoStartEnrollment() && !CanExitEnrollment()) {
+ mode = EnrollmentScreenActor::ENROLLMENT_MODE_FORCED;
+ }
+
+ screen->SetParameters(mode, enrollment_domain, user);
SetCurrentScreen(screen);
}
@@ -654,7 +659,7 @@
void WizardController::OnEnrollmentDone() {
// Mark OOBE as completed only if enterprise enrollment was part of the
// forced flow (i.e. app kiosk).
- if (ShouldAutoStartEnrollment() || ShouldRecoverEnrollment())
+ if (ShouldAutoStartEnrollment() || enrollment_recovery_)
PerformOOBECompletedActions();
// TODO(mnissler): Unify the logic for auto-login for Public Sessions and
@@ -699,7 +704,7 @@
}
void WizardController::OnOOBECompleted() {
- if (ShouldAutoStartEnrollment() || ShouldRecoverEnrollment()) {
+ if (ShouldAutoStartEnrollment() || enrollment_recovery_) {
ShowEnrollmentScreen();
} else {
PerformOOBECompletedActions();
@@ -759,6 +764,9 @@
"HIDDetection.TimesDialogShownPerOOBECompleted",
GetLocalState()->GetInteger(prefs::kTimesHIDDialogShown));
GetLocalState()->ClearPref(prefs::kTimesHIDDialogShown);
+
+ if (enrollment_recovery_)
+ chrome::AttemptRestart();
}
void WizardController::SetCurrentScreen(WizardScreen* new_current) {
@@ -1021,6 +1029,14 @@
}
// static
+std::string WizardController::GetEnrollmentRecoveryDomain() {
+ policy::BrowserPolicyConnectorChromeOS* connector =
+ g_browser_process->platform_part()->browser_policy_connector_chromeos();
+ return
+ connector->GetDeviceCloudPolicyManager()->GetEnrollmentRecoveryDomain();
+}
+
+// static
bool WizardController::CanExitEnrollment() {
policy::BrowserPolicyConnectorChromeOS* connector =
g_browser_process->platform_part()->browser_policy_connector_chromeos();
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h
index 1194b88..f230ab5 100644
--- a/chrome/browser/chromeos/login/wizard_controller.h
+++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -94,9 +94,13 @@
// Checks whether OOBE should start enrollment automatically.
static bool ShouldAutoStartEnrollment();
- // Checks whether OOBE should recover enrollment.
+ // Checks whether OOBE should recover enrollment. Note that this flips to
+ // false once device policy has been restored as a part of recovery.
static bool ShouldRecoverEnrollment();
+ // Obtains domain the device used to be enrolled to from install attributes.
+ static std::string GetEnrollmentRecoveryDomain();
+
// Shows the first screen defined by |first_screen_name| or by default
// if the parameter is empty. Takes ownership of |screen_parameters|.
void Init(const std::string& first_screen_name,
@@ -356,6 +360,10 @@
// EULA is accepted.
bool skip_update_enroll_after_eula_;
+ // Whether enrollment will be or has been recovered in the current wizard
+ // instance.
+ bool enrollment_recovery_;
+
// Time when the EULA was accepted. Used to measure the duration from the EULA
// acceptance until the Sign-In screen is displayed.
base::Time time_eula_accepted_;
diff --git a/chrome/browser/chromeos/net/network_portal_detector_strategy.cc b/chrome/browser/chromeos/net/network_portal_detector_strategy.cc
index cae7f93..f707f8a 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_strategy.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_strategy.cc
@@ -75,10 +75,14 @@
class SessionStrategy : public PortalDetectorStrategy {
public:
static const int kFastDelayBetweenAttemptsSec = 1;
- static const int kMaxFastAttempts = 3;
static const int kFastAttemptTimeoutSec = 3;
+ static const int kMaxFastAttempts = 3;
- static const int kSlowDelayBetweenAttemptsSec = 10;
+ static const int kNormalDelayBetweenAttemptsSec = 10;
+ static const int kNormalAttemptTimeoutSec = 5;
+ static const int kMaxNormalAttempts = 3;
+
+ static const int kSlowDelayBetweenAttemptsSec = 2 * 60;
static const int kSlowAttemptTimeoutSec = 5;
SessionStrategy() {}
@@ -90,22 +94,34 @@
virtual bool CanPerformAttemptAfterDetectionImpl() OVERRIDE { return true; }
virtual base::TimeDelta GetDelayTillNextAttemptImpl() OVERRIDE {
int delay;
- if (delegate_->AttemptCount() < kMaxFastAttempts)
+ if (IsFastAttempt())
delay = kFastDelayBetweenAttemptsSec;
+ else if (IsNormalAttempt())
+ delay = kNormalDelayBetweenAttemptsSec;
else
delay = kSlowDelayBetweenAttemptsSec;
return AdjustDelay(base::TimeDelta::FromSeconds(delay));
}
virtual base::TimeDelta GetNextAttemptTimeoutImpl() OVERRIDE {
int timeout;
- if (delegate_->AttemptCount() < kMaxFastAttempts)
+ if (IsFastAttempt())
timeout = kFastAttemptTimeoutSec;
+ else if (IsNormalAttempt())
+ timeout = kNormalAttemptTimeoutSec;
else
timeout = kSlowAttemptTimeoutSec;
return base::TimeDelta::FromSeconds(timeout);
}
private:
+ bool IsFastAttempt() {
+ return delegate_->AttemptCount() < kMaxFastAttempts;
+ }
+
+ bool IsNormalAttempt() {
+ return delegate_->AttemptCount() < kMaxFastAttempts + kMaxNormalAttempts;
+ }
+
DISALLOW_COPY_AND_ASSIGN(SessionStrategy);
};
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
index 6da4fb2..51f55d6 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
@@ -237,6 +237,11 @@
return false;
}
+std::string
+DeviceCloudPolicyManagerChromeOS::GetEnrollmentRecoveryDomain() const {
+ return install_attributes_->GetDomain();
+}
+
bool DeviceCloudPolicyManagerChromeOS::CanExitEnrollment() const {
if (GetRestoreMode() == kDeviceStateRestoreModeReEnrollmentEnforced)
return false;
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h
index fffd946..76f4d25 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h
@@ -86,6 +86,9 @@
// Checks whether enterprise enrollment recovery is required.
bool ShouldRecoverEnrollment() const;
+ // Looks up the domain from |install_attributes_|.
+ std::string GetEnrollmentRecoveryDomain() const;
+
// Checks whether the user can cancel enrollment.
bool CanExitEnrollment() const;
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.cc b/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.cc
index 13f4992..2136a10 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.cc
@@ -26,7 +26,7 @@
: device_settings_service_(device_settings_service),
install_attributes_(install_attributes),
background_task_runner_(background_task_runner),
- first_update_(true),
+ enrollment_validation_done_(false),
weak_factory_(this) {
device_settings_service_->AddObserver(this);
}
@@ -138,32 +138,47 @@
return;
}
- // Fill UMA histogram once per session. Skip temp validation error because it
- // is not a definitive result (policy load will be retried).
+ // Once per session, validate internal consistency of enrollment state (DM
+ // token must be present on enrolled devices) and in case of failure set flag
+ // to indicate that recovery is required.
const chromeos::DeviceSettingsService::Status status =
device_settings_service_->status();
- if (first_update_ &&
- status != chromeos::DeviceSettingsService::STORE_TEMP_VALIDATION_ERROR) {
- first_update_ = false;
- const bool has_dm_token =
- status == chromeos::DeviceSettingsService::STORE_SUCCESS &&
- device_settings_service_->policy_data() &&
- device_settings_service_->policy_data()->has_request_token();
+ switch (status) {
+ case chromeos::DeviceSettingsService::STORE_SUCCESS:
+ case chromeos::DeviceSettingsService::STORE_KEY_UNAVAILABLE:
+ case chromeos::DeviceSettingsService::STORE_NO_POLICY:
+ case chromeos::DeviceSettingsService::STORE_INVALID_POLICY:
+ case chromeos::DeviceSettingsService::STORE_VALIDATION_ERROR: {
+ if (!enrollment_validation_done_) {
+ enrollment_validation_done_ = true;
+ const bool has_dm_token =
+ status == chromeos::DeviceSettingsService::STORE_SUCCESS &&
+ device_settings_service_->policy_data() &&
+ device_settings_service_->policy_data()->has_request_token();
- // At the time LoginDisplayHostImpl decides whether enrollment flow is to be
- // started, policy hasn't been read yet, so LoginDisplayHostImpl is not in a
- // position to decide whether recovery is required. To work around this,
- // upon policy load on machines requiring recovery, a flag is stored in
- // prefs which is accessed by LoginDisplayHostImpl early during (next) boot.
- if (!has_dm_token) {
- LOG(ERROR) << "Policy read on enrolled device yields no DM token! "
- << "Status: " << status << ".";
- chromeos::StartupUtils::MarkEnrollmentRecoveryRequired();
+ // At the time LoginDisplayHostImpl decides whether enrollment flow is
+ // to be started, policy hasn't been read yet. To work around this,
+ // once the need for recovery is detected upon policy load, a flag is
+ // stored in prefs which is accessed by LoginDisplayHostImpl early
+ // during (next) boot.
+ if (!has_dm_token) {
+ LOG(ERROR) << "Device policy read on enrolled device yields "
+ << "no DM token! Status: " << status << ".";
+ chromeos::StartupUtils::MarkEnrollmentRecoveryRequired();
+ }
+ UMA_HISTOGRAM_BOOLEAN("Enterprise.EnrolledPolicyHasDMToken",
+ has_dm_token);
+ }
+ break;
}
- UMA_HISTOGRAM_BOOLEAN("Enterprise.EnrolledPolicyHasDMToken", has_dm_token);
+ case chromeos::DeviceSettingsService::STORE_POLICY_ERROR:
+ case chromeos::DeviceSettingsService::STORE_OPERATION_FAILED:
+ case chromeos::DeviceSettingsService::STORE_TEMP_VALIDATION_ERROR:
+ // Do nothing for write errors or transient read errors.
+ break;
}
- switch (device_settings_service_->status()) {
+ switch (status) {
case chromeos::DeviceSettingsService::STORE_SUCCESS: {
status_ = STATUS_OK;
policy_.reset(new em::PolicyData());
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h b/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h
index 327fdcf..dea0277 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h
@@ -76,9 +76,8 @@
scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
- // Run enrollment sanity check and UMA stats only upon the first policy
- // read/update.
- bool first_update_;
+ // Whether enterprise enrollment validation has yet been done.
+ bool enrollment_validation_done_;
base::WeakPtrFactory<DeviceCloudPolicyStoreChromeOS> weak_factory_;
diff --git a/chrome/browser/component_updater/component_updater_service.cc b/chrome/browser/component_updater/component_updater_service.cc
index 94ae2b3..e479c08 100644
--- a/chrome/browser/component_updater/component_updater_service.cc
+++ b/chrome/browser/component_updater/component_updater_service.cc
@@ -603,8 +603,6 @@
<< ", time_since_last_checked="
<< time_since_last_checked.InSeconds() << " seconds";
- ChangeItemState(item, CrxUpdateItem::kChecking);
-
item->last_check = now;
item->crx_urls.clear();
item->crx_diffurls.clear();
@@ -622,6 +620,8 @@
item->download_metrics.clear();
items_to_check.push_back(item);
+
+ ChangeItemState(item, CrxUpdateItem::kChecking);
}
if (items_to_check.empty())
@@ -928,14 +928,14 @@
}
if (is_success) {
- ChangeItemState(item, CrxUpdateItem::kUpdated);
item->component.version = item->next_version;
item->component.fingerprint = item->next_fp;
+ ChangeItemState(item, CrxUpdateItem::kUpdated);
} else {
- ChangeItemState(item, CrxUpdateItem::kNoUpdate);
item->error_category = error_category;
item->error_code = error;
item->extra_code1 = extra_code;
+ ChangeItemState(item, CrxUpdateItem::kNoUpdate);
}
ping_manager_->OnUpdateComplete(item);
@@ -1006,17 +1006,23 @@
if (!uit)
return kError;
- Status service_status = GetServiceStatus(uit->status);
- // If the item is already in the process of being updated, there is
- // no point in this call, so return kInProgress.
- if (service_status == kInProgress)
- return service_status;
-
- // Otherwise the item was already checked a while back (or it is new),
- // set its status to kNew to give it a slightly higher priority.
- ChangeItemState(uit, CrxUpdateItem::kNew);
uit->on_demand = true;
+ // If there is an update available for this item, then continue processing
+ // the update. This is an artifact of how update checks are done: in addition
+ // to the on-demand item, the update check may include other items as well.
+ if (uit->status != CrxUpdateItem::kCanUpdate) {
+ Status service_status = GetServiceStatus(uit->status);
+ // If the item is already in the process of being updated, there is
+ // no point in this call, so return kInProgress.
+ if (service_status == kInProgress)
+ return service_status;
+
+ // Otherwise the item was already checked a while back (or it is new),
+ // set its status to kNew to give it a slightly higher priority.
+ ChangeItemState(uit, CrxUpdateItem::kNew);
+ }
+
// In case the current delay is long, set the timer to a shorter value
// to get the ball rolling.
if (timer_.IsRunning()) {
diff --git a/chrome/browser/component_updater/widevine_cdm_component_installer.cc b/chrome/browser/component_updater/widevine_cdm_component_installer.cc
index 1445247..5dbd3b1 100644
--- a/chrome/browser/component_updater/widevine_cdm_component_installer.cc
+++ b/chrome/browser/component_updater/widevine_cdm_component_installer.cc
@@ -222,7 +222,10 @@
// true = Add to beginning of list to override any existing registrations.
PluginService::GetInstance()->RegisterInternalPlugin(
plugin_info.ToWebPluginInfo(), true);
+ // Tell the browser to refresh the plugin list. Then tell all renderers to
+ // update their plugin list caches.
PluginService::GetInstance()->RefreshPlugins();
+ PluginService::GetInstance()->PurgePluginListCache(NULL, false);
}
} // namespace
diff --git a/chrome/browser/plugins/plugin_info_message_filter.cc b/chrome/browser/plugins/plugin_info_message_filter.cc
index 2484160..50bbc75 100644
--- a/chrome/browser/plugins/plugin_info_message_filter.cc
+++ b/chrome/browser/plugins/plugin_info_message_filter.cc
@@ -59,6 +59,29 @@
return false;
}
+#if defined(ENABLE_PEPPER_CDMS)
+
+enum PluginAvailabilityStatusForUMA {
+ PLUGIN_NOT_REGISTERED,
+ PLUGIN_AVAILABLE,
+ PLUGIN_DISABLED,
+ PLUGIN_AVAILABILITY_STATUS_MAX
+};
+
+static void SendPluginAvailabilityUMA(const std::string& mime_type,
+ PluginAvailabilityStatusForUMA status) {
+#if defined(WIDEVINE_CDM_AVAILABLE)
+ // Only report results for Widevine CDM.
+ if (mime_type != kWidevineCdmPluginMimeType)
+ return;
+
+ UMA_HISTOGRAM_ENUMERATION("Plugin.AvailabilityStatus.WidevineCdm",
+ status, PLUGIN_AVAILABILITY_STATUS_MAX);
+#endif // defined(WIDEVINE_CDM_AVAILABLE)
+}
+
+#endif // defined(ENABLE_PEPPER_CDMS)
+
} // namespace
PluginInfoMessageFilter::Context::Context(int render_process_id,
@@ -94,9 +117,11 @@
IPC_BEGIN_MESSAGE_MAP(PluginInfoMessageFilter, message)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ChromeViewHostMsg_GetPluginInfo,
OnGetPluginInfo)
+#if defined(ENABLE_PEPPER_CDMS)
IPC_MESSAGE_HANDLER(
- ChromeViewHostMsg_IsInternalPluginRegisteredForMimeType,
- OnIsInternalPluginRegisteredForMimeType)
+ ChromeViewHostMsg_IsInternalPluginAvailableForMimeType,
+ OnIsInternalPluginAvailableForMimeType)
+#endif
IPC_MESSAGE_UNHANDLED(return false)
IPC_END_MESSAGE_MAP()
return true;
@@ -164,29 +189,43 @@
Send(reply_msg);
}
-void PluginInfoMessageFilter::OnIsInternalPluginRegisteredForMimeType(
+#if defined(ENABLE_PEPPER_CDMS)
+void PluginInfoMessageFilter::OnIsInternalPluginAvailableForMimeType(
const std::string& mime_type,
- bool* is_registered,
+ bool* is_available,
std::vector<base::string16>* additional_param_names,
std::vector<base::string16>* additional_param_values) {
std::vector<WebPluginInfo> plugins;
PluginService::GetInstance()->GetInternalPlugins(&plugins);
+
+ bool is_plugin_disabled = false;
for (size_t i = 0; i < plugins.size(); ++i) {
+ const WebPluginInfo& plugin = plugins[i];
const std::vector<content::WebPluginMimeType>& mime_types =
- plugins[i].mime_types;
+ plugin.mime_types;
for (size_t j = 0; j < mime_types.size(); ++j) {
if (mime_types[j].mime_type == mime_type) {
- *is_registered = true;
+ if (!context_.IsPluginEnabled(plugin)) {
+ is_plugin_disabled = true;
+ break;
+ }
+
+ *is_available = true;
*additional_param_names = mime_types[j].additional_param_names;
*additional_param_values = mime_types[j].additional_param_values;
+ SendPluginAvailabilityUMA(mime_type, PLUGIN_AVAILABLE);
return;
}
}
}
- *is_registered = false;
+ *is_available = false;
+ SendPluginAvailabilityUMA(
+ mime_type, is_plugin_disabled ? PLUGIN_DISABLED : PLUGIN_NOT_REGISTERED);
}
+#endif // defined(ENABLE_PEPPER_CDMS)
+
void PluginInfoMessageFilter::Context::DecidePluginStatus(
const GetPluginInfo_Params& params,
const WebPluginInfo& plugin,
@@ -394,3 +433,7 @@
}
}
+bool PluginInfoMessageFilter::Context::IsPluginEnabled(
+ const content::WebPluginInfo& plugin) const {
+ return plugin_prefs_->IsPluginEnabled(plugin);
+}
diff --git a/chrome/browser/plugins/plugin_info_message_filter.h b/chrome/browser/plugins/plugin_info_message_filter.h
index eb8dcb9..bcedfc3 100644
--- a/chrome/browser/plugins/plugin_info_message_filter.h
+++ b/chrome/browser/plugins/plugin_info_message_filter.h
@@ -63,6 +63,7 @@
bool* is_managed) const;
void MaybeGrantAccess(const ChromeViewHostMsg_GetPluginInfo_Status& status,
const base::FilePath& path) const;
+ bool IsPluginEnabled(const content::WebPluginInfo& plugin) const;
private:
int render_process_id_;
@@ -99,17 +100,20 @@
IPC::Message* reply_msg,
const std::vector<content::WebPluginInfo>& plugins);
- // Returns whether any internal plugin supporting |mime_type| is registered.
- // Does not determine whether the plugin can actually be instantiated
- // (e.g. whether it is allowed or has all its dependencies).
- // When the returned *|is_registered| is true, |additional_param_names| and
+#if defined(ENABLE_PEPPER_CDMS)
+ // Returns whether any internal plugin supporting |mime_type| is registered
+ // and enabled. Does not determine whether the plugin can actually be
+ // instantiated (e.g. whether it has all its dependencies).
+ // When the returned *|is_available| is true, |additional_param_names| and
// |additional_param_values| contain the name-value pairs, if any, specified
- // for the *first* plugin found that is registered for |mime_type|.
- void OnIsInternalPluginRegisteredForMimeType(
+ // for the *first* non-disabled plugin found that is registered for
+ // |mime_type|.
+ void OnIsInternalPluginAvailableForMimeType(
const std::string& mime_type,
- bool* is_registered,
+ bool* is_available,
std::vector<base::string16>* additional_param_names,
std::vector<base::string16>* additional_param_values);
+#endif
Context context_;
diff --git a/chrome/browser/prefs/DEPS b/chrome/browser/prefs/DEPS
new file mode 100644
index 0000000..10b39f7
--- /dev/null
+++ b/chrome/browser/prefs/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+sync/internal_api/public/base/model_type.h",
+]
diff --git a/chrome/browser/prefs/chrome_pref_service_factory.cc b/chrome/browser/prefs/chrome_pref_service_factory.cc
index 25b9dc5..17f77a4 100644
--- a/chrome/browser/prefs/chrome_pref_service_factory.cc
+++ b/chrome/browser/prefs/chrome_pref_service_factory.cc
@@ -35,6 +35,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/default_search_manager.h"
#include "chrome/browser/search_engines/default_search_pref_migration.h"
+#include "chrome/browser/sync/glue/sync_start_util.h"
#include "chrome/browser/ui/profile_error_dialog.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/pref_names.h"
@@ -46,6 +47,7 @@
#include "grit/browser_resources.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
+#include "sync/internal_api/public/base/model_type.h"
#include "ui/base/resource/resource_bundle.h"
#if defined(ENABLE_CONFIGURATION_POLICY)
@@ -442,16 +444,28 @@
const scoped_refptr<user_prefs::PrefRegistrySyncable>& pref_registry,
bool async) {
TRACE_EVENT0("browser", "chrome_prefs::CreateProfilePrefs");
+
+ // A StartSyncFlare used to kick sync early in case of a reset event. This is
+ // done since sync may bring back the user's server value post-reset which
+ // could potentially cause a "settings flash" between the factory default and
+ // the re-instantiated server value. Starting sync ASAP minimizes the window
+ // before the server value is re-instantiated (this window can otherwise be
+ // as long as 10 seconds by default).
+ const base::Closure start_sync_flare_for_prefs =
+ base::Bind(sync_start_util::GetFlareForSyncableService(profile_path),
+ syncer::PREFERENCES);
+
PrefServiceSyncableFactory factory;
- PrepareFactory(
- &factory,
- policy_service,
- supervised_user_settings,
- scoped_refptr<PersistentPrefStore>(
- CreateProfilePrefStoreManager(profile_path)->CreateProfilePrefStore(
- pref_io_task_runner, validation_delegate)),
- extension_prefs,
- async);
+ PrepareFactory(&factory,
+ policy_service,
+ supervised_user_settings,
+ scoped_refptr<PersistentPrefStore>(
+ CreateProfilePrefStoreManager(profile_path)
+ ->CreateProfilePrefStore(pref_io_task_runner,
+ start_sync_flare_for_prefs,
+ validation_delegate)),
+ extension_prefs,
+ async);
scoped_ptr<PrefServiceSyncable> pref_service =
factory.CreateSyncable(pref_registry.get());
diff --git a/chrome/browser/prefs/pref_hash_filter.cc b/chrome/browser/prefs/pref_hash_filter.cc
index 8bdf994..9c2a62e 100644
--- a/chrome/browser/prefs/pref_hash_filter.cc
+++ b/chrome/browser/prefs/pref_hash_filter.cc
@@ -24,10 +24,12 @@
PrefHashFilter::PrefHashFilter(
scoped_ptr<PrefHashStore> pref_hash_store,
const std::vector<TrackedPreferenceMetadata>& tracked_preferences,
+ const base::Closure& on_reset_on_load,
TrackedPreferenceValidationDelegate* delegate,
size_t reporting_ids_count,
bool report_super_mac_validity)
: pref_hash_store_(pref_hash_store.Pass()),
+ on_reset_on_load_(on_reset_on_load),
report_super_mac_validity_(report_super_mac_validity) {
DCHECK(pref_hash_store_);
DCHECK_GE(reporting_ids_count, tracked_preferences.size());
@@ -185,6 +187,9 @@
new base::StringValue(base::Int64ToString(
base::Time::Now().ToInternalValue())));
FilterUpdate(prefs::kPreferenceResetTime);
+
+ if (!on_reset_on_load_.is_null())
+ on_reset_on_load_.Run();
}
// TODO(gab): Remove this histogram by Feb 21 2014; after sufficient timing
diff --git a/chrome/browser/prefs/pref_hash_filter.h b/chrome/browser/prefs/pref_hash_filter.h
index f394557..f61222b 100644
--- a/chrome/browser/prefs/pref_hash_filter.h
+++ b/chrome/browser/prefs/pref_hash_filter.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/containers/scoped_ptr_hash_map.h"
#include "base/memory/scoped_ptr.h"
@@ -60,6 +61,8 @@
// Constructs a PrefHashFilter tracking the specified |tracked_preferences|
// using |pref_hash_store| to check/store hashes. An optional |delegate| is
// notified of the status of each preference as it is checked.
+ // If |on_reset_on_load| is provided, it will be invoked if a reset occurs in
+ // FilterOnLoad.
// |reporting_ids_count| is the count of all possible IDs (possibly greater
// than |tracked_preferences.size()|). If |report_super_mac_validity| is true,
// the state of the super MAC will be reported via UMA during
@@ -67,6 +70,7 @@
PrefHashFilter(
scoped_ptr<PrefHashStore> pref_hash_store,
const std::vector<TrackedPreferenceMetadata>& tracked_preferences,
+ const base::Closure& on_reset_on_load,
TrackedPreferenceValidationDelegate* delegate,
size_t reporting_ids_count,
bool report_super_mac_validity);
@@ -116,6 +120,9 @@
scoped_ptr<PrefHashStore> pref_hash_store_;
+ // Invoked if a reset occurs in a call to FilterOnLoad.
+ const base::Closure on_reset_on_load_;
+
TrackedPreferencesMap tracked_paths_;
// The set of all paths whose value has changed since the last call to
diff --git a/chrome/browser/prefs/pref_hash_filter_unittest.cc b/chrome/browser/prefs/pref_hash_filter_unittest.cc
index 3b5e821..429cd5c 100644
--- a/chrome/browser/prefs/pref_hash_filter_unittest.cc
+++ b/chrome/browser/prefs/pref_hash_filter_unittest.cc
@@ -348,7 +348,8 @@
public:
PrefHashFilterTest() : mock_pref_hash_store_(NULL),
pref_store_contents_(new base::DictionaryValue),
- last_filter_on_load_modified_prefs_(false) {}
+ last_filter_on_load_modified_prefs_(false),
+ reset_recorded_(false) {}
virtual void SetUp() OVERRIDE {
// Construct a PrefHashFilter and MockPrefHashStore for the test.
@@ -364,16 +365,21 @@
scoped_ptr<MockPrefHashStore> temp_mock_pref_hash_store(
new MockPrefHashStore);
mock_pref_hash_store_ = temp_mock_pref_hash_store.get();
- pref_hash_filter_.reset(
- new PrefHashFilter(temp_mock_pref_hash_store.PassAs<PrefHashStore>(),
- configuration,
- &mock_validation_delegate_,
- arraysize(kTestTrackedPrefs),
- true));
+ pref_hash_filter_.reset(new PrefHashFilter(
+ temp_mock_pref_hash_store.PassAs<PrefHashStore>(),
+ configuration,
+ base::Bind(&PrefHashFilterTest::RecordReset, base::Unretained(this)),
+ &mock_validation_delegate_,
+ arraysize(kTestTrackedPrefs),
+ true));
}
- bool RecordedReset() {
- return pref_store_contents_->Get(prefs::kPreferenceResetTime, NULL);
+ // Verifies whether a reset was reported by the PrefHashFiler. Also verifies
+ // that kPreferenceResetTime was set (or not) accordingly.
+ void VerifyRecordedReset(bool reset_expected) {
+ EXPECT_EQ(reset_expected, reset_recorded_);
+ EXPECT_EQ(reset_expected,
+ pref_store_contents_->Get(prefs::kPreferenceResetTime, NULL));
}
// Calls FilterOnLoad() on |pref_hash_Filter_|. |pref_store_contents_| is
@@ -404,6 +410,15 @@
EXPECT_EQ(expected_schedule_write, schedule_write);
}
+ void RecordReset() {
+ // As-is |reset_recorded_| is only designed to remember a single reset, make
+ // sure none was previously recorded.
+ EXPECT_FALSE(reset_recorded_);
+ reset_recorded_ = true;
+ }
+
+ bool reset_recorded_;
+
DISALLOW_COPY_AND_ASSIGN(PrefHashFilterTest);
};
@@ -421,7 +436,7 @@
kTestTrackedPrefs[i].name).first);
}
ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
- ASSERT_FALSE(RecordedReset());
+ VerifyRecordedReset(false);
// Delegate saw all paths, and all unchanged.
ASSERT_EQ(arraysize(kTestTrackedPrefs),
@@ -450,7 +465,7 @@
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC, stored_value.second);
ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
- ASSERT_FALSE(RecordedReset());
+ VerifyRecordedReset(false);
}
TEST_P(PrefHashFilterTest, FilterSplitPrefUpdate) {
@@ -474,7 +489,7 @@
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, stored_value.second);
ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
- ASSERT_FALSE(RecordedReset());
+ VerifyRecordedReset(false);
}
TEST_P(PrefHashFilterTest, FilterUntrackedPrefUpdate) {
@@ -644,7 +659,7 @@
ASSERT_FALSE(pref_store_contents_->Get(kSplitPref, NULL));
ASSERT_EQ(NULL, stored_split_value.first);
- ASSERT_TRUE(RecordedReset());
+ VerifyRecordedReset(true);
} else {
// Otherwise the values should have remained intact and the hashes should
// have been updated to match them.
@@ -658,7 +673,7 @@
ASSERT_EQ(dict_value, split_value_in_store);
ASSERT_EQ(dict_value, stored_split_value.first);
- ASSERT_FALSE(RecordedReset());
+ VerifyRecordedReset(false);
}
}
@@ -771,7 +786,7 @@
ASSERT_TRUE(dict_value->HasKey("d"));
ASSERT_EQ(dict_value, stored_split_value.first);
- ASSERT_TRUE(RecordedReset());
+ VerifyRecordedReset(true);
} else {
// Otherwise the value should have remained intact and the hash should have
// been updated to match it.
@@ -790,7 +805,7 @@
ASSERT_TRUE(dict_value->HasKey("d"));
ASSERT_EQ(dict_value, stored_split_value.first);
- ASSERT_FALSE(RecordedReset());
+ VerifyRecordedReset(false);
}
}
@@ -873,7 +888,7 @@
ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL));
ASSERT_EQ(NULL, stored_atomic_value.first);
- ASSERT_TRUE(RecordedReset());
+ VerifyRecordedReset(true);
} else {
// Otherwise the value should have remained intact and the hash should have
// been updated to match it.
@@ -882,7 +897,7 @@
ASSERT_EQ(list_value, atomic_value_in_store);
ASSERT_EQ(list_value, stored_atomic_value.first);
- ASSERT_FALSE(RecordedReset());
+ VerifyRecordedReset(false);
}
}
@@ -942,7 +957,7 @@
ASSERT_EQ(dict_value, split_value_in_store);
ASSERT_EQ(dict_value, stored_split_value.first);
- ASSERT_FALSE(RecordedReset());
+ VerifyRecordedReset(false);
}
TEST_P(PrefHashFilterTest, DontResetReportOnly) {
@@ -1005,7 +1020,7 @@
ASSERT_EQ(NULL, mock_pref_hash_store_->stored_value(kAtomicPref).first);
ASSERT_EQ(NULL, mock_pref_hash_store_->stored_value(kAtomicPref2).first);
- ASSERT_TRUE(RecordedReset());
+ VerifyRecordedReset(true);
} else {
const base::Value* value_in_store;
const base::Value* value_in_store2;
@@ -1018,7 +1033,7 @@
ASSERT_EQ(int_value2,
mock_pref_hash_store_->stored_value(kAtomicPref2).first);
- ASSERT_FALSE(RecordedReset());
+ VerifyRecordedReset(false);
}
}
diff --git a/chrome/browser/prefs/profile_pref_store_manager.cc b/chrome/browser/prefs/profile_pref_store_manager.cc
index f4264b7..f913d9a 100644
--- a/chrome/browser/prefs/profile_pref_store_manager.cc
+++ b/chrome/browser/prefs/profile_pref_store_manager.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/prefs/profile_pref_store_manager.h"
#include "base/bind.h"
+#include "base/callback.h"
#include "base/file_util.h"
#include "base/json/json_file_value_serializer.h"
#include "base/logging.h"
@@ -81,6 +82,7 @@
PersistentPrefStore* ProfilePrefStoreManager::CreateProfilePrefStore(
const scoped_refptr<base::SequencedTaskRunner>& io_task_runner,
+ const base::Closure& on_reset_on_load,
TrackedPreferenceValidationDelegate* validation_delegate) {
scoped_ptr<PrefFilter> pref_filter;
if (!kPlatformSupportsPreferenceTracking) {
@@ -111,12 +113,14 @@
scoped_ptr<PrefHashFilter> unprotected_pref_hash_filter(
new PrefHashFilter(GetPrefHashStore(false),
unprotected_configuration,
+ base::Closure(),
validation_delegate,
reporting_ids_count_,
false));
scoped_ptr<PrefHashFilter> protected_pref_hash_filter(
new PrefHashFilter(GetPrefHashStore(true),
protected_configuration,
+ on_reset_on_load,
validation_delegate,
reporting_ids_count_,
true));
@@ -175,6 +179,7 @@
to_serialize = copy.get();
PrefHashFilter(GetPrefHashStore(false),
tracking_configuration_,
+ base::Closure(),
NULL,
reporting_ids_count_,
false).Initialize(copy.get());
@@ -209,6 +214,7 @@
pref_filter.reset(
new PrefHashFilter(pref_hash_store_impl.PassAs<PrefHashStore>(),
tracking_configuration_,
+ base::Closure(),
NULL,
reporting_ids_count_,
false));
diff --git a/chrome/browser/prefs/profile_pref_store_manager.h b/chrome/browser/prefs/profile_pref_store_manager.h
index 806b129..759b988 100644
--- a/chrome/browser/prefs/profile_pref_store_manager.h
+++ b/chrome/browser/prefs/profile_pref_store_manager.h
@@ -79,10 +79,13 @@
static void ClearResetTime(PrefService* pref_service);
// Creates a PersistentPrefStore providing access to the user preferences of
- // the managed profile. An optional |validation_delegate| will be notified
+ // the managed profile. If |on_reset| is provided, it will be invoked if a
+ // reset occurs as a result of loading the profile's prefs.
+ // An optional |validation_delegate| will be notified
// of the status of each tracked preference as they are checked.
PersistentPrefStore* CreateProfilePrefStore(
const scoped_refptr<base::SequencedTaskRunner>& io_task_runner,
+ const base::Closure& on_reset_on_load,
TrackedPreferenceValidationDelegate* validation_delegate);
// Initializes the preferences for the managed profile with the preference
diff --git a/chrome/browser/prefs/profile_pref_store_manager_unittest.cc b/chrome/browser/prefs/profile_pref_store_manager_unittest.cc
index c478ac4..ead5ac4 100644
--- a/chrome/browser/prefs/profile_pref_store_manager_unittest.cc
+++ b/chrome/browser/prefs/profile_pref_store_manager_unittest.cc
@@ -92,7 +92,8 @@
kConfiguration + arraysize(kConfiguration)),
profile_pref_registry_(new user_prefs::PrefRegistrySyncable),
registry_verifier_(profile_pref_registry_),
- seed_("seed") {}
+ seed_("seed"),
+ reset_recorded_(false) {}
virtual void SetUp() OVERRIDE {
ProfilePrefStoreManager::RegisterPrefs(local_state_.registry());
@@ -142,17 +143,25 @@
virtual void TearDown() OVERRIDE { DestroyPrefStore(); }
protected:
- bool WasResetRecorded() {
+ // Verifies whether a reset was reported via the RecordReset() hook. Also
+ // verifies that GetResetTime() was set (or not) accordingly.
+ void VerifyResetRecorded(bool reset_expected) {
+ EXPECT_EQ(reset_expected, reset_recorded_);
+
base::PrefServiceFactory pref_service_factory;
pref_service_factory.set_user_prefs(pref_store_);
scoped_ptr<PrefService> pref_service(
pref_service_factory.Create(profile_pref_registry_));
- return !ProfilePrefStoreManager::GetResetTime(pref_service.get()).is_null();
+ EXPECT_EQ(
+ reset_expected,
+ !ProfilePrefStoreManager::GetResetTime(pref_service.get()).is_null());
}
void ClearResetRecorded() {
+ reset_recorded_ = false;
+
base::PrefServiceFactory pref_service_factory;
pref_service_factory.set_user_prefs(pref_store_);
@@ -168,6 +177,8 @@
scoped_refptr<PersistentPrefStore> pref_store =
manager_->CreateProfilePrefStore(
main_message_loop_.message_loop_proxy(),
+ base::Bind(&ProfilePrefStoreManagerTest::RecordReset,
+ base::Unretained(this)),
&mock_validation_delegate_);
InitializePrefStore(pref_store);
pref_store = NULL;
@@ -214,7 +225,10 @@
void LoadExistingPrefs() {
DestroyPrefStore();
pref_store_ = manager_->CreateProfilePrefStore(
- main_message_loop_.message_loop_proxy(), NULL);
+ main_message_loop_.message_loop_proxy(),
+ base::Bind(&ProfilePrefStoreManagerTest::RecordReset,
+ base::Unretained(this)),
+ NULL);
pref_store_->AddObserver(®istry_verifier_);
pref_store_->ReadPrefs();
}
@@ -267,6 +281,17 @@
scoped_refptr<PersistentPrefStore> pref_store_;
std::string seed_;
+
+ private:
+ void RecordReset() {
+ // As-is |reset_recorded_| is only designed to remember a single reset, make
+ // sure none was previously recorded (or that ClearResetRecorded() was
+ // called).
+ EXPECT_FALSE(reset_recorded_);
+ reset_recorded_ = true;
+ }
+
+ bool reset_recorded_;
};
TEST_F(ProfilePrefStoreManagerTest, StoreValues) {
@@ -276,7 +301,7 @@
ExpectStringValueEquals(kTrackedAtomic, kFoobar);
ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
- EXPECT_FALSE(WasResetRecorded());
+ VerifyResetRecorded(false);
ExpectValidationObserved(kTrackedAtomic);
ExpectValidationObserved(kProtectedAtomic);
}
@@ -309,8 +334,8 @@
// will be discarded at load time, leaving this preference undefined.
EXPECT_NE(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
pref_store_->GetValue(kProtectedAtomic, NULL));
- EXPECT_EQ(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
- WasResetRecorded());
+ VerifyResetRecorded(
+ ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking);
ExpectValidationObserved(kTrackedAtomic);
ExpectValidationObserved(kProtectedAtomic);
@@ -337,7 +362,7 @@
ExpectStringValueEquals(kTrackedAtomic, kFoobar);
ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
- EXPECT_FALSE(WasResetRecorded());
+ VerifyResetRecorded(false);
LoadExistingPrefs();
@@ -347,7 +372,7 @@
ExpectStringValueEquals(kTrackedAtomic, kFoobar);
ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
- EXPECT_FALSE(WasResetRecorded());
+ VerifyResetRecorded(false);
}
TEST_F(ProfilePrefStoreManagerTest, MigrateWithTampering) {
@@ -380,8 +405,8 @@
// will be discarded at load time, leaving this preference undefined.
EXPECT_NE(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
pref_store_->GetValue(kProtectedAtomic, NULL));
- EXPECT_EQ(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
- WasResetRecorded());
+ VerifyResetRecorded(
+ ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking);
LoadExistingPrefs();
@@ -390,7 +415,7 @@
PrefServiceHashStoreContents::kProfilePreferenceHashes));
ExpectStringValueEquals(kTrackedAtomic, kBarfoo);
- EXPECT_FALSE(WasResetRecorded());
+ VerifyResetRecorded(false);
}
TEST_F(ProfilePrefStoreManagerTest, InitializePrefsFromMasterPrefs) {
@@ -405,7 +430,7 @@
// necessary to authenticate these values.
ExpectStringValueEquals(kTrackedAtomic, kFoobar);
ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
- EXPECT_FALSE(WasResetRecorded());
+ VerifyResetRecorded(false);
}
TEST_F(ProfilePrefStoreManagerTest, UnprotectedToProtected) {
@@ -439,7 +464,7 @@
// Since there was a valid super MAC we were able to extend the existing trust
// to the newly protected preference.
ExpectStringValueEquals(kUnprotectedPref, kBarfoo);
- EXPECT_FALSE(WasResetRecorded());
+ VerifyResetRecorded(false);
// Ensure everything is written out to disk.
DestroyPrefStore();
@@ -450,8 +475,8 @@
LoadExistingPrefs();
EXPECT_NE(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
pref_store_->GetValue(kUnprotectedPref, NULL));
- EXPECT_EQ(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
- WasResetRecorded());
+ VerifyResetRecorded(
+ ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking);
}
TEST_F(ProfilePrefStoreManagerTest, NewPrefWhenFirstProtecting) {
@@ -490,7 +515,7 @@
// Since there was a valid super MAC we were able to extend the existing trust
// to the newly tracked & protected preference.
ExpectStringValueEquals(kUnprotectedPref, kFoobar);
- EXPECT_FALSE(WasResetRecorded());
+ VerifyResetRecorded(false);
}
TEST_F(ProfilePrefStoreManagerTest, UnprotectedToProtectedWithoutTrust) {
@@ -514,8 +539,8 @@
// discarded because new values are not accepted without a valid super MAC.
EXPECT_NE(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
pref_store_->GetValue(kUnprotectedPref, NULL));
- EXPECT_EQ(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
- WasResetRecorded());
+ VerifyResetRecorded(
+ ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking);
}
// This test verifies that preference values are correctly maintained when a
@@ -545,7 +570,7 @@
// Verify that the value was not reset.
ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
- EXPECT_FALSE(WasResetRecorded());
+ VerifyResetRecorded(false);
// Accessing the value of the previously protected pref didn't trigger its
// move to the unprotected preferences file, though the loading of the pref
@@ -558,5 +583,5 @@
pref_store_->SetValue(kProtectedAtomic, new base::StringValue(kGoodbyeWorld));
LoadExistingPrefs();
ExpectStringValueEquals(kProtectedAtomic, kGoodbyeWorld);
- EXPECT_FALSE(WasResetRecorded());
+ VerifyResetRecorded(false);
}
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.css b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.css
index 1a60f6a..38c464e 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.css
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.css
@@ -77,7 +77,8 @@
}
#oauth-enrollment.mode-manual #oauth-enroll-learn-more-link,
-#oauth-enrollment.mode-forced #oauth-enroll-learn-more-link {
+#oauth-enrollment.mode-forced #oauth-enroll-learn-more-link,
+#oauth-enrollment.mode-recovery #oauth-enroll-learn-more-link {
display: inline;
}
@@ -132,12 +133,15 @@
}
.oauth-enroll-state-signin.mode-manual #oauth-enroll-cancel-button,
-.oauth-enroll-state-working.mode-manual #oauth-enroll-cancel-button,
.oauth-enroll-state-signin.mode-forced #oauth-enroll-back-button,
+.oauth-enroll-state-signin.mode-recovery #oauth-enroll-back-button,
+.oauth-enroll-state-working.mode-manual #oauth-enroll-cancel-button,
.oauth-enroll-state-working.mode-forced #oauth-enroll-back-button,
+.oauth-enroll-state-working.mode-recovery #oauth-enroll-back-button,
.oauth-enroll-state-error.mode-manual #oauth-enroll-cancel-button,
.oauth-enroll-state-error.mode-auto #oauth-enroll-retry-button,
.oauth-enroll-state-error.mode-forced #oauth-enroll-back-button,
+.oauth-enroll-state-error.mode-recovery #oauth-enroll-back-button,
.oauth-enroll-state-explain #oauth-enroll-explain-retry-button,
.oauth-enroll-state-success #oauth-enroll-done-button {
display: inline;
diff --git a/chrome/browser/resources/components.html b/chrome/browser/resources/components.html
index de5e9c6..b7dfded 100644
--- a/chrome/browser/resources/components.html
+++ b/chrome/browser/resources/components.html
@@ -47,7 +47,8 @@
</span>
<span>
- <span i18n-content="componentVersion"></span>
- <span dir="ltr" jscontent="version"></span>
+ <span dir="ltr" jscontent="version"
+ jsvalues=".id: 'version-' + id"></span>
</span>
</div>
</div>
diff --git a/chrome/browser/resources/components.js b/chrome/browser/resources/components.js
index 036fe5b..64b6e3a 100644
--- a/chrome/browser/resources/components.js
+++ b/chrome/browser/resources/components.js
@@ -86,6 +86,9 @@
var id = eventArgs['id'];
$('status-' + id).textContent = eventArgs['event'];
}
+ if (eventArgs['version']) {
+ $('version-' + id).textContent = eventArgs['version'];
+ }
}
/**
diff --git a/chrome/browser/resources/omnibox/omnibox.js b/chrome/browser/resources/omnibox/omnibox.js
index afde3e0..e99c942 100644
--- a/chrome/browser/resources/omnibox/omnibox.js
+++ b/chrome/browser/resources/omnibox/omnibox.js
@@ -203,8 +203,8 @@
}
/**
- * @param {Object} autocompleteSuggestion the particular autocomplete
- * suggestion we're in the process of displaying.
+ * @param {AutocompleteMatchMojo} autocompleteSuggestion the particular
+ * autocomplete suggestion we're in the process of displaying.
* @param {string} propertyName the particular property of the autocomplete
* suggestion that should go in this cell.
* @return {HTMLTableCellElement} that contains the value within this
@@ -382,7 +382,8 @@
// Javascript? In any case, we want to display them.)
if (inDetailedMode) {
for (var key in autocompleteSuggestion) {
- if (!displayedProperties[key]) {
+ if (!displayedProperties[key] &&
+ typeof autocompleteSuggestion[key] != 'function') {
var cell = document.createElement('td');
cell.textContent = key + '=' + autocompleteSuggestion[key];
row.appendChild(cell);
diff --git a/chrome/browser/safe_browsing/last_download_finder.cc b/chrome/browser/safe_browsing/last_download_finder.cc
index 05e7c42..d0e1c2f 100644
--- a/chrome/browser/safe_browsing/last_download_finder.cc
+++ b/chrome/browser/safe_browsing/last_download_finder.cc
@@ -145,6 +145,14 @@
return;
}
+ // Exit early if already processing this profile. This could happen if, for
+ // example, NOTIFICATION_PROFILE_ADDED arrives after construction while
+ // waiting for NOTIFICATION_HISTORY_LOADED.
+ if (std::find(profiles_.begin(), profiles_.end(), profile) !=
+ profiles_.end()) {
+ return;
+ }
+
HistoryService* history_service =
HistoryServiceFactory::GetForProfile(profile, Profile::IMPLICIT_ACCESS);
// No history service is returned for profiles that do not save history.
diff --git a/chrome/browser/speech/tts_message_filter.cc b/chrome/browser/speech/tts_message_filter.cc
index 789eac3..3c47074 100644
--- a/chrome/browser/speech/tts_message_filter.cc
+++ b/chrome/browser/speech/tts_message_filter.cc
@@ -54,6 +54,10 @@
base::Bind(&TtsMessageFilter::OnChannelClosingInUIThread, this));
}
+void TtsMessageFilter::OnDestruct() const {
+ BrowserThread::DeleteOnUIThread::Destruct(this);
+}
+
void TtsMessageFilter::OnInitializeVoiceList() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
TtsController* tts_controller = TtsController::GetInstance();
@@ -159,4 +163,6 @@
}
TtsMessageFilter::~TtsMessageFilter() {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ TtsController::GetInstance()->RemoveVoicesChangedDelegate(this);
}
diff --git a/chrome/browser/speech/tts_message_filter.h b/chrome/browser/speech/tts_message_filter.h
index 629745c..154f482 100644
--- a/chrome/browser/speech/tts_message_filter.h
+++ b/chrome/browser/speech/tts_message_filter.h
@@ -26,6 +26,7 @@
content::BrowserThread::ID* thread) OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
virtual void OnChannelClosing() OVERRIDE;
+ virtual void OnDestruct() const OVERRIDE;
// UtteranceEventDelegate implementation.
virtual void OnTtsEvent(Utterance* utterance,
@@ -37,6 +38,9 @@
virtual void OnVoicesChanged() OVERRIDE;
private:
+ friend class content::BrowserThread;
+ friend class base::DeleteHelper<TtsMessageFilter>;
+
virtual ~TtsMessageFilter();
void OnInitializeVoiceList();
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
index 39ef4ca..e5651d7 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -32,6 +32,7 @@
#include "chrome/browser/defaults.h"
#include "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
#include "chrome/browser/net/chrome_cookie_notification_details.h"
+#include "chrome/browser/prefs/chrome_pref_service_factory.h"
#include "chrome/browser/prefs/pref_service_syncable.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/services/gcm/gcm_profile_service.h"
@@ -521,11 +522,20 @@
if (backend_mode_ == SYNC)
return !HasSyncSetupCompleted();
- // Start fresh if it's the first time backup after user stopped syncing.
- // This is needed because backup DB may contain items deleted by user during
- // sync period and can cause back-from-dead issues.
- if (backend_mode_ == BACKUP && !sync_prefs_.GetFirstSyncTime().is_null())
- return true;
+ if (backend_mode_ == BACKUP) {
+ base::Time reset_time = chrome_prefs::GetResetTime(profile_);
+
+ // Start fresh if:
+ // * It's the first time backup after user stopped syncing because backup
+ // DB may contain items deleted by user during sync period and can cause
+ // back-from-dead issues if user didn't choose rollback.
+ // * Settings are reset during startup because of tampering to avoid
+ // restoring settings from backup.
+ if (!sync_prefs_.GetFirstSyncTime().is_null() ||
+ (!reset_time.is_null() && profile_->GetStartTime() <= reset_time)) {
+ return true;
+ }
+ }
return false;
}
@@ -2578,3 +2588,10 @@
}
return result;
}
+
+void ProfileSyncService::StartStopBackupForTesting() {
+ if (backend_mode_ == BACKUP)
+ ShutdownImpl(browser_sync::SyncBackendHost::STOP_AND_CLAIM_THREAD);
+ else
+ backup_rollback_controller_.Start(base::TimeDelta());
+}
diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h
index 0325d0d..417582a 100644
--- a/chrome/browser/sync/profile_sync_service.h
+++ b/chrome/browser/sync/profile_sync_service.h
@@ -780,6 +780,8 @@
// Return the base URL of the Sync Server.
static GURL GetSyncServiceURL(const base::CommandLine& command_line);
+ void StartStopBackupForTesting();
+
protected:
// Helper to configure the priority data types.
void ConfigurePriorityDataTypes();
diff --git a/chrome/browser/sync/profile_sync_service_unittest.cc b/chrome/browser/sync/profile_sync_service_unittest.cc
index 2c70744..c9224e8 100644
--- a/chrome/browser/sync/profile_sync_service_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_unittest.cc
@@ -7,6 +7,7 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/invalidation/fake_invalidation_service.h"
@@ -491,10 +492,6 @@
}
#if defined(ENABLE_PRE_SYNC_BACKUP)
-void QuitLoop() {
- base::MessageLoop::current()->Quit();
-}
-
TEST_F(ProfileSyncServiceTest, StartBackup) {
CreateServiceWithoutSignIn();
ExpectDataTypeManagerCreation(1);
@@ -502,10 +499,11 @@
ExpectSyncBackendHostCreationCollectDeleteDir(1, &delete_dir_param);
Initialize();
EXPECT_EQ(ProfileSyncService::IDLE, service()->backend_mode());
+ base::RunLoop run_loop;
base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE, base::Bind(&QuitLoop),
+ FROM_HERE, run_loop.QuitClosure(),
base::TimeDelta::FromMilliseconds(100));
- base::MessageLoop::current()->Run();
+ run_loop.Run();
EXPECT_EQ(ProfileSyncService::BACKUP, service()->backend_mode());
EXPECT_EQ(1u, delete_dir_param.size());
@@ -520,7 +518,6 @@
ExpectSyncBackendHostCreationCollectDeleteDir(2, &delete_dir_param);
IssueTestTokens();
Initialize();
- base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&QuitLoop));
EXPECT_TRUE(service()->sync_initialized());
EXPECT_EQ(ProfileSyncService::SYNC, service()->backend_mode());
@@ -555,7 +552,6 @@
ExpectSyncBackendHostCreationCollectDeleteDir(3, &delete_dir_param);
IssueTestTokens();
Initialize();
- base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&QuitLoop));
EXPECT_TRUE(service()->sync_initialized());
EXPECT_EQ(ProfileSyncService::SYNC, service()->backend_mode());
@@ -586,6 +582,32 @@
EXPECT_FALSE(delete_dir_param[1]);
EXPECT_TRUE(delete_dir_param[2]);
}
+
+TEST_F(ProfileSyncServiceTest, StartNewBackupDbOnSettingsReset) {
+ CreateServiceWithoutSignIn();
+ ExpectDataTypeManagerCreation(1);
+ std::vector<bool> delete_dir_param;
+ ExpectSyncBackendHostCreationCollectDeleteDir(1, &delete_dir_param);
+ Initialize();
+ EXPECT_EQ(ProfileSyncService::IDLE, service()->backend_mode());
+
+ // Set reset time to pretend settings reset happened.
+ profile()->GetPrefs()->SetString(
+ prefs::kPreferenceResetTime,
+ base::Int64ToString(base::Time::Now().ToInternalValue()));
+
+ base::RunLoop run_loop;
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(),
+ base::TimeDelta::FromMilliseconds(100));
+ run_loop.Run();
+
+ EXPECT_EQ(ProfileSyncService::BACKUP, service()->backend_mode());
+
+ EXPECT_EQ(1u, delete_dir_param.size());
+ EXPECT_TRUE(delete_dir_param[0]);
+}
+
#endif
TEST_F(ProfileSyncServiceTest, GetSyncServiceURL) {
diff --git a/chrome/browser/sync/test/integration/single_client_backup_rollback_test.cc b/chrome/browser/sync/test/integration/single_client_backup_rollback_test.cc
index 5dec3a1..bf74892 100644
--- a/chrome/browser/sync/test/integration/single_client_backup_rollback_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_backup_rollback_test.cc
@@ -4,12 +4,15 @@
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
+#include "base/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/test/integration/bookmarks_helper.h"
+#include "chrome/browser/sync/test/integration/preferences_helper.h"
#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
#include "chrome/browser/sync/test/integration/sync_test.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "sync/test/fake_server/fake_server_verifier.h"
@@ -21,15 +24,25 @@
using bookmarks_helper::Remove;
using sync_integration_test_util::AwaitCommitActivityCompletion;
+namespace {
+const char kUrl1[] = "http://www.google.com";
+const char kUrl2[] = "http://map.google.com";
+const char kUrl3[] = "http://plus.google.com";
+} // anonymous namespace
+
class SingleClientBackupRollbackTest : public SyncTest {
public:
SingleClientBackupRollbackTest() : SyncTest(SINGLE_CLIENT) {}
virtual ~SingleClientBackupRollbackTest() {}
- virtual void SetUp() OVERRIDE {
+ void DisableBackup() {
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kSyncDisableBackup);
+ }
+
+ void EnableRollback() {
CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kSyncEnableRollback);
- SyncTest::SetUp();
}
private:
@@ -41,9 +54,10 @@
explicit BackupModeChecker(ProfileSyncService* service,
base::TimeDelta timeout)
: pss_(service),
- expiration_(base::TimeTicks::Now() + timeout) {}
+ timeout_(timeout) {}
bool Wait() {
+ expiration_ = base::TimeTicks::Now() + timeout_;
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&BackupModeChecker::PeriodicCheck, base::Unretained(this)),
@@ -70,6 +84,7 @@
}
ProfileSyncService* pss_;
+ base::TimeDelta timeout_;
base::TimeTicks expiration_;
};
@@ -80,6 +95,7 @@
#endif
IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
MAYBE_TestBackupRollback) {
+ EnableRollback();
ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
// Starting state:
@@ -131,3 +147,126 @@
const BookmarkNode* url2 = tier1_b->GetChild(0);
ASSERT_EQ(GURL("http://www.nhl.com"), url2->url());
}
+
+#if defined(ENABLE_PRE_SYNC_BACKUP)
+#define MAYBE_TestPrefBackupRollback TestPrefBackupRollback
+#else
+#define MAYBE_TestPrefBackupRollback DISABLED_TestPrefBackupRollback
+#endif
+// Verify local preferences are not affected by preferences in backup DB under
+// backup mode.
+IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
+ MAYBE_TestPrefBackupRollback) {
+ EnableRollback();
+
+ ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
+
+ preferences_helper::ChangeStringPref(0, prefs::kHomePage, kUrl1);
+
+ BackupModeChecker checker(GetSyncService(0),
+ base::TimeDelta::FromSeconds(15));
+ ASSERT_TRUE(checker.Wait());
+
+ // Shut down backup, then change preference.
+ GetSyncService(0)->StartStopBackupForTesting();
+ preferences_helper::ChangeStringPref(0, prefs::kHomePage, kUrl2);
+
+ // Restart backup. Preference shouldn't change after backup starts.
+ GetSyncService(0)->StartStopBackupForTesting();
+ ASSERT_TRUE(checker.Wait());
+ ASSERT_EQ(kUrl2,
+ preferences_helper::GetPrefs(0)->GetString(prefs::kHomePage));
+
+ // Start sync and change preference.
+ ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+ preferences_helper::ChangeStringPref(0, prefs::kHomePage, kUrl3);
+ ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
+ ASSERT_TRUE(ModelMatchesVerifier(0));
+
+ // Let server return rollback command on next sync request.
+ GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK);
+
+ // Make another change to trigger downloading of rollback command.
+ preferences_helper::ChangeStringPref(0, prefs::kHomePage, "");
+
+ // Wait for sync to switch to backup mode after finishing rollback.
+ ASSERT_TRUE(checker.Wait());
+
+ // Verify preference is restored.
+ ASSERT_EQ(kUrl2,
+ preferences_helper::GetPrefs(0)->GetString(prefs::kHomePage));
+}
+
+#if defined(ENABLE_PRE_SYNC_BACKUP)
+#define MAYBE_RollbackNoBackup RollbackNoBackup
+#else
+#define MAYBE_RollbackNoBackup DISABLED_RollbackNoBackup
+#endif
+IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
+ MAYBE_RollbackNoBackup) {
+ EnableRollback();
+
+ ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
+
+ // Setup sync, wait for its completion, and make sure changes were synced.
+ ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+
+ // Starting state:
+ // other_node
+ // -> http://mail.google.com "url0"
+ // -> http://www.nhl.com "url1"
+ ASSERT_TRUE(AddURL(0, GetOtherNode(0), 0, "url0",
+ GURL("http://mail.google.com")));
+ ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url1",
+ GURL("http://www.nhl.com")));
+
+ ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
+ ASSERT_TRUE(ModelMatchesVerifier(0));
+
+ // Let server to return rollback command on next sync request.
+ GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK);
+
+ // Make another change to trigger downloading of rollback command.
+ Remove(0, GetOtherNode(0), 0);
+
+ // Wait for sync to switch to backup mode after finishing rollback.
+ BackupModeChecker checker(GetSyncService(0),
+ base::TimeDelta::FromSeconds(15));
+ ASSERT_TRUE(checker.Wait());
+
+ // Without backup DB, bookmarks added during sync shouldn't be removed.
+ ASSERT_EQ(1, GetOtherNode(0)->child_count());
+ ASSERT_EQ(GURL("http://www.nhl.com"),
+ GetOtherNode(0)->GetChild(0)->url());
+}
+
+#if defined(ENABLE_PRE_SYNC_BACKUP)
+#define MAYBE_DontChangeBookmarkOrdering DontChangeBookmarkOrdering
+#else
+#define MAYBE_DontChangeBookmarkOrdering DISABLED_DontChangeBookmarkOrdering
+#endif
+IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
+ MAYBE_DontChangeBookmarkOrdering) {
+ ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
+
+ const BookmarkNode* sub_folder = AddFolder(0, GetOtherNode(0), 0, "test");
+ ASSERT_TRUE(AddURL(0, sub_folder, 0, "", GURL(kUrl1)));
+ ASSERT_TRUE(AddURL(0, sub_folder, 1, "", GURL(kUrl2)));
+ ASSERT_TRUE(AddURL(0, sub_folder, 2, "", GURL(kUrl3)));
+
+ BackupModeChecker checker(GetSyncService(0),
+ base::TimeDelta::FromSeconds(15));
+ ASSERT_TRUE(checker.Wait());
+
+ // Restart backup.
+ GetSyncService(0)->StartStopBackupForTesting();
+ GetSyncService(0)->StartStopBackupForTesting();
+ ASSERT_TRUE(checker.Wait());
+
+ // Verify bookmarks are unchanged.
+ ASSERT_EQ(3, sub_folder->child_count());
+ ASSERT_EQ(GURL(kUrl1), sub_folder->GetChild(0)->url());
+ ASSERT_EQ(GURL(kUrl2), sub_folder->GetChild(1)->url());
+ ASSERT_EQ(GURL(kUrl3), sub_folder->GetChild(2)->url());
+}
+
diff --git a/chrome/browser/ui/browser_tabrestore.cc b/chrome/browser/ui/browser_tabrestore.cc
index abe591c..c5af58f 100644
--- a/chrome/browser/ui/browser_tabrestore.cc
+++ b/chrome/browser/ui/browser_tabrestore.cc
@@ -122,8 +122,12 @@
// location calculations to be incorrect even after a new layout with
// proper view dimensions. TabStripModel::AddWebContents() contains similar
// logic.
- apps::ResizeWebContents(web_contents,
- browser->window()->GetRestoredBounds().size());
+ gfx::Size size = browser->window()->GetBounds().size();
+ // Fallback to the restore bounds if it's empty as the window is not shown
+ // yet and the bounds may not be available on all platforms.
+ if (size.IsEmpty())
+ size = browser->window()->GetRestoredBounds().size();
+ apps::ResizeWebContents(web_contents, size);
web_contents->WasHidden();
}
SessionService* session_service =
diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h
index cea4db8..c896571 100644
--- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h
+++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h
@@ -135,6 +135,7 @@
virtual SkColor ActiveFrameColor() const OVERRIDE;
virtual SkColor InactiveFrameColor() const OVERRIDE;
virtual gfx::Insets GetFrameInsets() const OVERRIDE;
+ virtual bool CanHaveAlphaEnabled() const OVERRIDE;
// These are used to simulate Mac-style hide/show. Since windows can be hidden
// and shown using the app.window API, this sets is_hidden_with_app_ to
diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm
index 9b45321..e3bdc70 100644
--- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm
+++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm
@@ -799,6 +799,10 @@
return frame_rect.InsetsFrom(content_rect);
}
+bool NativeAppWindowCocoa::CanHaveAlphaEnabled() const {
+ return false;
+}
+
gfx::NativeView NativeAppWindowCocoa::GetHostView() const {
NOTIMPLEMENTED();
return NULL;
diff --git a/chrome/browser/ui/views/app_list/app_list_dialog_contents_view.cc b/chrome/browser/ui/views/app_list/app_list_dialog_contents_view.cc
index a786474..a6d245b 100644
--- a/chrome/browser/ui/views/app_list/app_list_dialog_contents_view.cc
+++ b/chrome/browser/ui/views/app_list/app_list_dialog_contents_view.cc
@@ -154,10 +154,6 @@
return ui::MODAL_TYPE_WINDOW;
}
-ui::AXRole AppListDialogContentsView::GetAccessibleWindowRole() const {
- return ui::AX_ROLE_DIALOG;
-}
-
void AppListDialogContentsView::WindowClosing() {
app_list_controller_delegate_->OnCloseChildDialog();
}
diff --git a/chrome/browser/ui/views/app_list/app_list_dialog_contents_view.h b/chrome/browser/ui/views/app_list/app_list_dialog_contents_view.h
index 51654d4..375af85 100644
--- a/chrome/browser/ui/views/app_list/app_list_dialog_contents_view.h
+++ b/chrome/browser/ui/views/app_list/app_list_dialog_contents_view.h
@@ -6,7 +6,7 @@
#define CHROME_BROWSER_UI_VIEWS_APP_LIST_APP_LIST_DIALOG_CONTENTS_VIEW_H_
#include "ui/views/controls/button/button.h"
-#include "ui/views/widget/widget_delegate.h"
+#include "ui/views/window/dialog_delegate.h"
class AppListControllerDelegate;
@@ -17,7 +17,7 @@
// The contents view for an App List Dialog, which covers the entire app list
// and adds a close button.
-class AppListDialogContentsView : public views::WidgetDelegateView,
+class AppListDialogContentsView : public views::DialogDelegateView,
public views::ButtonListener {
public:
AppListDialogContentsView(
@@ -48,7 +48,6 @@
protected:
// Overridden from views::WidgetDelegate:
virtual ui::ModalType GetModalType() const OVERRIDE;
- virtual ui::AXRole GetAccessibleWindowRole() const OVERRIDE;
virtual void WindowClosing() OVERRIDE;
private:
diff --git a/chrome/browser/ui/views/apps/app_window_desktop_window_tree_host_win.cc b/chrome/browser/ui/views/apps/app_window_desktop_window_tree_host_win.cc
index b2301e6..f6a8139 100644
--- a/chrome/browser/ui/views/apps/app_window_desktop_window_tree_host_win.cc
+++ b/chrome/browser/ui/views/apps/app_window_desktop_window_tree_host_win.cc
@@ -48,6 +48,7 @@
void AppWindowDesktopWindowTreeHostWin::HandleFrameChanged() {
// We need to update the glass region on or off before the base class adjusts
// the window region.
+ app_window_->OnCanHaveAlphaEnabledChanged();
UpdateDWMFrame();
DesktopWindowTreeHostWin::HandleFrameChanged();
}
diff --git a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
index d16820f..2cd8f88 100644
--- a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
@@ -44,22 +45,12 @@
const char kEnrollmentStepSuccess[] = "success";
// Enrollment mode strings.
-const char kEnrollmentModeManual[] = "manual";
-const char kEnrollmentModeForced[] = "forced";
-const char kEnrollmentModeAuto[] = "auto";
+const char* const kModeStrings[EnrollmentScreenActor::ENROLLMENT_MODE_COUNT] =
+ { "manual", "forced", "auto", "recovery" };
std::string EnrollmentModeToString(EnrollmentScreenActor::EnrollmentMode mode) {
- switch (mode) {
- case EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL:
- return kEnrollmentModeManual;
- case EnrollmentScreenActor::ENROLLMENT_MODE_FORCED:
- return kEnrollmentModeForced;
- case EnrollmentScreenActor::ENROLLMENT_MODE_AUTO:
- return kEnrollmentModeAuto;
- }
-
- NOTREACHED() << "Bad enrollment mode " << mode;
- return kEnrollmentModeManual;
+ CHECK(0 <= mode && mode < EnrollmentScreenActor::ENROLLMENT_MODE_COUNT);
+ return kModeStrings[mode];
}
// A helper class that takes care of asynchronously revoking a given token.
diff --git a/chrome/browser/ui/webui/components_ui.cc b/chrome/browser/ui/webui/components_ui.cc
index c439f73..705a755 100644
--- a/chrome/browser/ui/webui/components_ui.cc
+++ b/chrome/browser/ui/webui/components_ui.cc
@@ -241,7 +241,15 @@
void ComponentsUI::OnEvent(Events event, const std::string& id) {
base::DictionaryValue parameters;
parameters.SetString("event", ComponentEventToString(event));
- if (!id.empty())
+ if (!id.empty()) {
+ using component_updater::ComponentUpdateService;
+ if (event == ComponentUpdateService::Observer::COMPONENT_UPDATED) {
+ ComponentUpdateService* cus = g_browser_process->component_updater();
+ component_updater::CrxUpdateItem item;
+ if (cus->GetComponentDetails(id, &item))
+ parameters.SetString("version", item.component.version.GetString());
+ }
parameters.SetString("id", id);
+ }
web_ui()->CallJavascriptFunction("onComponentEvent", parameters);
}
diff --git a/chrome/common/extensions/api/app_current_window_internal.idl b/chrome/common/extensions/api/app_current_window_internal.idl
index a8a1cd5..890e75b 100644
--- a/chrome/common/extensions/api/app_current_window_internal.idl
+++ b/chrome/common/extensions/api/app_current_window_internal.idl
@@ -61,6 +61,7 @@
static void onMinimized();
static void onMaximized();
static void onRestored();
+ static void onAlphaEnabledChanged();
// Only sent in tests.
static void onWindowShownForTests();
};
diff --git a/chrome/common/extensions/api/app_window.idl b/chrome/common/extensions/api/app_window.idl
index b08037b..26922d7 100644
--- a/chrome/common/extensions/api/app_window.idl
+++ b/chrome/common/extensions/api/app_window.idl
@@ -351,6 +351,10 @@
// <code>"alwaysOnTopWindows"</code> permission.
static void setAlwaysOnTop(boolean alwaysOnTop);
+ // Can the window use alpha transparency?
+ // TODO(jackhou): Document this properly before going to stable.
+ [nodoc] static boolean alphaEnabled();
+
// The JavaScript 'window' object for the created child.
[instanceOf=Window] object contentWindow;
@@ -433,6 +437,9 @@
// Fired when the window is restored from being minimized or maximized.
[nocompile] static void onRestored();
+ // Fired when the window's ability to use alpha transparency changes.
+ [nocompile, nodoc] static void onAlphaEnabledChanged();
+
// Event for testing. Lets tests wait until a window has been shown.
[nocompile, nodoc] static void onWindowFirstShown();
};
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 2885c1b..40d16c6 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1649,6 +1649,9 @@
// Customized app page names that appear on the New Tab Page.
const char kNtpAppPageNames[] = "ntp.app_page_names";
+// Keeps track of currently open tabs collapsed state in the Other Devices menu.
+const char kNtpCollapsedCurrentlyOpenTabs[] = "ntp.collapsed_open_tabs";
+
// Keeps track of which sessions are collapsed in the Other Devices menu.
const char kNtpCollapsedForeignSessions[] = "ntp.collapsed_foreign_sessions";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 6e0a457..57f8f05 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -545,6 +545,7 @@
extern const char kDisablePluginFinder[];
extern const char kNtpAppPageNames[];
+extern const char kNtpCollapsedCurrentlyOpenTabs[];
extern const char kNtpCollapsedForeignSessions[];
extern const char kNtpCollapsedRecentlyClosedTabs[];
extern const char kNtpCollapsedSnapshotDocument[];
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 2f58fd2..76133a8 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -444,16 +444,16 @@
std::string /* mime_type */,
ChromeViewHostMsg_GetPluginInfo_Output /* output */)
-// Returns whether any internal plugin supporting |mime_type| is registered
-// Does not determine whether the plugin can actually be instantiated
-// (e.g. whether it is allowed or has all its dependencies).
-// When the returned *|is_registered| is true, |additional_param_names| and
+// Returns whether any internal plugin supporting |mime_type| is registered and
+// enabled. Does not determine whether the plugin can actually be instantiated
+// (e.g. whether it has all its dependencies).
+// When the returned *|is_available| is true, |additional_param_names| and
// |additional_param_values| contain the name-value pairs, if any, specified
-// for the *first* plugin found that is registered for |mime_type|.
+// for the *first* non-disabled plugin found that is registered for |mime_type|.
IPC_SYNC_MESSAGE_CONTROL1_3(
- ChromeViewHostMsg_IsInternalPluginRegisteredForMimeType,
+ ChromeViewHostMsg_IsInternalPluginAvailableForMimeType,
std::string /* mime_type */,
- bool /* registered */,
+ bool /* is_available */,
std::vector<base::string16> /* additional_param_names */,
std::vector<base::string16> /* additional_param_values */)
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index 8556201..49fd44b 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -655,6 +655,7 @@
const char* const kChromeDebugURLs[] = {
content::kChromeUICrashURL,
+ content::kChromeUIDumpURL,
content::kChromeUIKillURL,
content::kChromeUIHangURL,
content::kChromeUIShorthangURL,
diff --git a/chrome/renderer/media/chrome_key_systems.cc b/chrome/renderer/media/chrome_key_systems.cc
index e8099fb..c15d493 100644
--- a/chrome/renderer/media/chrome_key_systems.cc
+++ b/chrome/renderer/media/chrome_key_systems.cc
@@ -32,19 +32,19 @@
using content::SupportedCodecs;
#if defined(ENABLE_PEPPER_CDMS)
-static bool IsPepperCdmRegistered(
+static bool IsPepperCdmAvailable(
const std::string& pepper_type,
std::vector<base::string16>* additional_param_names,
std::vector<base::string16>* additional_param_values) {
- bool is_registered = false;
+ bool is_available = false;
content::RenderThread::Get()->Send(
- new ChromeViewHostMsg_IsInternalPluginRegisteredForMimeType(
+ new ChromeViewHostMsg_IsInternalPluginAvailableForMimeType(
pepper_type,
- &is_registered,
+ &is_available,
additional_param_names,
additional_param_values));
- return is_registered;
+ return is_available;
}
// External Clear Key (used for testing).
@@ -65,9 +65,9 @@
std::vector<base::string16> additional_param_names;
std::vector<base::string16> additional_param_values;
- if (!IsPepperCdmRegistered(kExternalClearKeyPepperType,
- &additional_param_names,
- &additional_param_values)) {
+ if (!IsPepperCdmAvailable(kExternalClearKeyPepperType,
+ &additional_param_names,
+ &additional_param_values)) {
return;
}
@@ -141,9 +141,9 @@
std::vector<base::string16> additional_param_names;
std::vector<base::string16> additional_param_values;
- if (!IsPepperCdmRegistered(kWidevineCdmPluginMimeType,
- &additional_param_names,
- &additional_param_values)) {
+ if (!IsPepperCdmAvailable(kWidevineCdmPluginMimeType,
+ &additional_param_names,
+ &additional_param_values)) {
DVLOG(1) << "Widevine CDM is not currently available.";
return;
}
diff --git a/chrome/renderer/printing/print_web_view_helper.cc b/chrome/renderer/printing/print_web_view_helper.cc
index 22005ec..47bc09e 100644
--- a/chrome/renderer/printing/print_web_view_helper.cc
+++ b/chrome/renderer/printing/print_web_view_helper.cc
@@ -1703,13 +1703,10 @@
// |is_modifiable| value until they are fully loaded, which occurs when
// DidStopLoading() is called. Defer showing the preview until then.
} else {
- // TODO(japhet): This delay is a terrible hack. See crbug.com/376969
- // for the motivation.
- base::MessageLoop::current()->PostDelayedTask(
+ base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&PrintWebViewHelper::ShowScriptedPrintPreview,
- weak_ptr_factory_.GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(100));
+ weak_ptr_factory_.GetWeakPtr()));
}
IPC::SyncMessage* msg =
new PrintHostMsg_SetupScriptedPrintPreview(routing_id());
diff --git a/chrome/renderer/resources/extensions/app_window_custom_bindings.js b/chrome/renderer/resources/extensions/app_window_custom_bindings.js
index 99ca8bc..c666d32 100644
--- a/chrome/renderer/resources/extensions/app_window_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/app_window_custom_bindings.js
@@ -241,6 +241,9 @@
AppWindow.prototype.isAlwaysOnTop = function() {
return appWindowData.alwaysOnTop;
};
+ AppWindow.prototype.alphaEnabled = function() {
+ return appWindowData.alphaEnabled;
+ }
AppWindow.prototype.handleWindowFirstShownForTests = function(callback) {
// This allows test apps to get have their callback run even if they
// call this after the first show has happened.
@@ -301,7 +304,8 @@
alwaysOnTop: params.alwaysOnTop,
hasFrameColor: params.hasFrameColor,
activeFrameColor: params.activeFrameColor,
- inactiveFrameColor: params.inactiveFrameColor
+ inactiveFrameColor: params.inactiveFrameColor,
+ alphaEnabled: params.alphaEnabled
};
currentAppWindow = new AppWindow;
});
@@ -348,6 +352,9 @@
(oldData.minimized && !update.minimized) ||
(oldData.maximized && !update.maximized))
dispatchEventIfExists(currentWindow, "onRestored");
+
+ if (oldData.alphaEnabled !== update.alphaEnabled)
+ dispatchEventIfExists(currentWindow, "onAlphaEnabledChanged");
};
function onAppWindowShownForTests() {
diff --git a/chrome/test/base/chrome_unit_test_suite.cc b/chrome/test/base/chrome_unit_test_suite.cc
index 9e40a65..ca239cd 100644
--- a/chrome/test/base/chrome_unit_test_suite.cc
+++ b/chrome/test/base/chrome_unit_test_suite.cc
@@ -6,7 +6,6 @@
#include "base/path_service.h"
#include "base/process/process_handle.h"
-#include "base/metrics/stats_table.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/common/chrome_content_client.h"
@@ -98,12 +97,6 @@
InitializeProviders();
RegisterInProcessThreads();
- // Create an anonymous stats table since we don't need to share between
- // processes.
- stats_table_.reset(
- new base::StatsTable(base::StatsTable::TableIdentifier(), 20, 200));
- base::StatsTable::set_current(stats_table_.get());
-
ChromeTestSuite::Initialize();
// This needs to run after ChromeTestSuite::Initialize which calls content's
@@ -113,10 +106,6 @@
void ChromeUnitTestSuite::Shutdown() {
ResourceBundle::CleanupSharedInstance();
-
- base::StatsTable::set_current(NULL);
- stats_table_.reset();
-
ChromeTestSuite::Shutdown();
}
diff --git a/chrome/test/base/chrome_unit_test_suite.h b/chrome/test/base/chrome_unit_test_suite.h
index 0ac9eb4..1c1ddbd 100644
--- a/chrome/test/base/chrome_unit_test_suite.h
+++ b/chrome/test/base/chrome_unit_test_suite.h
@@ -10,10 +10,6 @@
#include "base/files/file_path.h"
#include "chrome/test/base/chrome_test_suite.h"
-namespace base {
-class StatsTable;
-}
-
// Test suite for unit tests. Creates additional stub services that are not
// needed for browser tests (e.g. a TestingBrowserProcess).
class ChromeUnitTestSuite : public ChromeTestSuite {
@@ -32,7 +28,6 @@
static void InitializeResourceBundle();
private:
- scoped_ptr<base::StatsTable> stats_table_;
DISALLOW_COPY_AND_ASSIGN(ChromeUnitTestSuite);
};
diff --git a/components/breakpad/app/breakpad_win.cc b/components/breakpad/app/breakpad_win.cc
index 1f6a3c4..56c4cf9 100644
--- a/components/breakpad/app/breakpad_win.cc
+++ b/components/breakpad/app/breakpad_win.cc
@@ -573,6 +573,10 @@
google_breakpad::ExceptionHandler::HANDLER_NONE,
dump_type, pipe_name.c_str(), custom_info);
+ // Set the DumpWithoutCrashingFunction for this instance of base.lib. Other
+ // executable images linked with base should set this again for
+ // DumpWithoutCrashing to function correctly.
+ // See chrome_main.cc for example.
base::debug::SetDumpWithoutCrashingFunction(&DumpProcessWithoutCrash);
if (g_breakpad->IsOutOfProcess()) {
diff --git a/components/policy/core/common/cloud/enterprise_metrics.cc b/components/policy/core/common/cloud/enterprise_metrics.cc
index 12394fa..b541e80 100644
--- a/components/policy/core/common/cloud/enterprise_metrics.cc
+++ b/components/policy/core/common/cloud/enterprise_metrics.cc
@@ -9,6 +9,7 @@
const char kMetricToken[] = "Enterprise.DMToken";
const char kMetricPolicy[] = "Enterprise.Policy";
const char kMetricEnrollment[] = "Enterprise.Enrollment";
+const char kMetricEnrollmentRecovery[] = "Enterprise.EnrollmentRecovery";
const char kMetricPolicyRefresh[] = "Enterprise.PolicyRefresh";
const char kMetricPolicyInvalidations[] = "Enterprise.PolicyInvalidations";
diff --git a/components/policy/core/common/cloud/enterprise_metrics.h b/components/policy/core/common/cloud/enterprise_metrics.h
index daac653..79bdcf1 100644
--- a/components/policy/core/common/cloud/enterprise_metrics.h
+++ b/components/policy/core/common/cloud/enterprise_metrics.h
@@ -167,6 +167,10 @@
kMetricEnrollmentDeprovisioned,
// Enrollment failed because the device doesn't belong to the domain.
kMetricEnrollmentDomainMismatch,
+ // Enrollment has been triggered, the credential screen has been shown.
+ kMetricEnrollmentTriggered,
+ // The user retried to submitted credentials.
+ kMetricEnrollmentRetried,
kMetricEnrollmentSize // Must be the last.
};
@@ -212,6 +216,7 @@
POLICY_EXPORT extern const char kMetricToken[];
POLICY_EXPORT extern const char kMetricPolicy[];
POLICY_EXPORT extern const char kMetricEnrollment[];
+POLICY_EXPORT extern const char kMetricEnrollmentRecovery[];
POLICY_EXPORT extern const char kMetricPolicyRefresh[];
POLICY_EXPORT extern const char kMetricPolicyInvalidations[];
diff --git a/content/browser/frame_host/debug_urls.cc b/content/browser/frame_host/debug_urls.cc
index 733f899..ae454ae 100644
--- a/content/browser/frame_host/debug_urls.cc
+++ b/content/browser/frame_host/debug_urls.cc
@@ -174,6 +174,7 @@
return true;
return url == GURL(kChromeUICrashURL) ||
+ url == GURL(kChromeUIDumpURL) ||
url == GURL(kChromeUIKillURL) ||
url == GURL(kChromeUIHangURL) ||
url == GURL(kChromeUIShorthangURL);
diff --git a/content/browser/media/media_canplaytype_browsertest.cc b/content/browser/media/media_canplaytype_browsertest.cc
index 87d9969..cfcfd5a 100644
--- a/content/browser/media/media_canplaytype_browsertest.cc
+++ b/content/browser/media/media_canplaytype_browsertest.cc
@@ -358,9 +358,13 @@
EXPECT_EQ(kNot, CanPlay("'video/mpeg'"));
EXPECT_EQ(kNot, CanPlay("'video/x-mp3'"));
- // audio/mpeg does not allow any codecs parameter
+ // audio/mpeg without a codecs parameter (RFC 3003 compliant)
EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg'"));
+ // audio/mpeg with mp3 in codecs parameter. (Not RFC compliant, but
+ // very common in the wild so it is a defacto standard).
+ EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"mp3\"'"));
+
EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc1\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc3\"'"));
diff --git a/content/browser/renderer_host/compositing_iosurface_layer_mac.h b/content/browser/renderer_host/compositing_iosurface_layer_mac.h
index 9103314..0449ae7 100644
--- a/content/browser/renderer_host/compositing_iosurface_layer_mac.h
+++ b/content/browser/renderer_host/compositing_iosurface_layer_mac.h
@@ -64,6 +64,8 @@
// Called when a new frame is received.
- (void)gotNewFrame;
+- (void)setNeedsDisplayAndDisplayAndAck;
+- (void)displayIfNeededAndAck;
@end
#endif // CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_LAYER_MAC_H_
diff --git a/content/browser/renderer_host/compositing_iosurface_layer_mac.mm b/content/browser/renderer_host/compositing_iosurface_layer_mac.mm
index 040d8f9..bda4c5f 100644
--- a/content/browser/renderer_host/compositing_iosurface_layer_mac.mm
+++ b/content/browser/renderer_host/compositing_iosurface_layer_mac.mm
@@ -18,7 +18,6 @@
#include "ui/gl/gpu_switching_manager.h"
@interface CompositingIOSurfaceLayer(Private)
-- (void)immediatelyForceDisplayAndAck;
- (void)ackPendingFrame:(bool)success;
- (void)timerFired;
@end
@@ -101,7 +100,7 @@
if (context_ && context_->is_vsync_disabled()) {
// If vsync is disabled, draw immediately and don't bother trying to use
// the isAsynchronous property to ensure smooth animation.
- [self immediatelyForceDisplayAndAck];
+ [self setNeedsDisplayAndDisplayAndAck];
} else {
needs_display_ = YES;
if (![self isAsynchronous])
@@ -111,8 +110,20 @@
// Private methods:
-- (void)immediatelyForceDisplayAndAck {
+- (void)setNeedsDisplayAndDisplayAndAck {
+ // Workaround for crbug.com/395827
+ if ([self isAsynchronous])
+ [self setAsynchronous:NO];
+
[self setNeedsDisplay];
+ [self displayIfNeededAndAck];
+}
+
+- (void)displayIfNeededAndAck {
+ // Workaround for crbug.com/395827
+ if ([self isAsynchronous])
+ [self setAsynchronous:NO];
+
[self displayIfNeeded];
// Calls to setNeedsDisplay can sometimes be ignored, especially if issued
@@ -134,7 +145,7 @@
- (void)timerFired {
if (has_pending_frame_)
- [self immediatelyForceDisplayAndAck];
+ [self setNeedsDisplayAndDisplayAndAck];
}
// The remaining methods implement the CAOpenGLLayer interface.
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 6232bcd..47f037d 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -341,9 +341,14 @@
}
void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) {
- root_layer_->RemoveAllChildren();
- if (root_layer)
+ if (subroot_layer_) {
+ subroot_layer_->RemoveFromParent();
+ subroot_layer_ = NULL;
+ }
+ if (root_layer) {
+ subroot_layer_ = root_layer;
root_layer_->AddChild(root_layer);
+ }
}
void CompositorImpl::SetWindowSurface(ANativeWindow* window) {
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h
index e3cc42e..4792d90 100644
--- a/content/browser/renderer_host/compositor_impl_android.h
+++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -132,7 +132,11 @@
bool is_transient);
void OnGpuChannelEstablished();
+ // root_layer_ is the persistent internal root layer, while subroot_layer_
+ // is the one attached by the compositor client.
scoped_refptr<cc::Layer> root_layer_;
+ scoped_refptr<cc::Layer> subroot_layer_;
+
scoped_ptr<cc::LayerTreeHost> host_;
content::UIResourceProviderImpl ui_resource_provider_;
diff --git a/content/browser/renderer_host/input/input_router.h b/content/browser/renderer_host/input/input_router.h
index bb3bd03..1b30815 100644
--- a/content/browser/renderer_host/input/input_router.h
+++ b/content/browser/renderer_host/input/input_router.h
@@ -63,6 +63,8 @@
MOBILE_VIEWPORT = 1 << 1
};
virtual void OnViewUpdated(int view_flags) = 0;
+
+ virtual bool HasPendingEvents() const = 0;
};
} // namespace content
diff --git a/content/browser/renderer_host/input/input_router_impl.h b/content/browser/renderer_host/input/input_router_impl.h
index b49c778..e06113b 100644
--- a/content/browser/renderer_host/input/input_router_impl.h
+++ b/content/browser/renderer_host/input/input_router_impl.h
@@ -74,6 +74,7 @@
virtual const NativeWebKeyboardEvent* GetLastKeyboardEvent() const OVERRIDE;
virtual bool ShouldForwardTouchEvent() const OVERRIDE;
virtual void OnViewUpdated(int view_flags) OVERRIDE;
+ virtual bool HasPendingEvents() const OVERRIDE;
// IPC::Listener
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
@@ -205,8 +206,6 @@
// all events have been dispatched (i.e., |HasPendingEvents()| is false).
void SignalFlushedIfNecessary();
- bool HasPendingEvents() const;
-
bool IsInOverscrollGesture() const;
int routing_id() const { return routing_id_; }
diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.cc b/content/browser/renderer_host/legacy_render_widget_host_win.cc
index 2be9ec7..86799c9 100644
--- a/content/browser/renderer_host/legacy_render_widget_host_win.cc
+++ b/content/browser/renderer_host/legacy_render_widget_host_win.cc
@@ -25,9 +25,6 @@
// accessibility support.
const int kIdScreenReaderHoneyPot = 1;
-// A version of the OBJID_CLIENT constant that works in 64-bit mode too.
-static const LPARAM kObjIdClient = static_cast<ULONG>(OBJID_CLIENT);
-
LegacyRenderWidgetHostHWND::~LegacyRenderWidgetHostHWND() {
::DestroyWindow(hwnd());
}
@@ -138,14 +135,18 @@
LRESULT LegacyRenderWidgetHostHWND::OnGetObject(UINT message,
WPARAM w_param,
LPARAM l_param) {
- if (kIdScreenReaderHoneyPot == l_param) {
+ // Only the lower 32 bits of l_param are valid when checking the object id
+ // because it sometimes gets sign-extended incorrectly (but not always).
+ DWORD obj_id = static_cast<DWORD>(static_cast<DWORD_PTR>(l_param));
+
+ if (kIdScreenReaderHoneyPot == obj_id) {
// When an MSAA client has responded to our fake event on this id,
// enable screen reader support.
BrowserAccessibilityState::GetInstance()->OnScreenReaderDetected();
return static_cast<LRESULT>(0L);
}
- if (kObjIdClient != l_param || !manager_)
+ if (OBJID_CLIENT != obj_id || !manager_)
return static_cast<LRESULT>(0L);
base::win::ScopedComPtr<IAccessible> root(
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 52a3890..a0037f3 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -1189,10 +1189,6 @@
waiting_for_screen_rects_ack_ = false;
- // Reset to ensure that input routing works with a new renderer.
- input_router_.reset(new InputRouterImpl(
- process_, this, this, routing_id_, GetInputRouterConfigForPlatform()));
-
// Must reset these to ensure that keyboard events work with a new renderer.
suppress_next_char_events_ = false;
@@ -1211,6 +1207,13 @@
view_ = NULL; // The View should be deleted by RenderProcessGone.
}
+ // Reconstruct the input router to ensure that it has fresh state for a new
+ // renderer. Otherwise it may be stuck waiting for the old renderer to ack an
+ // event. (In particular, the above call to view_->RenderProcessGone will
+ // destroy the aura window, which may dispatch a synthetic mouse move.)
+ input_router_.reset(new InputRouterImpl(
+ process_, this, this, routing_id_, GetInputRouterConfigForPlatform()));
+
synthetic_gesture_controller_.reset();
}
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index 0e6a9d1..710719c 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -104,6 +104,7 @@
}
virtual bool ShouldForwardTouchEvent() const OVERRIDE { return true; }
virtual void OnViewUpdated(int view_flags) OVERRIDE {}
+ virtual bool HasPendingEvents() const OVERRIDE { return false; }
// IPC::Listener
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
@@ -327,6 +328,17 @@
return mock_physical_backing_size_;
return TestRenderWidgetHostView::GetPhysicalBackingSize();
}
+#if defined(USE_AURA)
+ virtual ~TestView() {
+ // Simulate the mouse exit event dispatched when an aura window is
+ // destroyed. (MakeWebMouseEventFromAuraEvent translates ET_MOUSE_EXITED
+ // into WebInputEvent::MouseMove.)
+ rwh_->input_router()->SendMouseEvent(
+ MouseEventWithLatencyInfo(
+ SyntheticWebMouseEventBuilder::Build(WebInputEvent::MouseMove),
+ ui::LatencyInfo()));
+ }
+#endif
protected:
WebMouseWheelEvent unhandled_wheel_event_;
@@ -1416,4 +1428,13 @@
SendInputEventACK(WebInputEvent::TouchStart, INPUT_EVENT_ACK_STATE_CONSUMED);
}
+TEST_F(RenderWidgetHostTest, RendererExitedResetsInputRouter) {
+ // RendererExited will delete the view.
+ host_->SetView(new TestView(host_.get()));
+ host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
+
+ // Make sure the input router is in a fresh state.
+ ASSERT_FALSE(host_->input_router()->HasPendingEvents());
+}
+
} // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index dce9a5e..553ded7 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -800,6 +800,9 @@
// Call setNeedsDisplay before pausing for new frames to come in -- if any
// do, and are drawn, then the needsDisplay bit will be cleared.
+ // Workaround for crbug.com/395827
+ if ([compositing_iosurface_layer_ isAsynchronous])
+ [compositing_iosurface_layer_ setAsynchronous:NO];
[compositing_iosurface_layer_ setNeedsDisplay];
PauseForPendingResizeOrRepaintsAndDraw();
}
@@ -1698,8 +1701,8 @@
}
void RenderWidgetHostViewMac::AcceleratedSurfaceSuspend() {
- if (compositing_iosurface_)
- compositing_iosurface_->UnrefIOSurface();
+ if (!render_widget_host_->is_hidden())
+ DestroyCompositedIOSurfaceAndLayer();
}
void RenderWidgetHostViewMac::AcceleratedSurfaceRelease() {
@@ -2173,7 +2176,7 @@
// to keep the window and the window's contents in sync.
[cocoa_view_ displayIfNeeded];
[software_layer_ displayIfNeeded];
- [compositing_iosurface_layer_ displayIfNeeded];
+ [compositing_iosurface_layer_ displayIfNeededAndAck];
}
void RenderWidgetHostViewMac::LayoutLayers() {
@@ -2224,8 +2227,10 @@
// displayed. Calling displayIfNeeded will ensure that the right size
// frame is drawn to the screen.
// http://crbug.com/350817
- [compositing_iosurface_layer_ setNeedsDisplay];
- [compositing_iosurface_layer_ displayIfNeeded];
+ // Workaround for crbug.com/395827
+ if ([compositing_iosurface_layer_ isAsynchronous])
+ [compositing_iosurface_layer_ setAsynchronous:NO];
+ [compositing_iosurface_layer_ setNeedsDisplayAndDisplayAndAck];
}
}
diff --git a/content/content_browser.target.darwin-arm.mk b/content/content_browser.target.darwin-arm.mk
index 11fe636..c65a2d6 100644
--- a/content/content_browser.target.darwin-arm.mk
+++ b/content/content_browser.target.darwin-arm.mk
@@ -680,6 +680,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -870,6 +871,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.darwin-arm64.mk b/content/content_browser.target.darwin-arm64.mk
index 429d5ae..3a28f73 100644
--- a/content/content_browser.target.darwin-arm64.mk
+++ b/content/content_browser.target.darwin-arm64.mk
@@ -669,6 +669,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -847,6 +848,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.darwin-mips.mk b/content/content_browser.target.darwin-mips.mk
index dafd7a6..d1b3523 100644
--- a/content/content_browser.target.darwin-mips.mk
+++ b/content/content_browser.target.darwin-mips.mk
@@ -674,6 +674,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -858,6 +859,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.darwin-x86.mk b/content/content_browser.target.darwin-x86.mk
index 8a84133..9358c7e 100644
--- a/content/content_browser.target.darwin-x86.mk
+++ b/content/content_browser.target.darwin-x86.mk
@@ -674,6 +674,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -857,6 +858,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.darwin-x86_64.mk b/content/content_browser.target.darwin-x86_64.mk
index 92cc0a8..c84ecec 100644
--- a/content/content_browser.target.darwin-x86_64.mk
+++ b/content/content_browser.target.darwin-x86_64.mk
@@ -674,6 +674,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -857,6 +858,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.linux-arm.mk b/content/content_browser.target.linux-arm.mk
index 11fe636..c65a2d6 100644
--- a/content/content_browser.target.linux-arm.mk
+++ b/content/content_browser.target.linux-arm.mk
@@ -680,6 +680,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -870,6 +871,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.linux-arm64.mk b/content/content_browser.target.linux-arm64.mk
index 429d5ae..3a28f73 100644
--- a/content/content_browser.target.linux-arm64.mk
+++ b/content/content_browser.target.linux-arm64.mk
@@ -669,6 +669,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -847,6 +848,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.linux-mips.mk b/content/content_browser.target.linux-mips.mk
index dafd7a6..d1b3523 100644
--- a/content/content_browser.target.linux-mips.mk
+++ b/content/content_browser.target.linux-mips.mk
@@ -674,6 +674,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -858,6 +859,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.linux-x86.mk b/content/content_browser.target.linux-x86.mk
index 8a84133..9358c7e 100644
--- a/content/content_browser.target.linux-x86.mk
+++ b/content/content_browser.target.linux-x86.mk
@@ -674,6 +674,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -857,6 +858,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.linux-x86_64.mk b/content/content_browser.target.linux-x86_64.mk
index 92cc0a8..c84ecec 100644
--- a/content/content_browser.target.linux-x86_64.mk
+++ b/content/content_browser.target.linux-x86_64.mk
@@ -674,6 +674,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -857,6 +858,7 @@
$(LOCAL_PATH)/third_party/leveldatabase/src/include \
$(LOCAL_PATH)/third_party/leveldatabase/src \
$(LOCAL_PATH)/third_party/leveldatabase \
+ $(gyp_shared_intermediate_dir)/angle \
$(LOCAL_PATH)/third_party/WebKit \
$(LOCAL_PATH)/third_party/npapi \
$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/public/common/url_constants.cc b/content/public/common/url_constants.cc
index a19b8b1..ac65ded 100644
--- a/content/public/common/url_constants.cc
+++ b/content/public/common/url_constants.cc
@@ -33,6 +33,7 @@
const char kChromeUIWebRTCInternalsHost[] = "webrtc-internals";
const char kChromeUICrashURL[] = "chrome://crash";
+const char kChromeUIDumpURL[] = "chrome://crashdump";
const char kChromeUIGpuCleanURL[] = "chrome://gpuclean";
const char kChromeUIGpuCrashURL[] = "chrome://gpucrash";
const char kChromeUIGpuHangURL[] = "chrome://gpuhang";
diff --git a/content/public/common/url_constants.h b/content/public/common/url_constants.h
index d1d0ddc..7f125f7 100644
--- a/content/public/common/url_constants.h
+++ b/content/public/common/url_constants.h
@@ -42,6 +42,7 @@
// Full about URLs (including schemes).
CONTENT_EXPORT extern const char kChromeUICrashURL[];
+CONTENT_EXPORT extern const char kChromeUIDumpURL[];
CONTENT_EXPORT extern const char kChromeUIGpuCleanURL[];
CONTENT_EXPORT extern const char kChromeUIGpuCrashURL[];
CONTENT_EXPORT extern const char kChromeUIGpuHangURL[];
diff --git a/content/renderer/media/crypto/key_systems.cc b/content/renderer/media/crypto/key_systems.cc
index 6cd8218..dace751 100644
--- a/content/renderer/media/crypto/key_systems.cc
+++ b/content/renderer/media/crypto/key_systems.cc
@@ -10,6 +10,8 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
+#include "base/threading/thread_checker.h"
+#include "base/time/time.h"
#include "content/public/common/content_client.h"
#include "content/public/common/eme_codec.h"
#include "content/public/renderer/content_renderer_client.h"
@@ -87,6 +89,8 @@
public:
static KeySystems& GetInstance();
+ void UpdateIfNeeded();
+
bool IsConcreteSupportedKeySystem(const std::string& key_system);
bool IsSupportedKeySystemWithMediaMimeType(
@@ -104,6 +108,8 @@
void AddCodecMask(const std::string& codec, uint32 mask);
private:
+ void UpdateSupportedKeySystems();
+
void AddConcreteSupportedKeySystems(
const std::vector<KeySystemInfo>& concrete_key_systems);
@@ -161,18 +167,26 @@
CodecMaskMap container_codec_masks_;
CodecMaskMap codec_masks_;
+ bool needs_update_;
+ base::Time last_update_time_;
+
+ // Makes sure all methods are called from the same thread.
+ base::ThreadChecker thread_checker_;
+
DISALLOW_COPY_AND_ASSIGN(KeySystems);
};
static base::LazyInstance<KeySystems> g_key_systems = LAZY_INSTANCE_INITIALIZER;
KeySystems& KeySystems::GetInstance() {
- return g_key_systems.Get();
+ KeySystems& key_systems = g_key_systems.Get();
+ key_systems.UpdateIfNeeded();
+ return key_systems;
}
// Because we use a LazyInstance, the key systems info must be populated when
// the instance is lazily initiated.
-KeySystems::KeySystems() {
+KeySystems::KeySystems() : needs_update_(true) {
// Build container and codec masks for quick look up.
for (size_t i = 0; i < arraysize(kContainerCodecMasks); ++i) {
const CodecMask& container_codec_mask = kContainerCodecMasks[i];
@@ -187,18 +201,60 @@
codec_masks_[codec_mask.type] = codec_mask.mask;
}
- std::vector<KeySystemInfo> key_systems_info;
- GetContentClient()->renderer()->AddKeySystems(&key_systems_info);
- // Clear Key is always supported.
- AddClearKey(&key_systems_info);
- AddConcreteSupportedKeySystems(key_systems_info);
+ UpdateSupportedKeySystems();
+
#if defined(WIDEVINE_CDM_AVAILABLE)
key_systems_support_uma_.AddKeySystemToReport(kWidevineKeySystem);
#endif // defined(WIDEVINE_CDM_AVAILABLE)
}
+void KeySystems::UpdateIfNeeded() {
+#if defined(WIDEVINE_CDM_AVAILABLE) && defined(WIDEVINE_CDM_IS_COMPONENT)
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!needs_update_)
+ return;
+
+ // The update could involve a sync IPC to the browser process. Use a minimum
+ // update interval to avoid unnecessary frequent IPC to the browser.
+ static const int kMinUpdateIntervalInSeconds = 5;
+ base::Time now = base::Time::Now();
+ if (now - last_update_time_ <
+ base::TimeDelta::FromSeconds(kMinUpdateIntervalInSeconds)) {
+ return;
+ }
+
+ UpdateSupportedKeySystems();
+#endif
+}
+
+void KeySystems::UpdateSupportedKeySystems() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(needs_update_);
+ concrete_key_system_map_.clear();
+ parent_key_system_map_.clear();
+
+ // Build KeySystemInfo.
+ std::vector<KeySystemInfo> key_systems_info;
+ GetContentClient()->renderer()->AddKeySystems(&key_systems_info);
+ // Clear Key is always supported.
+ AddClearKey(&key_systems_info);
+
+ AddConcreteSupportedKeySystems(key_systems_info);
+
+#if defined(WIDEVINE_CDM_AVAILABLE) && defined(WIDEVINE_CDM_IS_COMPONENT)
+ if (IsConcreteSupportedKeySystem(kWidevineKeySystem))
+ needs_update_ = false;
+#endif
+
+ last_update_time_ = base::Time::Now();
+}
+
void KeySystems::AddConcreteSupportedKeySystems(
const std::vector<KeySystemInfo>& concrete_key_systems) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(concrete_key_system_map_.empty());
+ DCHECK(parent_key_system_map_.empty());
+
for (size_t i = 0; i < concrete_key_systems.size(); ++i) {
const KeySystemInfo& key_system_info = concrete_key_systems[i];
AddConcreteSupportedKeySystem(key_system_info.key_system,
@@ -219,6 +275,7 @@
#endif
SupportedCodecs supported_codecs,
const std::string& parent_key_system) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!IsConcreteSupportedKeySystem(concrete_key_system))
<< "Key system '" << concrete_key_system << "' already registered";
DCHECK(parent_key_system_map_.find(concrete_key_system) ==
@@ -247,6 +304,7 @@
}
bool KeySystems::IsConcreteSupportedKeySystem(const std::string& key_system) {
+ DCHECK(thread_checker_.CalledOnValidThread());
return concrete_key_system_map_.find(key_system) !=
concrete_key_system_map_.end();
}
@@ -254,6 +312,7 @@
bool KeySystems::IsSupportedContainer(
const std::string& container,
SupportedCodecs key_system_supported_codecs) const {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!container.empty());
// When checking container support for EME, "audio/foo" should be treated the
@@ -280,6 +339,7 @@
const std::string& container,
const std::vector<std::string>& codecs,
SupportedCodecs key_system_supported_codecs) const {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!container.empty());
DCHECK(!codecs.empty());
DCHECK(IsSupportedContainer(container, key_system_supported_codecs));
@@ -312,6 +372,8 @@
const std::string& mime_type,
const std::vector<std::string>& codecs,
const std::string& key_system) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
// If |key_system| is a parent key_system, use its concrete child.
// Otherwise, use |key_system|.
std::string concrete_key_system;
@@ -356,6 +418,8 @@
}
bool KeySystems::UseAesDecryptor(const std::string& concrete_key_system) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
KeySystemPropertiesMap::iterator key_system_iter =
concrete_key_system_map_.find(concrete_key_system);
if (key_system_iter == concrete_key_system_map_.end()) {
@@ -368,6 +432,8 @@
#if defined(ENABLE_PEPPER_CDMS)
std::string KeySystems::GetPepperType(const std::string& concrete_key_system) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
KeySystemPropertiesMap::iterator key_system_iter =
concrete_key_system_map_.find(concrete_key_system);
if (key_system_iter == concrete_key_system_map_.end()) {
@@ -382,13 +448,17 @@
#endif
void KeySystems::AddContainerMask(const std::string& container, uint32 mask) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(container_codec_masks_.find(container) ==
container_codec_masks_.end());
+
container_codec_masks_[container] = static_cast<EmeCodec>(mask);
}
void KeySystems::AddCodecMask(const std::string& codec, uint32 mask) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(codec_masks_.find(codec) == codec_masks_.end());
+
codec_masks_[codec] = static_cast<EmeCodec>(mask);
}
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index fc74021..65c8b7a 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -287,6 +287,12 @@
return;
if (url == GURL(kChromeUICrashURL)) {
CrashIntentionally();
+ } else if (url == GURL(kChromeUIDumpURL)) {
+ // This URL will only correctly create a crash dump file if content is
+ // hosted in a process that has correctly called
+ // base::debug::SetDumpWithoutCrashingFunction. Refer to the documentation
+ // of base::debug::DumpWithoutCrashing for more details.
+ base::debug::DumpWithoutCrashing();
} else if (url == GURL(kChromeUIKillURL)) {
base::KillProcess(base::GetCurrentProcessHandle(), 1, false);
} else if (url == GURL(kChromeUIHangURL)) {
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index c0b60f6..381b96c 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -307,7 +307,7 @@
if (host != common_host_) {
common_host_ = host;
common_host_histogram_suffix_ = HostToCustomHistogramSuffix(host);
- v8::V8::SetCreateHistogramFunction(CreateHistogram);
+ blink::mainThreadIsolate()->SetCreateHistogramFunction(CreateHistogram);
}
}
@@ -333,10 +333,6 @@
base::PlatformThread::CurrentId(),
kTraceEventRendererMainThreadSortIndex);
- v8::V8::SetCounterFunction(base::StatsTable::FindLocation);
- v8::V8::SetCreateHistogramFunction(CreateHistogram);
- v8::V8::SetAddHistogramSampleFunction(AddHistogramSample);
-
#if defined(OS_MACOSX) || defined(OS_ANDROID)
// On Mac and Android, the select popups are rendered by the browser.
blink::WebView::setUseExternalPopupMenus(true);
@@ -737,6 +733,12 @@
webkit_platform_support_.reset(new RendererWebKitPlatformSupportImpl);
blink::initialize(webkit_platform_support_.get());
+ v8::Isolate* isolate = blink::mainThreadIsolate();
+
+ isolate->SetCounterFunction(base::StatsTable::FindLocation);
+ isolate->SetCreateHistogramFunction(CreateHistogram);
+ isolate->SetAddHistogramSampleFunction(AddHistogramSample);
+
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
bool enable = command_line.HasSwitch(switches::kEnableThreadedCompositing);
diff --git a/content/test/test_webkit_platform_support.cc b/content/test/test_webkit_platform_support.cc
index 0e9aaf0..a55ebf6 100644
--- a/content/test/test_webkit_platform_support.cc
+++ b/content/test/test_webkit_platform_support.cc
@@ -42,9 +42,16 @@
TestWebKitPlatformSupport::TestWebKitPlatformSupport() {
url_loader_factory_.reset(new WebURLLoaderMockFactory());
mock_clipboard_.reset(new MockWebClipboardImpl());
- v8::V8::SetCounterFunction(base::StatsTable::FindLocation);
+
+ // Create an anonymous stats table since we don't need to share between
+ // processes.
+ stats_table_.reset(
+ new base::StatsTable(base::StatsTable::TableIdentifier(), 20, 200));
+ base::StatsTable::set_current(stats_table_.get());
blink::initialize(this);
+ blink::mainThreadIsolate()->SetCounterFunction(
+ base::StatsTable::FindLocation);
blink::setLayoutTestMode(true);
blink::WebSecurityPolicy::registerURLSchemeAsLocal(
blink::WebString::fromUTF8("test-shell-resource"));
@@ -97,6 +104,8 @@
url_loader_factory_.reset();
mock_clipboard_.reset();
blink::shutdown();
+ base::StatsTable::set_current(NULL);
+ stats_table_.reset();
}
blink::WebMimeRegistry* TestWebKitPlatformSupport::mimeRegistry() {
diff --git a/content/test/test_webkit_platform_support.h b/content/test/test_webkit_platform_support.h
index 469d6bf..3c983dc 100644
--- a/content/test/test_webkit_platform_support.h
+++ b/content/test/test_webkit_platform_support.h
@@ -15,6 +15,10 @@
#include "content/test/weburl_loader_mock_factory.h"
#include "third_party/WebKit/public/platform/WebUnitTestSupport.h"
+namespace base {
+class StatsTable;
+}
+
namespace blink {
class WebLayerTreeView;
}
@@ -91,6 +95,7 @@
base::ScopedTempDir file_system_root_;
scoped_ptr<WebURLLoaderMockFactory> url_loader_factory_;
WebCompositorSupportImpl compositor_support_;
+ scoped_ptr<base::StatsTable> stats_table_;
#if defined(OS_WIN) || defined(OS_MACOSX)
blink::WebThemeEngine* active_theme_engine_;
diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc
index 79cb6c0..b1e59a8 100644
--- a/gpu/command_buffer/service/in_process_command_buffer.cc
+++ b/gpu/command_buffer/service/in_process_command_buffer.cc
@@ -658,8 +658,15 @@
void InProcessCommandBuffer::RetireSyncPointOnGpuThread(uint32 sync_point) {
gles2::MailboxManager* mailbox_manager =
decoder_->GetContextGroup()->mailbox_manager();
- if (mailbox_manager->UsesSync() && MakeCurrent())
- mailbox_manager->PushTextureUpdates();
+ if (mailbox_manager->UsesSync()) {
+ bool make_current_success = false;
+ {
+ base::AutoLock lock(command_buffer_lock_);
+ make_current_success = MakeCurrent();
+ }
+ if (make_current_success)
+ mailbox_manager->PushTextureUpdates();
+ }
g_sync_point_manager.Get().RetireSyncPoint(sync_point);
}
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc
index c668fbf..bcd2dd4 100644
--- a/gpu/config/gpu_driver_bug_list_json.cc
+++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -19,7 +19,7 @@
{
"name": "gpu driver bug list",
// Please update the version number whenever you change this file.
- "version": "6.5",
+ "version": "6.7",
"entries": [
{
"id": 1,
@@ -1082,6 +1082,18 @@
"features": [
"disable_async_readpixels"
]
+ },
+ {
+ "id": 86,
+ "description": "Disable use of Direct3D 11 on Matrox video cards",
+ "cr_bugs": [395861],
+ "os": {
+ "type": "win"
+ },
+ "vendor_id": "0x102b",
+ "features": [
+ "disable_d3d11"
+ ]
}
]
}
diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc
index 2f02da1..9b02c4c 100644
--- a/net/base/mime_util.cc
+++ b/net/base/mime_util.cc
@@ -460,7 +460,12 @@
{ "video/ogg", "opus,theora,vorbis" },
{ "audio/ogg", "opus,vorbis" },
{ "application/ogg", "opus,theora,vorbis" },
- { "audio/mpeg", "" },
+ { "audio/mpeg", ",mp3" }, // Note: The comma before the 'mp3'results in an
+ // empty string codec ID and indicates
+ // a missing codecs= parameter is also valid.
+ // The presense of 'mp3' is not RFC compliant,
+ // but is common in the wild so it is a defacto
+ // standard.
{ "audio/mp3", "" },
{ "audio/x-mp3", "" }
};
@@ -475,11 +480,19 @@
if (supported_codecs.empty())
return codecs.empty();
+ // If no codecs are specified in the mimetype, check to see if a missing
+ // codecs parameter is allowed.
+ if (codecs.empty())
+ return supported_codecs.find(std::string()) != supported_codecs.end();
+
for (size_t i = 0; i < codecs.size(); ++i) {
- if (supported_codecs.find(codecs[i]) == supported_codecs.end())
+ if (codecs[i].empty() ||
+ supported_codecs.find(codecs[i]) == supported_codecs.end()) {
return false;
+ }
}
- return !codecs.empty();
+
+ return true;
}
void MimeUtil::InitializeMimeTypeMaps() {
diff --git a/pdf/instance.cc b/pdf/instance.cc
index a17db57..5c71bbf 100644
--- a/pdf/instance.cc
+++ b/pdf/instance.cc
@@ -349,6 +349,10 @@
// For PDFs embedded in a frame, we don't get the data automatically like we
// do for full-frame loads. Start loading the data manually.
LoadUrl(url);
+ } else {
+ DCHECK(!did_call_start_loading_);
+ pp::PDF::DidStartLoading(this);
+ did_call_start_loading_ = true;
}
ZoomLimitsChanged(kMinZoom, kMaxZoom);
diff --git a/remoting/remoting_host.gypi b/remoting/remoting_host.gypi
index 47d60fa..3571924 100644
--- a/remoting/remoting_host.gypi
+++ b/remoting/remoting_host.gypi
@@ -795,6 +795,7 @@
},
'mac_bundle_resources': [
'<(PRODUCT_DIR)/icudtl.dat',
+ 'host/disconnect_window.xib',
'host/it2me/remote_assistance_host-Info.plist',
'<!@pymod_do_main(remoting_copy_locales -o -p <(OS) -x <(PRODUCT_DIR) <(remoting_locales))',
diff --git a/sandbox/win/src/handle_closer_agent.cc b/sandbox/win/src/handle_closer_agent.cc
index be0ffc1..07c6a09 100644
--- a/sandbox/win/src/handle_closer_agent.cc
+++ b/sandbox/win/src/handle_closer_agent.cc
@@ -78,7 +78,7 @@
bool HandleCloserAgent::CloseHandles() {
DWORD handle_count = UINT_MAX;
const int kInvalidHandleThreshold = 100;
- const size_t kHandleOffset = sizeof(HANDLE);
+ const size_t kHandleOffset = 4; // Handles are always a multiple of 4.
if (!::GetProcessHandleCount(::GetCurrentProcess(), &handle_count))
return false;
diff --git a/sandbox/win/src/handle_closer_test.cc b/sandbox/win/src/handle_closer_test.cc
index 9adcf6c..7fa2598 100644
--- a/sandbox/win/src/handle_closer_test.cc
+++ b/sandbox/win/src/handle_closer_test.cc
@@ -73,7 +73,7 @@
// Brute force the handle table to find what we're looking for.
DWORD handle_count = UINT_MAX;
const int kInvalidHandleThreshold = 100;
- const size_t kHandleOffset = sizeof(HANDLE);
+ const size_t kHandleOffset = 4; // Handles are always a multiple of 4.
HANDLE handle = NULL;
int invalid_count = 0;
base::string16 handle_name;
diff --git a/sync/internal_api/sync_backup_manager.cc b/sync/internal_api/sync_backup_manager.cc
index 295f79a..3295568 100644
--- a/sync/internal_api/sync_backup_manager.cc
+++ b/sync/internal_api/sync_backup_manager.cc
@@ -4,6 +4,7 @@
#include "sync/internal_api/sync_backup_manager.h"
+#include "sync/internal_api/public/read_node.h"
#include "sync/internal_api/public/write_transaction.h"
#include "sync/syncable/directory.h"
#include "sync/syncable/mutable_entry.h"
@@ -37,26 +38,24 @@
ReportUnrecoverableErrorFunction
report_unrecoverable_error_function,
CancelationSignal* cancelation_signal) {
- SyncRollbackManagerBase::Init(database_location, event_handler,
- sync_server_and_path, sync_server_port,
- use_ssl, post_factory.Pass(),
- workers, extensions_activity, change_delegate,
- credentials, invalidator_client_id,
- restored_key_for_bootstrapping,
- restored_keystore_key_for_bootstrapping,
- internal_components_factory, encryptor,
- unrecoverable_error_handler.Pass(),
- report_unrecoverable_error_function,
- cancelation_signal);
+ if (SyncRollbackManagerBase::InitInternal(
+ database_location,
+ internal_components_factory,
+ unrecoverable_error_handler.Pass(),
+ report_unrecoverable_error_function)) {
+ GetUserShare()->directory->CollectMetaHandleCounts(
+ &status_.num_entries_by_type, &status_.num_to_delete_entries_by_type);
- GetUserShare()->directory->CollectMetaHandleCounts(
- &status_.num_entries_by_type,
- &status_.num_to_delete_entries_by_type);
+ HideSyncPreference(PRIORITY_PREFERENCES);
+ HideSyncPreference(PREFERENCES);
+ }
}
void SyncBackupManager::SaveChanges() {
- NormalizeEntries();
- GetUserShare()->directory->SaveChanges();
+ if (initialized()) {
+ NormalizeEntries();
+ GetUserShare()->directory->SaveChanges();
+ }
}
SyncStatus SyncBackupManager::GetDetailedStatus() const {
@@ -104,7 +103,7 @@
if (!entry.GetId().ServerKnows())
entry.PutId(syncable::Id::CreateFromServerId(entry.GetId().value()));
if (!entry.GetParentId().ServerKnows()) {
- entry.PutParentId(syncable::Id::CreateFromServerId(
+ entry.PutParentIdPropertyOnly(syncable::Id::CreateFromServerId(
entry.GetParentId().value()));
}
entry.PutBaseVersion(1);
@@ -113,6 +112,34 @@
unsynced_.clear();
}
+void SyncBackupManager::HideSyncPreference(ModelType type) {
+ WriteTransaction trans(FROM_HERE, GetUserShare());
+ ReadNode pref_root(&trans);
+ if (BaseNode::INIT_OK != pref_root.InitTypeRoot(type))
+ return;
+
+ std::vector<int64> pref_ids;
+ pref_root.GetChildIds(&pref_ids);
+ for (uint32 i = 0; i < pref_ids.size(); ++i) {
+ syncable::MutableEntry entry(trans.GetWrappedWriteTrans(),
+ syncable::GET_BY_HANDLE, pref_ids[i]);
+ if (entry.good()) {
+ // HACKY: Set IS_DEL to true to remove entry from parent-children
+ // index so that it's not returned when syncable service asks
+ // for sync data. Syncable service then creates entry for local
+ // model. Then the existing entry is undeleted and set to local value
+ // because it has the same unique client tag.
+ entry.PutIsDel(true);
+ entry.PutIsUnsynced(false);
+
+ // Don't persist on disk so that if backup is aborted before receiving
+ // local preference values, values in sync DB are saved.
+ GetUserShare()->directory->UnmarkDirtyEntry(
+ trans.GetWrappedWriteTrans(), &entry);
+ }
+ }
+}
+
void SyncBackupManager::RegisterDirectoryTypeDebugInfoObserver(
syncer::TypeDebugInfoObserver* observer) {}
diff --git a/sync/internal_api/sync_backup_manager.h b/sync/internal_api/sync_backup_manager.h
index e6b9ca4..aba58e2 100644
--- a/sync/internal_api/sync_backup_manager.h
+++ b/sync/internal_api/sync_backup_manager.h
@@ -61,6 +61,12 @@
// entries.
void NormalizeEntries();
+ // Manipulate preference nodes so that they'll be overwritten by local
+ // preference values during model association, i.e. local wins instead of
+ // server wins. This is for preventing backup from changing preferences in
+ // case backup DB has hijacked preferences.
+ void HideSyncPreference(ModelType pref_type);
+
// Handles of unsynced entries caused by local model changes.
std::set<int64> unsynced_;
diff --git a/sync/internal_api/sync_backup_manager_unittest.cc b/sync/internal_api/sync_backup_manager_unittest.cc
index 5472c02..c075354 100644
--- a/sync/internal_api/sync_backup_manager_unittest.cc
+++ b/sync/internal_api/sync_backup_manager_unittest.cc
@@ -5,15 +5,22 @@
#include "sync/internal_api/sync_backup_manager.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/run_loop.h"
#include "sync/internal_api/public/read_node.h"
#include "sync/internal_api/public/read_transaction.h"
+#include "sync/internal_api/public/sessions/sync_session_snapshot.h"
#include "sync/internal_api/public/test/test_internal_components_factory.h"
#include "sync/internal_api/public/write_node.h"
#include "sync/internal_api/public/write_transaction.h"
#include "sync/syncable/entry.h"
#include "sync/test/test_directory_backing_store.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::WithArgs;
+
namespace syncer {
namespace {
@@ -22,16 +29,36 @@
EXPECT_TRUE(success);
}
-class SyncBackupManagerTest : public testing::Test {
+class SyncBackupManagerTest : public syncer::SyncManager::Observer,
+ public testing::Test {
+ public:
+ MOCK_METHOD1(OnSyncCycleCompleted,
+ void(const sessions::SyncSessionSnapshot&));
+ MOCK_METHOD1(OnConnectionStatusChange, void(ConnectionStatus));
+ MOCK_METHOD1(OnActionableError, void(const SyncProtocolError&));
+ MOCK_METHOD1(OnMigrationRequested, void(ModelTypeSet));;
+ MOCK_METHOD1(OnProtocolEvent, void(const ProtocolEvent&));
+ MOCK_METHOD4(OnInitializationComplete,
+ void(const WeakHandle<JsBackend>&,
+ const WeakHandle<DataTypeDebugInfoListener>&,
+ bool, ModelTypeSet));
+
protected:
virtual void SetUp() OVERRIDE {
CHECK(temp_dir_.CreateUniqueTempDir());
}
- void InitManager(SyncManager* manager) {
- TestInternalComponentsFactory factory(InternalComponentsFactory::Switches(),
- STORAGE_ON_DISK);
+ void InitManager(SyncManager* manager, StorageOption storage_option) {
+ manager_ = manager;
+ EXPECT_CALL(*this, OnInitializationComplete(_, _, _, _))
+ .WillOnce(WithArgs<2>(Invoke(this,
+ &SyncBackupManagerTest::HandleInit)));
+ TestInternalComponentsFactory factory(InternalComponentsFactory::Switches(),
+ storage_option);
+ manager->AddObserver(this);
+
+ base::RunLoop run_loop;
manager->Init(temp_dir_.path(),
MakeWeakHandle(base::WeakPtr<JsEventHandler>()),
"", 0, true, scoped_ptr<HttpPostProviderFactory>().Pass(),
@@ -39,13 +66,8 @@
NULL, NULL, SyncCredentials(), "", "", "", &factory,
NULL, scoped_ptr<UnrecoverableErrorHandler>().Pass(),
NULL, NULL);
- manager->ConfigureSyncer(
- CONFIGURE_REASON_NEW_CLIENT,
- ModelTypeSet(PREFERENCES),
- ModelTypeSet(), ModelTypeSet(), ModelTypeSet(),
- ModelSafeRoutingInfo(),
- base::Bind(&OnConfigDone, true),
- base::Bind(&OnConfigDone, false));
+ loop_.PostTask(FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
}
void CreateEntry(UserShare* user_share, ModelType type,
@@ -59,22 +81,43 @@
node.InitUniqueByCreation(type, type_root, client_tag));
}
+ private:
+ void ConfigureSyncer() {
+ manager_->ConfigureSyncer(CONFIGURE_REASON_NEW_CLIENT,
+ ModelTypeSet(SEARCH_ENGINES),
+ ModelTypeSet(), ModelTypeSet(), ModelTypeSet(),
+ ModelSafeRoutingInfo(),
+ base::Bind(&OnConfigDone, true),
+ base::Bind(&OnConfigDone, false));
+ }
+
+ void HandleInit(bool success) {
+ if (success) {
+ loop_.PostTask(FROM_HERE,
+ base::Bind(&SyncBackupManagerTest::ConfigureSyncer,
+ base::Unretained(this)));
+ } else {
+ manager_->ShutdownOnSyncThread();
+ }
+ }
+
base::ScopedTempDir temp_dir_;
base::MessageLoop loop_; // Needed for WeakHandle
+ SyncManager* manager_;
};
TEST_F(SyncBackupManagerTest, NormalizeAndPersist) {
scoped_ptr<SyncBackupManager> manager(new SyncBackupManager);
- InitManager(manager.get());
+ InitManager(manager.get(), STORAGE_ON_DISK);
- CreateEntry(manager->GetUserShare(), PREFERENCES, "test");
+ CreateEntry(manager->GetUserShare(), SEARCH_ENGINES, "test");
{
// New entry is local and unsynced at first.
ReadTransaction trans(FROM_HERE, manager->GetUserShare());
ReadNode pref(&trans);
EXPECT_EQ(BaseNode::INIT_OK,
- pref.InitByClientTagLookup(PREFERENCES, "test"));
+ pref.InitByClientTagLookup(SEARCH_ENGINES, "test"));
EXPECT_FALSE(pref.GetEntry()->GetId().ServerKnows());
EXPECT_TRUE(pref.GetEntry()->GetIsUnsynced());
}
@@ -86,7 +129,7 @@
ReadTransaction trans(FROM_HERE, manager->GetUserShare());
ReadNode pref(&trans);
EXPECT_EQ(BaseNode::INIT_OK,
- pref.InitByClientTagLookup(PREFERENCES, "test"));
+ pref.InitByClientTagLookup(SEARCH_ENGINES, "test"));
EXPECT_TRUE(pref.GetEntry()->GetId().ServerKnows());
EXPECT_FALSE(pref.GetEntry()->GetIsUnsynced());
}
@@ -94,17 +137,23 @@
// Reopen db to verify entry is persisted.
manager.reset(new SyncBackupManager);
- InitManager(manager.get());
+ InitManager(manager.get(), STORAGE_ON_DISK);
{
ReadTransaction trans(FROM_HERE, manager->GetUserShare());
ReadNode pref(&trans);
EXPECT_EQ(BaseNode::INIT_OK,
- pref.InitByClientTagLookup(PREFERENCES, "test"));
+ pref.InitByClientTagLookup(SEARCH_ENGINES, "test"));
EXPECT_TRUE(pref.GetEntry()->GetId().ServerKnows());
EXPECT_FALSE(pref.GetEntry()->GetIsUnsynced());
}
}
+TEST_F(SyncBackupManagerTest, FailToInitialize) {
+ // Test graceful shutdown on initialization failure.
+ scoped_ptr<SyncBackupManager> manager(new SyncBackupManager);
+ InitManager(manager.get(), STORAGE_INVALID);
+}
+
} // anonymous namespace
} // namespace syncer
diff --git a/sync/internal_api/sync_rollback_manager.cc b/sync/internal_api/sync_rollback_manager.cc
index 84367b0..c5a6f75 100644
--- a/sync/internal_api/sync_rollback_manager.cc
+++ b/sync/internal_api/sync_rollback_manager.cc
@@ -41,28 +41,22 @@
ReportUnrecoverableErrorFunction
report_unrecoverable_error_function,
CancelationSignal* cancelation_signal) {
- SyncRollbackManagerBase::Init(database_location, event_handler,
- sync_server_and_path, sync_server_port,
- use_ssl, post_factory.Pass(),
- workers, extensions_activity, change_delegate,
- credentials, invalidator_client_id,
- restored_key_for_bootstrapping,
- restored_keystore_key_for_bootstrapping,
- internal_components_factory, encryptor,
- unrecoverable_error_handler.Pass(),
- report_unrecoverable_error_function,
- cancelation_signal);
+ if (SyncRollbackManagerBase::InitInternal(
+ database_location,
+ internal_components_factory,
+ unrecoverable_error_handler.Pass(),
+ report_unrecoverable_error_function)) {
+ change_delegate_ = change_delegate;
- change_delegate_ = change_delegate;
+ for (size_t i = 0; i < workers.size(); ++i) {
+ ModelSafeGroup group = workers[i]->GetModelSafeGroup();
+ CHECK(workers_.find(group) == workers_.end());
+ workers_[group] = workers[i];
+ }
- for (size_t i = 0; i < workers.size(); ++i) {
- ModelSafeGroup group = workers[i]->GetModelSafeGroup();
- CHECK(workers_.find(group) == workers_.end());
- workers_[group] = workers[i];
+ rollback_ready_types_ = GetUserShare()->directory->InitialSyncEndedTypes();
+ rollback_ready_types_.RetainAll(BackupTypes());
}
-
- rollback_ready_types_ = GetUserShare()->directory->InitialSyncEndedTypes();
- rollback_ready_types_.RetainAll(BackupTypes());
}
void SyncRollbackManager::StartSyncingNormally(
diff --git a/sync/internal_api/sync_rollback_manager_base.cc b/sync/internal_api/sync_rollback_manager_base.cc
index ade0422..338f5af 100644
--- a/sync/internal_api/sync_rollback_manager_base.cc
+++ b/sync/internal_api/sync_rollback_manager_base.cc
@@ -15,8 +15,8 @@
namespace {
// Permanent bookmark folders as defined in bookmark_model_associator.cc.
+// No mobile bookmarks because they only exists with sync enabled.
const char kBookmarkBarTag[] = "bookmark_bar";
-const char kMobileBookmarksTag[] = "synced_bookmarks";
const char kOtherBookmarksTag[] = "other_bookmarks";
class DummyEntryptionHandler : public syncer::SyncEncryptionHandler {
@@ -43,41 +43,29 @@
SyncRollbackManagerBase::SyncRollbackManagerBase()
: report_unrecoverable_error_function_(NULL),
weak_ptr_factory_(this),
- dummy_handler_(new DummyEntryptionHandler) {
+ dummy_handler_(new DummyEntryptionHandler),
+ initialized_(false) {
}
SyncRollbackManagerBase::~SyncRollbackManagerBase() {
}
-void SyncRollbackManagerBase::Init(
- const base::FilePath& database_location,
- const WeakHandle<JsEventHandler>& event_handler,
- const std::string& sync_server_and_path,
- int sync_server_port,
- bool use_ssl,
- scoped_ptr<HttpPostProviderFactory> post_factory,
- const std::vector<scoped_refptr<ModelSafeWorker> >& workers,
- ExtensionsActivity* extensions_activity,
- SyncManager::ChangeDelegate* change_delegate,
- const SyncCredentials& credentials,
- const std::string& invalidator_client_id,
- const std::string& restored_key_for_bootstrapping,
- const std::string& restored_keystore_key_for_bootstrapping,
- InternalComponentsFactory* internal_components_factory,
- Encryptor* encryptor,
- scoped_ptr<UnrecoverableErrorHandler> unrecoverable_error_handler,
- ReportUnrecoverableErrorFunction
- report_unrecoverable_error_function,
- CancelationSignal* cancelation_signal) {
+bool SyncRollbackManagerBase::InitInternal(
+ const base::FilePath& database_location,
+ InternalComponentsFactory* internal_components_factory,
+ scoped_ptr<UnrecoverableErrorHandler> unrecoverable_error_handler,
+ ReportUnrecoverableErrorFunction report_unrecoverable_error_function) {
unrecoverable_error_handler_ = unrecoverable_error_handler.Pass();
report_unrecoverable_error_function_ = report_unrecoverable_error_function;
if (!InitBackupDB(database_location, internal_components_factory)) {
NotifyInitializationFailure();
- return;
+ return false;
}
+ initialized_ = true;
NotifyInitializationSuccess();
+ return true;
}
ModelTypeSet SyncRollbackManagerBase::InitialSyncEndedTypes() {
@@ -118,7 +106,6 @@
if (InitTypeRootNode(type.Get())) {
if (type.Get() == BOOKMARKS) {
InitBookmarkFolder(kBookmarkBarTag);
- InitBookmarkFolder(kMobileBookmarksTag);
InitBookmarkFolder(kOtherBookmarksTag);
}
}
@@ -151,10 +138,11 @@
}
void SyncRollbackManagerBase::ShutdownOnSyncThread() {
- if (share_.directory) {
+ if (initialized_) {
SaveChanges();
share_.directory->Close();
share_.directory.reset();
+ initialized_ = false;
}
}
@@ -227,7 +215,7 @@
OnInitializationComplete(
MakeWeakHandle(base::WeakPtr<JsBackend>()),
MakeWeakHandle(base::WeakPtr<DataTypeDebugInfoListener>()),
- false, InitialSyncEndedTypes()));
+ false, ModelTypeSet()));
}
std::string SyncRollbackManagerBase::GetOwnerName() const {
diff --git a/sync/internal_api/sync_rollback_manager_base.h b/sync/internal_api/sync_rollback_manager_base.h
index 6b4153e..fce980b 100644
--- a/sync/internal_api/sync_rollback_manager_base.h
+++ b/sync/internal_api/sync_rollback_manager_base.h
@@ -35,26 +35,6 @@
virtual ~SyncRollbackManagerBase();
// SyncManager implementation.
- virtual void Init(
- const base::FilePath& database_location,
- const WeakHandle<JsEventHandler>& event_handler,
- const std::string& sync_server_and_path,
- int sync_server_port,
- bool use_ssl,
- scoped_ptr<HttpPostProviderFactory> post_factory,
- const std::vector<scoped_refptr<ModelSafeWorker> >& workers,
- ExtensionsActivity* extensions_activity,
- SyncManager::ChangeDelegate* change_delegate,
- const SyncCredentials& credentials,
- const std::string& invalidator_client_id,
- const std::string& restored_key_for_bootstrapping,
- const std::string& restored_keystore_key_for_bootstrapping,
- InternalComponentsFactory* internal_components_factory,
- Encryptor* encryptor,
- scoped_ptr<UnrecoverableErrorHandler> unrecoverable_error_handler,
- ReportUnrecoverableErrorFunction
- report_unrecoverable_error_function,
- CancelationSignal* cancelation_signal) OVERRIDE;
virtual ModelTypeSet InitialSyncEndedTypes() OVERRIDE;
virtual ModelTypeSet GetTypesWithEmptyProgressMarkerToken(
ModelTypeSet types) OVERRIDE;
@@ -115,6 +95,13 @@
protected:
ObserverList<SyncManager::Observer>* GetObservers();
+ // Initialize sync backup DB.
+ bool InitInternal(
+ const base::FilePath& database_location,
+ InternalComponentsFactory* internal_components_factory,
+ scoped_ptr<UnrecoverableErrorHandler> unrecoverable_error_handler,
+ ReportUnrecoverableErrorFunction report_unrecoverable_error_function);
+
virtual void RegisterDirectoryTypeDebugInfoObserver(
syncer::TypeDebugInfoObserver* observer) OVERRIDE;
virtual void UnregisterDirectoryTypeDebugInfoObserver(
@@ -123,6 +110,10 @@
syncer::TypeDebugInfoObserver* observer) OVERRIDE;
virtual void RequestEmitDebugInfo() OVERRIDE;
+ bool initialized() const {
+ return initialized_;
+ }
+
private:
void NotifyInitializationSuccess();
void NotifyInitializationFailure();
@@ -144,6 +135,8 @@
scoped_ptr<SyncEncryptionHandler> dummy_handler_;
+ bool initialized_;
+
DISALLOW_COPY_AND_ASSIGN(SyncRollbackManagerBase);
};
diff --git a/sync/internal_api/sync_rollback_manager_base_unittest.cc b/sync/internal_api/sync_rollback_manager_base_unittest.cc
index 79075d2..1d4c2de 100644
--- a/sync/internal_api/sync_rollback_manager_base_unittest.cc
+++ b/sync/internal_api/sync_rollback_manager_base_unittest.cc
@@ -18,6 +18,34 @@
EXPECT_TRUE(success);
}
+class SyncTestRollbackManager : public SyncRollbackManagerBase {
+ public:
+ virtual void Init(
+ const base::FilePath& database_location,
+ const WeakHandle<JsEventHandler>& event_handler,
+ const std::string& sync_server_and_path,
+ int sync_server_port,
+ bool use_ssl,
+ scoped_ptr<HttpPostProviderFactory> post_factory,
+ const std::vector<scoped_refptr<ModelSafeWorker> >& workers,
+ ExtensionsActivity* extensions_activity,
+ ChangeDelegate* change_delegate,
+ const SyncCredentials& credentials,
+ const std::string& invalidator_client_id,
+ const std::string& restored_key_for_bootstrapping,
+ const std::string& restored_keystore_key_for_bootstrapping,
+ InternalComponentsFactory* internal_components_factory,
+ Encryptor* encryptor,
+ scoped_ptr<UnrecoverableErrorHandler> unrecoverable_error_handler,
+ ReportUnrecoverableErrorFunction report_unrecoverable_error_function,
+ CancelationSignal* cancelation_signal) OVERRIDE {
+ SyncRollbackManagerBase::InitInternal(database_location,
+ internal_components_factory,
+ unrecoverable_error_handler.Pass(),
+ report_unrecoverable_error_function);
+ }
+};
+
class SyncRollbackManagerBaseTest : public testing::Test {
protected:
virtual void SetUp() OVERRIDE {
@@ -32,7 +60,7 @@
NULL, NULL);
}
- SyncRollbackManagerBase manager_;
+ SyncTestRollbackManager manager_;
base::MessageLoop loop_; // Needed for WeakHandle
};
@@ -58,7 +86,7 @@
EXPECT_EQ(BaseNode::INIT_OK,
bookmark_bar.InitByTagLookupForBookmarks("bookmark_bar"));
ReadNode bookmark_mobile(&trans);
- EXPECT_EQ(BaseNode::INIT_OK,
+ EXPECT_EQ(BaseNode::INIT_FAILED_ENTRY_NOT_GOOD,
bookmark_mobile.InitByTagLookupForBookmarks("synced_bookmarks"));
ReadNode bookmark_other(&trans);
EXPECT_EQ(BaseNode::INIT_OK,
diff --git a/sync/internal_api/sync_rollback_manager_unittest.cc b/sync/internal_api/sync_rollback_manager_unittest.cc
index d66ee06..11f875f 100644
--- a/sync/internal_api/sync_rollback_manager_unittest.cc
+++ b/sync/internal_api/sync_rollback_manager_unittest.cc
@@ -5,6 +5,7 @@
#include "sync/internal_api/sync_rollback_manager.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/run_loop.h"
#include "sync/internal_api/public/read_node.h"
#include "sync/internal_api/public/read_transaction.h"
#include "sync/internal_api/public/sessions/sync_session_snapshot.h"
@@ -76,9 +77,9 @@
void(const sessions::SyncSessionSnapshot&));
MOCK_METHOD1(OnConnectionStatusChange, void(ConnectionStatus));
MOCK_METHOD4(OnInitializationComplete,
- void(const WeakHandle<JsBackend>&,
- const WeakHandle<DataTypeDebugInfoListener>&,
- bool, ModelTypeSet));
+ void(const WeakHandle<JsBackend>&,
+ const WeakHandle<DataTypeDebugInfoListener>&,
+ bool, ModelTypeSet));
MOCK_METHOD1(OnActionableError, void(const SyncProtocolError&));
MOCK_METHOD1(OnMigrationRequested, void(ModelTypeSet));;
MOCK_METHOD1(OnProtocolEvent, void(const ProtocolEvent&));
@@ -100,11 +101,19 @@
}
void InitManager(SyncManager* manager, ModelTypeSet types,
- TestChangeDelegate* delegate) {
+ TestChangeDelegate* delegate, StorageOption storage_option) {
+ manager_ = manager;
+ types_ = types;
+
+ EXPECT_CALL(*this, OnInitializationComplete(_, _, _, _))
+ .WillOnce(WithArgs<2>(Invoke(this,
+ &SyncRollbackManagerTest::HandleInit)));
+
manager->AddObserver(this);
TestInternalComponentsFactory factory(InternalComponentsFactory::Switches(),
- STORAGE_ON_DISK);
+ storage_option);
+ base::RunLoop run_loop;
manager->Init(temp_dir_.path(),
MakeWeakHandle(base::WeakPtr<JsEventHandler>()),
"", 0, true, scoped_ptr<HttpPostProviderFactory>().Pass(),
@@ -113,21 +122,16 @@
NULL, delegate, SyncCredentials(), "", "", "", &factory,
NULL, scoped_ptr<UnrecoverableErrorHandler>().Pass(),
NULL, NULL);
- manager->ConfigureSyncer(
- CONFIGURE_REASON_NEW_CLIENT,
- types,
- ModelTypeSet(), ModelTypeSet(), ModelTypeSet(), ModelSafeRoutingInfo(),
- base::Bind(&SyncRollbackManagerTest::OnConfigDone,
- base::Unretained(this), true),
- base::Bind(&SyncRollbackManagerTest::OnConfigDone,
- base::Unretained(this), false));
+ loop_.PostTask(FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
}
// Create and persist an entry by unique tag in DB.
void PrepopulateDb(ModelType type, const std::string& client_tag) {
SyncBackupManager backup_manager;
TestChangeDelegate delegate;
- InitManager(&backup_manager, ModelTypeSet(type), &delegate);
+ InitManager(&backup_manager, ModelTypeSet(type), &delegate,
+ STORAGE_ON_DISK);
CreateEntry(backup_manager.GetUserShare(), type, client_tag);
backup_manager.ShutdownOnSyncThread();
}
@@ -140,9 +144,34 @@
return BaseNode::INIT_OK == node.InitByClientTagLookup(type, client_tag);
}
+ private:
+ void ConfigureSyncer() {
+ manager_->ConfigureSyncer(
+ CONFIGURE_REASON_NEW_CLIENT,
+ types_,
+ ModelTypeSet(), ModelTypeSet(), ModelTypeSet(),
+ ModelSafeRoutingInfo(),
+ base::Bind(&SyncRollbackManagerTest::OnConfigDone,
+ base::Unretained(this), true),
+ base::Bind(&SyncRollbackManagerTest::OnConfigDone,
+ base::Unretained(this), false));
+ }
+
+ void HandleInit(bool success) {
+ if (success) {
+ loop_.PostTask(FROM_HERE,
+ base::Bind(&SyncRollbackManagerTest::ConfigureSyncer,
+ base::Unretained(this)));
+ } else {
+ manager_->ShutdownOnSyncThread();
+ }
+ }
+
base::ScopedTempDir temp_dir_;
scoped_refptr<ModelSafeWorker> worker_;
base::MessageLoop loop_; // Needed for WeakHandle
+ SyncManager* manager_;
+ ModelTypeSet types_;
};
bool IsRollbackDoneAction(SyncProtocolError e) {
@@ -154,7 +183,8 @@
TestChangeDelegate delegate;
SyncRollbackManager rollback_manager;
- InitManager(&rollback_manager, ModelTypeSet(PREFERENCES), &delegate);
+ InitManager(&rollback_manager, ModelTypeSet(PREFERENCES), &delegate,
+ STORAGE_ON_DISK);
// Simulate a new entry added during type initialization.
int64 new_pref_id =
@@ -177,7 +207,8 @@
TestChangeDelegate delegate;
SyncRollbackManager rollback_manager;
- InitManager(&rollback_manager, ModelTypeSet(PREFERENCES, APPS), &delegate);
+ InitManager(&rollback_manager, ModelTypeSet(PREFERENCES, APPS), &delegate,
+ STORAGE_ON_DISK);
// Simulate new entry added during type initialization.
int64 new_pref_id =
@@ -204,7 +235,8 @@
TestChangeDelegate delegate;
scoped_ptr<SyncRollbackManager> rollback_manager(
new SyncRollbackManager);
- InitManager(rollback_manager.get(), ModelTypeSet(PREFERENCES), &delegate);
+ InitManager(rollback_manager.get(), ModelTypeSet(PREFERENCES), &delegate,
+ STORAGE_ON_DISK);
// Simulate a new entry added during type initialization.
CreateEntry(rollback_manager->GetUserShare(), PREFERENCES, "pref2");
@@ -214,11 +246,20 @@
// Verify new entry was not persisted.
rollback_manager.reset(new SyncRollbackManager);
- InitManager(rollback_manager.get(), ModelTypeSet(PREFERENCES), &delegate);
+ InitManager(rollback_manager.get(), ModelTypeSet(PREFERENCES), &delegate,
+ STORAGE_ON_DISK);
EXPECT_FALSE(VerifyEntry(rollback_manager->GetUserShare(), PREFERENCES,
"pref2"));
}
+TEST_F(SyncRollbackManagerTest, OnInitializationFailure) {
+ // Test graceful shutdown on initialization failure.
+ scoped_ptr<SyncRollbackManager> rollback_manager(
+ new SyncRollbackManager);
+ InitManager(rollback_manager.get(), ModelTypeSet(PREFERENCES), NULL,
+ STORAGE_ON_DISK);
+}
+
} // anonymous namespace
} // namespace syncer
diff --git a/sync/syncable/directory.cc b/sync/syncable/directory.cc
index ad107b1..be489b2 100644
--- a/sync/syncable/directory.cc
+++ b/sync/syncable/directory.cc
@@ -1446,5 +1446,10 @@
}
}
+void Directory::UnmarkDirtyEntry(WriteTransaction* trans, Entry* entry) {
+ CHECK(trans);
+ entry->kernel_->clear_dirty(&kernel_->dirty_metahandles);
+}
+
} // namespace syncable
} // namespace syncer
diff --git a/sync/syncable/directory.h b/sync/syncable/directory.h
index f7dd44e..2830eec 100644
--- a/sync/syncable/directory.h
+++ b/sync/syncable/directory.h
@@ -19,6 +19,7 @@
#include "sync/internal_api/public/util/report_unrecoverable_error_function.h"
#include "sync/internal_api/public/util/weak_handle.h"
#include "sync/syncable/dir_open_result.h"
+#include "sync/syncable/entry.h"
#include "sync/syncable/entry_kernel.h"
#include "sync/syncable/metahandle_set.h"
#include "sync/syncable/parent_child_index.h"
@@ -404,6 +405,11 @@
const sync_pb::AttachmentIdProto& attachment_id_proto,
Metahandles* result);
+ // Change entry to not dirty. Used in special case when we don't want to
+ // persist modified entry on disk. e.g. SyncBackupManager uses this to
+ // preserve sync preferences in DB on disk.
+ void UnmarkDirtyEntry(WriteTransaction* trans, Entry* entry);
+
protected: // for friends, mainly used by Entry constructors
virtual EntryKernel* GetEntryByHandle(int64 handle);
virtual EntryKernel* GetEntryByHandle(int64 metahandle,
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 34af7b6..cf3e4f5 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -5145,6 +5145,11 @@
</summary>
</histogram>
+<histogram name="Enterprise.EnrollmentRecovery" enum="EnterpriseEnrollmentType">
+ <owner>tnagel@chromium.org</owner>
+ <summary>Events related to Chrome OS enterprise enrollment recovery.</summary>
+</histogram>
+
<histogram name="Enterprise.IOSPolicies">
<owner>joaodasilva@chromium.org</owner>
<summary>
@@ -20819,6 +20824,17 @@
</summary>
</histogram>
+<histogram name="Plugin.AvailabilityStatus.WidevineCdm"
+ enum="PluginAvailabilityStatus">
+ <owner>xhwang@chromium.org</owner>
+ <summary>
+ The availability status of Widevine CDM. In normal cases, this is reported
+ per render process if EME API is used. This is not reported if EME API is
+ not used. This could be reported multiple times per render process until
+ PLUGIN_AVAILABLE is reported (which should be a rare case).
+ </summary>
+</histogram>
+
<histogram name="Plugin.FlashNavigateUsage" enum="FlashNavigateUsageType">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>Record usage of PPB_Flash.Navigate() Pepper API.</summary>
@@ -35258,6 +35274,10 @@
<int value="23" label="Domain mismatch">
Enrollment failed because the device belongs to a different domain.
</int>
+ <int value="24" label="Triggered">
+ Enrollment has been triggered, the credential screen has been shown.
+ </int>
+ <int value="25" label="Retried">The user retried to submit credentials.</int>
</enum>
<enum name="EnterprisePolicies" type="int">
@@ -42233,6 +42253,12 @@
<int value="16" label="I/O"/>
</enum>
+<enum name="PluginAvailabilityStatus" type="int">
+ <int value="0" label="PLUGIN_NOT_REGISTERED"/>
+ <int value="1" label="PLUGIN_AVAILABLE"/>
+ <int value="2" label="PLUGIN_DISABLED"/>
+</enum>
+
<enum name="PluginLoadResult" type="int">
<int value="0" label="LOAD_SUCCESS"/>
<int value="1" label="LOAD_FAILED"/>
diff --git a/ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java b/ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java
index 894376c..d9faa0f 100644
--- a/ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java
+++ b/ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java
@@ -5,6 +5,7 @@
package org.chromium.ui;
import android.content.Context;
+import android.graphics.Rect;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.View.OnLayoutChangeListener;
@@ -30,6 +31,7 @@
private float mAnchorY;
private OnLayoutChangeListener mLayoutChangeListener;
private PopupWindow.OnDismissListener mOnDismissListener;
+ ListAdapter mAdapter;
/**
* Creates an DropdownPopupWindow with specified parameters.
@@ -89,21 +91,32 @@
}
@Override
+ public void setAdapter(ListAdapter adapter) {
+ mAdapter = adapter;
+ super.setAdapter(adapter);
+ }
+
+ @Override
public void show() {
// An ugly hack to keep the popup from expanding on top of the keyboard.
setInputMethodMode(INPUT_METHOD_NEEDED);
- super.show();
- getListView().setDividerHeight(0);
int contentWidth = measureContentWidth();
float contentWidthInDip = contentWidth /
mContext.getResources().getDisplayMetrics().density;
if (contentWidthInDip > mAnchorWidth) {
setContentWidth(contentWidth);
+ final Rect displayFrame = new Rect();
+ mAnchorView.getWindowVisibleDisplayFrame(displayFrame);
+ if (getWidth() > displayFrame.width()) {
+ setWidth(displayFrame.width());
+ }
} else {
setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
}
mViewAndroidDelegate.setAnchorViewPosition(mAnchorView, mAnchorX, mAnchorY, mAnchorWidth,
mAnchorHeight);
+ super.show();
+ getListView().setDividerHeight(0);
}
@Override
@@ -118,13 +131,12 @@
private int measureContentWidth() {
int maxWidth = 0;
View itemView = null;
- final ListAdapter adapter = getListView().getAdapter();
- if (adapter == null)
+ if (mAdapter == null)
return 0;
final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- for (int i = 0; i < adapter.getCount(); i++) {
- itemView = adapter.getView(i, itemView, null);
+ for (int i = 0; i < mAdapter.getCount(); i++) {
+ itemView = mAdapter.getView(i, itemView, null);
LinearLayout.LayoutParams params =
new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
diff --git a/ui/android/java/src/org/chromium/ui/interpolators/BakedBezierInterpolator.java b/ui/android/java/src/org/chromium/ui/interpolators/BakedBezierInterpolator.java
new file mode 100644
index 0000000..f95d855
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/interpolators/BakedBezierInterpolator.java
@@ -0,0 +1,163 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.ui.interpolators;
+
+import android.view.animation.Interpolator;
+
+/**
+ * A pre-baked bezier-curved interpolator for quantum-paper transitions.
+ * TODO(dtrainor): Move to the API Compatability version iff that supports the curves we need and
+ * once we move to that SDK.
+ */
+public class BakedBezierInterpolator implements Interpolator {
+ /**
+ * Lookup table values.
+ * Generated using a Bezier curve from (0,0) to (1,1) with control points:
+ * P0 (0.0, 0.0)
+ * P1 (0.4, 0.0)
+ * P2 (0.2, 1.0)
+ * P3 (1.0, 1.0)
+ *
+ * Values sampled with x at regular intervals between 0 and 1.
+ */
+ private static final float[] TRANSFORM_VALUES = new float[] {
+ 0.0f, 0.0002f, 0.0009f, 0.0019f, 0.0036f, 0.0059f, 0.0086f, 0.0119f, 0.0157f, 0.0209f,
+ 0.0257f, 0.0321f, 0.0392f, 0.0469f, 0.0566f, 0.0656f, 0.0768f, 0.0887f, 0.1033f, 0.1186f,
+ 0.1349f, 0.1519f, 0.1696f, 0.1928f, 0.2121f, 0.237f, 0.2627f, 0.2892f, 0.3109f, 0.3386f,
+ 0.3667f, 0.3952f, 0.4241f, 0.4474f, 0.4766f, 0.5f, 0.5234f, 0.5468f, 0.5701f, 0.5933f,
+ 0.6134f, 0.6333f, 0.6531f, 0.6698f, 0.6891f, 0.7054f, 0.7214f, 0.7346f, 0.7502f, 0.763f,
+ 0.7756f, 0.7879f, 0.8f, 0.8107f, 0.8212f, 0.8326f, 0.8415f, 0.8503f, 0.8588f, 0.8672f,
+ 0.8754f, 0.8833f, 0.8911f, 0.8977f, 0.9041f, 0.9113f, 0.9165f, 0.9232f, 0.9281f, 0.9328f,
+ 0.9382f, 0.9434f, 0.9476f, 0.9518f, 0.9557f, 0.9596f, 0.9632f, 0.9662f, 0.9695f, 0.9722f,
+ 0.9753f, 0.9777f, 0.9805f, 0.9826f, 0.9847f, 0.9866f, 0.9884f, 0.9901f, 0.9917f, 0.9931f,
+ 0.9944f, 0.9955f, 0.9964f, 0.9973f, 0.9981f, 0.9986f, 0.9992f, 0.9995f, 0.9998f, 1.0f, 1.0f
+ };
+
+ /**
+ * Lookup table values.
+ * Generated using a Bezier curve from (0,0) to (1,1) with control points:
+ * P0 (0.0, 0.0)
+ * P1 (0.4, 0.0)
+ * P2 (1.0, 1.0)
+ * P3 (1.0, 1.0)
+ *
+ * Values sampled with x at regular intervals between 0 and 1.
+ */
+ private static final float[] FADE_OUT_VALUES = new float[] {
+ 0.0f, 0.0002f, 0.0008f, 0.0019f, 0.0032f, 0.0049f, 0.0069f, 0.0093f, 0.0119f, 0.0149f,
+ 0.0182f, 0.0218f, 0.0257f, 0.0299f, 0.0344f, 0.0392f, 0.0443f, 0.0496f, 0.0552f, 0.0603f,
+ 0.0656f, 0.0719f, 0.0785f, 0.0853f, 0.0923f, 0.0986f, 0.1051f, 0.1128f, 0.1206f, 0.1287f,
+ 0.1359f, 0.1433f, 0.1519f, 0.1607f, 0.1696f, 0.1776f, 0.1857f, 0.1952f, 0.2048f, 0.2145f,
+ 0.2232f, 0.2319f, 0.2421f, 0.2523f, 0.2627f, 0.2733f, 0.2826f, 0.2919f, 0.3027f, 0.3137f,
+ 0.3247f, 0.3358f, 0.3469f, 0.3582f, 0.3695f, 0.3809f, 0.3924f, 0.4039f, 0.4154f, 0.427f,
+ 0.4386f, 0.4503f, 0.4619f, 0.4751f, 0.4883f, 0.5f, 0.5117f, 0.5264f, 0.5381f, 0.5497f,
+ 0.5643f, 0.5759f, 0.5904f, 0.6033f, 0.6162f, 0.6305f, 0.6446f, 0.6587f, 0.6698f, 0.6836f,
+ 0.7f, 0.7134f, 0.7267f, 0.7425f, 0.7554f, 0.7706f, 0.7855f, 0.8f, 0.8143f, 0.8281f, 0.8438f,
+ 0.8588f, 0.8733f, 0.8892f, 0.9041f, 0.9215f, 0.9344f, 0.9518f, 0.9667f, 0.9826f, 0.9993f
+ };
+
+ /**
+ * Lookup table values.
+ * Generated using a Bezier curve from (0,0) to (1,1) with control points:
+ * P0 (0.0, 0.0)
+ * P1 (0.0, 0.0)
+ * P2 (0.2, 1.0)
+ * P3 (1.0, 1.0)
+ *
+ * Values sampled with x at regular intervals between 0 and 1.
+ */
+ private static final float[] FADE_IN_VALUES = new float[] {
+ 0.0029f, 0.043f, 0.0785f, 0.1147f, 0.1476f, 0.1742f, 0.2024f, 0.2319f, 0.2575f, 0.2786f,
+ 0.3055f, 0.3274f, 0.3498f, 0.3695f, 0.3895f, 0.4096f, 0.4299f, 0.4474f, 0.4649f, 0.4824f,
+ 0.5f, 0.5176f, 0.5322f, 0.5468f, 0.5643f, 0.5788f, 0.5918f, 0.6048f, 0.6191f, 0.6333f,
+ 0.6446f, 0.6573f, 0.6698f, 0.6808f, 0.6918f, 0.704f, 0.7148f, 0.7254f, 0.7346f, 0.7451f,
+ 0.7554f, 0.7655f, 0.7731f, 0.783f, 0.7916f, 0.8f, 0.8084f, 0.8166f, 0.8235f, 0.8315f,
+ 0.8393f, 0.8459f, 0.8535f, 0.8599f, 0.8672f, 0.8733f, 0.8794f, 0.8853f, 0.8911f, 0.8967f,
+ 0.9023f, 0.9077f, 0.9121f, 0.9173f, 0.9224f, 0.9265f, 0.9313f, 0.9352f, 0.9397f, 0.9434f,
+ 0.9476f, 0.9511f, 0.9544f, 0.9577f, 0.9614f, 0.9644f, 0.9673f, 0.9701f, 0.9727f, 0.9753f,
+ 0.9777f, 0.98f, 0.9818f, 0.9839f, 0.9859f, 0.9877f, 0.9891f, 0.9907f, 0.9922f, 0.9933f,
+ 0.9946f, 0.9957f, 0.9966f, 0.9974f, 0.9981f, 0.9986f, 0.9992f, 0.9995f, 0.9998f, 1.0f, 1.0f
+ };
+
+ /**
+ * Lookup table values.
+ * Generated using a Bezier curve from (0,0) to (1,1) with control points:
+ * P0 (0.0, 0.0)
+ * P1 (0.0, 0.84)
+ * P2 (0.13, 0.99)
+ * P3 (1.0, 1.0)
+ */
+ private static final float[] TRANSFORM_FOLLOW_THROUGH_VALUES = new float[] {
+ 0.0767f, 0.315f, 0.4173f, 0.484f, 0.5396f, 0.5801f, 0.6129f, 0.644f, 0.6687f, 0.6876f,
+ 0.7102f, 0.7276f, 0.7443f, 0.7583f, 0.7718f, 0.7849f, 0.7975f, 0.8079f, 0.8179f, 0.8276f,
+ 0.8355f, 0.8446f, 0.8519f, 0.859f, 0.8659f, 0.8726f, 0.8791f, 0.8841f, 0.8902f, 0.8949f,
+ 0.9001f, 0.9051f, 0.9094f, 0.9136f, 0.9177f, 0.9217f, 0.925f, 0.9283f, 0.9319f, 0.9355f,
+ 0.938f, 0.9413f, 0.9437f, 0.9469f, 0.9491f, 0.9517f, 0.9539f, 0.9563f, 0.9583f, 0.9603f,
+ 0.9622f, 0.9643f, 0.9661f, 0.9679f, 0.9693f, 0.9709f, 0.9725f, 0.974f, 0.9753f, 0.9767f,
+ 0.9779f, 0.9792f, 0.9803f, 0.9816f, 0.9826f, 0.9835f, 0.9845f, 0.9854f, 0.9863f, 0.9872f,
+ 0.988f, 0.9888f, 0.9895f, 0.9903f, 0.991f, 0.9917f, 0.9922f, 0.9928f, 0.9934f, 0.9939f,
+ 0.9944f, 0.9948f, 0.9953f, 0.9957f, 0.9962f, 0.9965f, 0.9969f, 0.9972f, 0.9975f, 0.9978f,
+ 0.9981f, 0.9984f, 0.9986f, 0.9989f, 0.9991f, 0.9992f, 0.9994f, 0.9996f, 0.9997f, 0.9999f,
+ 1.0f
+ };
+
+ /**
+ * 0.4 to 0.2 bezier curve. Should be used for general movement.
+ */
+ public static final BakedBezierInterpolator TRANSFORM_CURVE =
+ new BakedBezierInterpolator(TRANSFORM_VALUES);
+
+ /**
+ * 0.4 to 1.0 bezier curve. Should be used for fading out.
+ */
+ public static final BakedBezierInterpolator FADE_OUT_CURVE =
+ new BakedBezierInterpolator(FADE_OUT_VALUES);
+
+ /**
+ * 0.0 to 0.2 bezier curve. Should be used for fading in.
+ */
+ public static final BakedBezierInterpolator FADE_IN_CURVE =
+ new BakedBezierInterpolator(FADE_IN_VALUES);
+
+ /**
+ * 0.0 to 0.13 by 0.84 to 0.99 bezier curve. Should be used for very quick transforms.
+ */
+ public static final BakedBezierInterpolator TRANSFORM_FOLLOW_THROUGH_CURVE =
+ new BakedBezierInterpolator(TRANSFORM_FOLLOW_THROUGH_VALUES);
+
+ private final float[] mValues;
+ private final float mStepSize;
+
+ /**
+ * Use the INSTANCE variable instead of instantiating.
+ */
+ private BakedBezierInterpolator(float[] values) {
+ super();
+ mValues = values;
+ mStepSize = 1.f / (mValues.length - 1);
+ }
+
+ @Override
+ public float getInterpolation(float input) {
+ if (input >= 1.0f) {
+ return 1.0f;
+ }
+
+ if (input <= 0f) {
+ return 0f;
+ }
+
+ int position = Math.min(
+ (int)(input * (mValues.length - 1)),
+ mValues.length - 2);
+
+ float quantized = position * mStepSize;
+ float difference = input - quantized;
+ float weight = difference / mStepSize;
+
+ return mValues[position] + weight * (mValues[position + 1] - mValues[position]);
+ }
+
+}
\ No newline at end of file
diff --git a/ui/display/chromeos/touchscreen_delegate_impl.cc b/ui/display/chromeos/touchscreen_delegate_impl.cc
index 5311a82..dc60e3f 100644
--- a/ui/display/chromeos/touchscreen_delegate_impl.cc
+++ b/ui/display/chromeos/touchscreen_delegate_impl.cc
@@ -23,7 +23,38 @@
std::vector<DisplayConfigurator::DisplayState>* displays) {
std::set<int> no_match_touchscreen;
std::vector<TouchscreenDevice> devices = touch_device_manager_->GetDevices();
+
+ int internal_touchscreen = -1;
for (size_t i = 0; i < devices.size(); ++i) {
+ if (devices[i].is_internal) {
+ internal_touchscreen = i;
+ break;
+ }
+ }
+
+ DisplayConfigurator::DisplayState* internal_state = NULL;
+ for (size_t i = 0; i < displays->size(); ++i) {
+ DisplayConfigurator::DisplayState* state = &(*displays)[i];
+ if (state->display->type() == DISPLAY_CONNECTION_TYPE_INTERNAL &&
+ state->display->native_mode() &&
+ state->touch_device_id == 0) {
+ internal_state = state;
+ break;
+ }
+ }
+
+ if (internal_state && internal_touchscreen >= 0) {
+ internal_state->touch_device_id = devices[internal_touchscreen].id;
+ VLOG(2) << "Found internal touchscreen for internal display "
+ << internal_state->display->display_id() << " touch_device_id "
+ << internal_state->touch_device_id << " size "
+ << devices[internal_touchscreen].size.ToString();
+ }
+
+ for (size_t i = 0; i < devices.size(); ++i) {
+ if (internal_state &&
+ internal_state->touch_device_id == devices[i].id)
+ continue;
bool found_mapping = false;
for (size_t j = 0; j < displays->size(); ++j) {
DisplayConfigurator::DisplayState* state = &(*displays)[j];
diff --git a/ui/display/chromeos/touchscreen_delegate_impl_unittest.cc b/ui/display/chromeos/touchscreen_delegate_impl_unittest.cc
index b41fbdb..9e80712 100644
--- a/ui/display/chromeos/touchscreen_delegate_impl_unittest.cc
+++ b/ui/display/chromeos/touchscreen_delegate_impl_unittest.cc
@@ -48,8 +48,9 @@
delegate_.reset(new TouchscreenDelegateImpl(
scoped_ptr<TouchscreenDeviceManager>(device_manager_)));
- // Internal display. Must not be matched to a touch screen unless the size
- // matches.
+ // Internal display will always match to internal touchscreen. If internal
+ // touchscreen can't be detected, it is then associated to a touch screen
+ // with matching size.
TestDisplaySnapshot* snapshot = new TestDisplaySnapshot();
DisplayMode* mode = new DisplayMode(gfx::Size(1920, 1080), false, 60.0);
snapshot->set_type(DISPLAY_CONNECTION_TYPE_INTERNAL);
@@ -110,8 +111,8 @@
}
TEST_F(TouchscreenDelegateImplTest, OneToOneMapping) {
- device_manager_->AddDevice(TouchscreenDevice(1, gfx::Size(800, 600)));
- device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(1024, 768)));
+ device_manager_->AddDevice(TouchscreenDevice(1, gfx::Size(800, 600), false));
+ device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(1024, 768), false));
std::vector<DisplayConfigurator::DisplayState> display_states =
GetDisplayStates();
@@ -124,7 +125,7 @@
}
TEST_F(TouchscreenDelegateImplTest, MapToCorrectDisplaySize) {
- device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(1024, 768)));
+ device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(1024, 768), false));
std::vector<DisplayConfigurator::DisplayState> display_states =
GetDisplayStates();
@@ -137,8 +138,8 @@
}
TEST_F(TouchscreenDelegateImplTest, MapWhenSizeDiffersByOne) {
- device_manager_->AddDevice(TouchscreenDevice(1, gfx::Size(801, 600)));
- device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(1023, 768)));
+ device_manager_->AddDevice(TouchscreenDevice(1, gfx::Size(801, 600), false));
+ device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(1023, 768), false));
std::vector<DisplayConfigurator::DisplayState> display_states =
GetDisplayStates();
@@ -151,8 +152,8 @@
}
TEST_F(TouchscreenDelegateImplTest, MapWhenSizesDoNotMatch) {
- device_manager_->AddDevice(TouchscreenDevice(1, gfx::Size(1022, 768)));
- device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(802, 600)));
+ device_manager_->AddDevice(TouchscreenDevice(1, gfx::Size(1022, 768), false));
+ device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(802, 600), false));
std::vector<DisplayConfigurator::DisplayState> display_states =
GetDisplayStates();
@@ -164,4 +165,20 @@
EXPECT_EQ(2, display_states[3].touch_device_id);
}
+TEST_F(TouchscreenDelegateImplTest, MapInternalTouchscreen) {
+ device_manager_->AddDevice(
+ TouchscreenDevice(1, gfx::Size(1920, 1080), false));
+ device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(9999, 888), true));
+
+ std::vector<DisplayConfigurator::DisplayState> display_states =
+ GetDisplayStates();
+ delegate_->AssociateTouchscreens(&display_states);
+
+ // Internal touchscreen is always mapped to internal display.
+ EXPECT_EQ(2, display_states[0].touch_device_id);
+ EXPECT_EQ(1, display_states[1].touch_device_id);
+ EXPECT_EQ(TouchscreenDevice::kInvalidId, display_states[2].touch_device_id);
+ EXPECT_EQ(TouchscreenDevice::kInvalidId, display_states[3].touch_device_id);
+}
+
} // namespace ui
diff --git a/ui/display/chromeos/x11/touchscreen_device_manager_x11.cc b/ui/display/chromeos/x11/touchscreen_device_manager_x11.cc
index 6c8137b..f613532 100644
--- a/ui/display/chromeos/x11/touchscreen_device_manager_x11.cc
+++ b/ui/display/chromeos/x11/touchscreen_device_manager_x11.cc
@@ -9,9 +9,88 @@
#include <cmath>
#include <set>
+#include <string>
+#include <vector>
+#include "base/command_line.h"
+#include "base/files/file_enumerator.h"
+#include "base/logging.h"
+#include "base/process/launch.h"
+#include "base/strings/string_util.h"
+#include "base/sys_info.h"
#include "ui/gfx/x/x11_types.h"
+namespace {
+
+// We consider the touchscreen to be internal if it is an I2c device.
+// With the device id, we can query X to get the device's dev input
+// node eventXXX. Then we search all the dev input nodes registered
+// by I2C devices to see if we can find eventXXX.
+bool IsTouchscreenInternal(XDisplay* dpy, int device_id) {
+ using base::FileEnumerator;
+ using base::FilePath;
+
+ if (!base::SysInfo::IsRunningOnChromeOS())
+ return false;
+
+ // Input device has a property "Device Node" pointing to its dev input node,
+ // e.g. Device Node (250): "/dev/input/event8"
+ Atom device_node = XInternAtom(dpy, "Device Node", False);
+ if (device_node == None)
+ return false;
+
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems, bytes_after;
+ unsigned char* data;
+ XDevice* dev = XOpenDevice(dpy, device_id);
+ if (!dev)
+ return false;
+
+ if (XGetDeviceProperty(dpy, dev, device_node, 0, 1000, False,
+ AnyPropertyType, &actual_type, &actual_format,
+ &nitems, &bytes_after, &data) != Success) {
+ XCloseDevice(dpy, dev);
+ return false;
+ }
+ base::FilePath dev_node_path(reinterpret_cast<char*>(data));
+ XFree(data);
+ XCloseDevice(dpy, dev);
+
+ std::string event_node = dev_node_path.BaseName().value();
+ if (event_node.empty() ||
+ !StartsWithASCII(event_node, "event", false)) {
+ return false;
+ }
+
+ // Extract id "XXX" from "eventXXX"
+ std::string event_node_id = event_node.substr(5);
+
+ // I2C input device registers its dev input node at
+ // /sys/bus/i2c/devices/*/input/inputXXX/eventXXX
+ FileEnumerator i2c_enum(FilePath(FILE_PATH_LITERAL("/sys/bus/i2c/devices/")),
+ false,
+ base::FileEnumerator::DIRECTORIES);
+ for (FilePath i2c_name = i2c_enum.Next();
+ !i2c_name.empty();
+ i2c_name = i2c_enum.Next()) {
+ FileEnumerator input_enum(i2c_name.Append(FILE_PATH_LITERAL("input")),
+ false,
+ base::FileEnumerator::DIRECTORIES,
+ FILE_PATH_LITERAL("input*"));
+ for (base::FilePath input = input_enum.Next();
+ !input.empty();
+ input = input_enum.Next()) {
+ if (input.BaseName().value().substr(5) == event_node_id)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+} // namespace
+
namespace ui {
TouchscreenDeviceManagerX11::TouchscreenDeviceManagerX11()
@@ -70,8 +149,10 @@
// Touchscreens should have absolute X and Y axes, and be direct touch
// devices.
if (width > 0.0 && height > 0.0 && is_direct_touch) {
+ bool is_internal = IsTouchscreenInternal(display_, info[i].deviceid);
devices.push_back(TouchscreenDevice(info[i].deviceid,
- gfx::Size(width, height)));
+ gfx::Size(width, height),
+ is_internal));
}
}
diff --git a/ui/display/types/chromeos/touchscreen_device.cc b/ui/display/types/chromeos/touchscreen_device.cc
index 09ee885..714b8f9 100644
--- a/ui/display/types/chromeos/touchscreen_device.cc
+++ b/ui/display/types/chromeos/touchscreen_device.cc
@@ -9,8 +9,11 @@
// static
const int TouchscreenDevice::kInvalidId = 0;
-TouchscreenDevice::TouchscreenDevice(int id, const gfx::Size& size)
+TouchscreenDevice::TouchscreenDevice(int id,
+ const gfx::Size& size,
+ bool is_internal)
: id(id),
- size(size) {}
+ size(size),
+ is_internal(is_internal) {}
} // namespace ui
diff --git a/ui/display/types/chromeos/touchscreen_device.h b/ui/display/types/chromeos/touchscreen_device.h
index ecc6452..3a471fa 100644
--- a/ui/display/types/chromeos/touchscreen_device.h
+++ b/ui/display/types/chromeos/touchscreen_device.h
@@ -14,13 +14,16 @@
struct DISPLAY_TYPES_EXPORT TouchscreenDevice {
static const int kInvalidId;
- TouchscreenDevice(int id, const gfx::Size& size);
+ TouchscreenDevice(int id, const gfx::Size& size, bool is_internal);
// ID of the touch screen. This ID must uniquely identify the touch screen.
int id;
// Size of the touch screen area.
gfx::Size size;
+
+ // True if this is an internal touchscreen.
+ bool is_internal;
};
} // namespace ui
diff --git a/ui/views/accessibility/native_view_accessibility_win.cc b/ui/views/accessibility/native_view_accessibility_win.cc
index fb5e177..670de4d 100644
--- a/ui/views/accessibility/native_view_accessibility_win.cc
+++ b/ui/views/accessibility/native_view_accessibility_win.cc
@@ -30,9 +30,6 @@
namespace views {
namespace {
-// A version of the OBJID_CLIENT constant that works in 64-bit mode too.
-static const LPARAM kObjIdClient = static_cast<ULONG>(OBJID_CLIENT);
-
class AccessibleWebViewRegistry {
public:
static AccessibleWebViewRegistry* GetInstance();
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index 60458c7..1a45795 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -932,6 +932,11 @@
desktop_window_tree_host_->OnRootViewLayout();
}
+bool DesktopNativeWidgetAura::IsTranslucentWindowOpacitySupported() const {
+ return content_window_ &&
+ desktop_window_tree_host_->IsTranslucentWindowOpacitySupported();
+}
+
void DesktopNativeWidgetAura::RepostNativeEvent(gfx::NativeEvent native_event) {
OnEvent(native_event);
}
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
index f265814..f005f36 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
@@ -178,6 +178,7 @@
virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE;
virtual ui::NativeTheme* GetNativeTheme() const OVERRIDE;
virtual void OnRootViewLayout() const OVERRIDE;
+ virtual bool IsTranslucentWindowOpacitySupported() const OVERRIDE;
virtual void RepostNativeEvent(gfx::NativeEvent native_event) OVERRIDE;
// Overridden from aura::WindowDelegate:
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host.h b/ui/views/widget/desktop_aura/desktop_window_tree_host.h
index 26925b6..9ccb672 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host.h
@@ -153,6 +153,9 @@
// Returns true if the Widget was closed but is still showing because of
// animations.
virtual bool IsAnimatingClosed() const = 0;
+
+ // Returns true if the Widget supports translucency.
+ virtual bool IsTranslucentWindowOpacitySupported() const = 0;
};
} // namespace views
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index fc2bda6..6347526 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -365,7 +365,7 @@
}
bool DesktopWindowTreeHostWin::ShouldUseNativeFrame() const {
- return ui::win::IsAeroGlassEnabled();
+ return IsTranslucentWindowOpacitySupported();
}
bool DesktopWindowTreeHostWin::ShouldWindowContentsBeTransparent() const {
@@ -427,6 +427,10 @@
return pending_close_;
}
+bool DesktopWindowTreeHostWin::IsTranslucentWindowOpacitySupported() const {
+ return ui::win::IsAeroGlassEnabled();
+}
+
////////////////////////////////////////////////////////////////////////////////
// DesktopWindowTreeHostWin, WindowTreeHost implementation:
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
index 5fb0639..225365f 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
@@ -103,6 +103,7 @@
virtual void OnNativeWidgetFocus() OVERRIDE;
virtual void OnNativeWidgetBlur() OVERRIDE;
virtual bool IsAnimatingClosed() const OVERRIDE;
+ virtual bool IsTranslucentWindowOpacitySupported() const OVERRIDE;
// Overridden from aura::WindowTreeHost:
virtual ui::EventSource* GetEventSource() OVERRIDE;
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
index e7d86b5..74026c1 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -831,6 +831,10 @@
return false;
}
+bool DesktopWindowTreeHostX11::IsTranslucentWindowOpacitySupported() const {
+ return false;
+}
+
////////////////////////////////////////////////////////////////////////////////
// DesktopWindowTreeHostX11, aura::WindowTreeHost implementation:
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
index cbcd9fc..cee65f5 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
@@ -144,6 +144,7 @@
virtual void OnNativeWidgetFocus() OVERRIDE;
virtual void OnNativeWidgetBlur() OVERRIDE;
virtual bool IsAnimatingClosed() const OVERRIDE;
+ virtual bool IsTranslucentWindowOpacitySupported() const OVERRIDE;
// Overridden from aura::WindowTreeHost:
virtual ui::EventSource* GetEventSource() OVERRIDE;
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index e26c52c..a1f05c4 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -691,6 +691,10 @@
void NativeWidgetAura::OnRootViewLayout() const {
}
+bool NativeWidgetAura::IsTranslucentWindowOpacitySupported() const {
+ return true;
+}
+
void NativeWidgetAura::RepostNativeEvent(gfx::NativeEvent native_event) {
OnEvent(native_event);
}
diff --git a/ui/views/widget/native_widget_aura.h b/ui/views/widget/native_widget_aura.h
index 3b1e58a..dd6fafe 100644
--- a/ui/views/widget/native_widget_aura.h
+++ b/ui/views/widget/native_widget_aura.h
@@ -132,6 +132,7 @@
virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE;
virtual ui::NativeTheme* GetNativeTheme() const OVERRIDE;
virtual void OnRootViewLayout() const OVERRIDE;
+ virtual bool IsTranslucentWindowOpacitySupported() const OVERRIDE;
virtual void RepostNativeEvent(gfx::NativeEvent native_event) OVERRIDE;
// Overridden from views::InputMethodDelegate:
diff --git a/ui/views/widget/native_widget_mac.h b/ui/views/widget/native_widget_mac.h
index 0cd87b7..64cb9a3 100644
--- a/ui/views/widget/native_widget_mac.h
+++ b/ui/views/widget/native_widget_mac.h
@@ -102,6 +102,7 @@
virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE;
virtual ui::NativeTheme* GetNativeTheme() const OVERRIDE;
virtual void OnRootViewLayout() const OVERRIDE;
+ virtual bool IsTranslucentWindowOpacitySupported() const OVERRIDE;
virtual void RepostNativeEvent(gfx::NativeEvent native_event) OVERRIDE;
private:
diff --git a/ui/views/widget/native_widget_mac.mm b/ui/views/widget/native_widget_mac.mm
index 729207a..37545b9 100644
--- a/ui/views/widget/native_widget_mac.mm
+++ b/ui/views/widget/native_widget_mac.mm
@@ -359,6 +359,10 @@
NOTIMPLEMENTED();
}
+bool NativeWidgetMac::IsTranslucentWindowOpacitySupported() const {
+ return false;
+}
+
void NativeWidgetMac::RepostNativeEvent(gfx::NativeEvent native_event) {
NOTIMPLEMENTED();
}
diff --git a/ui/views/widget/native_widget_private.h b/ui/views/widget/native_widget_private.h
index d87bb0f..8c9233a 100644
--- a/ui/views/widget/native_widget_private.h
+++ b/ui/views/widget/native_widget_private.h
@@ -227,6 +227,7 @@
virtual void SetVisibilityChangedAnimationsEnabled(bool value) = 0;
virtual ui::NativeTheme* GetNativeTheme() const = 0;
virtual void OnRootViewLayout() const = 0;
+ virtual bool IsTranslucentWindowOpacitySupported() const = 0;
// Repost an unhandled event to the native widget for default OS processing.
virtual void RepostNativeEvent(gfx::NativeEvent native_event) = 0;
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc
index fdcb32a..3f4a170 100644
--- a/ui/views/widget/widget.cc
+++ b/ui/views/widget/widget.cc
@@ -981,6 +981,10 @@
native_widget_->OnRootViewLayout();
}
+bool Widget::IsTranslucentWindowOpacitySupported() const {
+ return native_widget_->IsTranslucentWindowOpacitySupported();
+}
+
void Widget::OnOwnerClosing() {
}
diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h
index bc3f914..c76633b 100644
--- a/ui/views/widget/widget.h
+++ b/ui/views/widget/widget.h
@@ -198,6 +198,9 @@
WidgetDelegate* delegate;
bool child;
// If TRANSLUCENT_WINDOW, the widget may be fully or partially transparent.
+ // Translucent windows may not always be supported. Use
+ // IsTranslucentWindowOpacitySupported to determine if translucent windows
+ // are supported.
// If OPAQUE_WINDOW, we can perform optimizations based on the widget being
// fully opaque. Defaults to TRANSLUCENT_WINDOW if
// ViewsDelegate::UseTransparentWindows(). Defaults to OPAQUE_WINDOW for
@@ -726,6 +729,9 @@
// window sizing information to the window server on some platforms.
void OnRootViewLayout();
+ // Whether the widget supports translucency.
+ bool IsTranslucentWindowOpacitySupported() const;
+
// Notification that our owner is closing.
// NOTE: this is not invoked for aura as it's currently not needed there.
// Under aura menus close by way of activation getting reset when the owner
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc
index d6ab099..d606206 100644
--- a/ui/views/widget/widget_unittest.cc
+++ b/ui/views/widget/widget_unittest.cc
@@ -623,6 +623,7 @@
widget->ReleaseCapture();
widget->HasCapture();
widget->GetWorkAreaBoundsInScreen();
+ widget->IsTranslucentWindowOpacitySupported();
}
private:
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index e4f55bf..adbe4fa 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -45,9 +45,6 @@
namespace views {
namespace {
-// A version of the OBJID_CLIENT constant that works in 64-bit mode too.
-static const LPARAM kObjIdClient = static_cast<ULONG>(OBJID_CLIENT);
-
// MoveLoopMouseWatcher is used to determine if the user canceled or completed a
// move. win32 doesn't appear to offer a way to determine the result of a move,
// so we install hooks to determine if we got a mouse up and assume the move
@@ -1419,8 +1416,12 @@
LPARAM l_param) {
LRESULT reference_result = static_cast<LRESULT>(0L);
+ // Only the lower 32 bits of l_param are valid when checking the object id
+ // because it sometimes gets sign-extended incorrectly (but not always).
+ DWORD obj_id = static_cast<DWORD>(static_cast<DWORD_PTR>(l_param));
+
// Accessibility readers will send an OBJID_CLIENT message
- if (kObjIdClient == l_param) {
+ if (OBJID_CLIENT == obj_id) {
// Retrieve MSAA dispatch object for the root view.
base::win::ScopedComPtr<IAccessible> root(
delegate_->GetNativeViewAccessible());