Merge from Chromium at DEPS revision 30.0.1599.38
This commit was generated by merge_to_master.py.
Change-Id: Id08bb8b59eaaeaecaf66c3f1d40cd1f7bc61aac2
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc
index 6577044..073fe36 100644
--- a/android_webview/browser/aw_browser_context.cc
+++ b/android_webview/browser/aw_browser_context.cc
@@ -21,6 +21,8 @@
#include "content/public/browser/web_contents.h"
#include "net/url_request/url_request_context.h"
+using content::BrowserThread;
+
namespace android_webview {
namespace {
@@ -37,11 +39,11 @@
// content::ResourceContext implementation.
virtual net::HostResolver* GetHostResolver() OVERRIDE {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
return getter_->GetURLRequestContext()->host_resolver();
}
virtual net::URLRequestContext* GetRequestContext() OVERRIDE {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
return getter_->GetURLRequestContext();
}
virtual bool AllowMicAccess(const GURL& origin) OVERRIDE {
@@ -69,6 +71,10 @@
user_pref_service_ready_(false) {
DCHECK(g_browser_context == NULL);
g_browser_context = this;
+
+ // This constructor is entered during the creation of ContentBrowserClient,
+ // before browser threads are created. Therefore any checks to enforce
+ // threading (such as BrowserThread::CurrentlyOn()) will fail here.
}
AwBrowserContext::~AwBrowserContext() {
@@ -99,6 +105,9 @@
visitedlink_master_.reset(
new visitedlink::VisitedLinkMaster(this, this, false));
visitedlink_master_->Init();
+
+ form_database_service_.reset(
+ new AwFormDatabaseService(context_storage_path_));
}
void AwBrowserContext::AddVisitedURLs(const std::vector<GURL>& urls) {
@@ -131,10 +140,6 @@
}
AwFormDatabaseService* AwBrowserContext::GetFormDatabaseService() {
- if (!form_database_service_) {
- form_database_service_.reset(
- new AwFormDatabaseService(context_storage_path_));
- }
return form_database_service_.get();
}
diff --git a/android_webview/browser/aw_form_database_service.cc b/android_webview/browser/aw_form_database_service.cc
index 2b168de..de6b953 100644
--- a/android_webview/browser/aw_form_database_service.cc
+++ b/android_webview/browser/aw_form_database_service.cc
@@ -4,11 +4,13 @@
#include "android_webview/browser/aw_form_database_service.h"
#include "base/logging.h"
+#include "base/synchronization/waitable_event.h"
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/webdata/common/webdata_constants.h"
#include "content/public/browser/browser_thread.h"
#include "ui/base/l10n/l10n_util_android.h"
+using base::WaitableEvent;
using content::BrowserThread;
namespace {
@@ -23,11 +25,8 @@
namespace android_webview {
-AwFormDatabaseService::AwFormDatabaseService(const base::FilePath path)
- : pending_query_handle_(0),
- has_form_data_(false),
- completion_(false, false) {
-
+AwFormDatabaseService::AwFormDatabaseService(const base::FilePath path) {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
web_database_ = new WebDatabaseService(path.Append(kWebDataFilename),
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB));
@@ -42,30 +41,33 @@
}
AwFormDatabaseService::~AwFormDatabaseService() {
- CancelPendingQuery();
Shutdown();
}
void AwFormDatabaseService::Shutdown() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(result_map_.empty());
+ // TODO(sgurun) we don't run into this logic right now,
+ // but if we do, then we need to implement cancellation
+ // of pending queries.
autofill_data_->ShutdownOnUIThread();
web_database_->ShutdownDatabase();
}
-void AwFormDatabaseService::CancelPendingQuery() {
- if (pending_query_handle_) {
- if (autofill_data_.get())
- autofill_data_->CancelRequest(pending_query_handle_);
- pending_query_handle_ = 0;
- }
-}
-
scoped_refptr<autofill::AutofillWebDataService>
AwFormDatabaseService::get_autofill_webdata_service() {
return autofill_data_;
}
void AwFormDatabaseService::ClearFormData() {
+ BrowserThread::PostTask(
+ BrowserThread::DB,
+ FROM_HERE,
+ base::Bind(&AwFormDatabaseService::ClearFormDataImpl,
+ base::Unretained(this)));
+}
+
+void AwFormDatabaseService::ClearFormDataImpl() {
base::Time begin;
base::Time end = base::Time::Max();
autofill_data_->RemoveFormElementsAddedBetween(begin, end);
@@ -73,35 +75,50 @@
}
bool AwFormDatabaseService::HasFormData() {
- BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
+ WaitableEvent completion(false, false);
+ bool result = false;
+ BrowserThread::PostTask(
+ BrowserThread::DB,
+ FROM_HERE,
base::Bind(&AwFormDatabaseService::HasFormDataImpl,
- base::Unretained(this)));
- completion_.Wait();
- return has_form_data_;
+ base::Unretained(this),
+ &completion,
+ &result));
+ completion.Wait();
+ return result;
}
-void AwFormDatabaseService::HasFormDataImpl() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
- pending_query_handle_ = autofill_data_->HasFormElements(this);
+void AwFormDatabaseService::HasFormDataImpl(
+ WaitableEvent* completion,
+ bool* result) {
+ WebDataServiceBase::Handle pending_query_handle =
+ autofill_data_->HasFormElements(this);
+ PendingQuery query;
+ query.result = result;
+ query.completion = completion;
+ result_map_[pending_query_handle] = query;
}
-
void AwFormDatabaseService::OnWebDataServiceRequestDone(
WebDataServiceBase::Handle h,
const WDTypedResult* result) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
- DCHECK_EQ(pending_query_handle_, h);
- pending_query_handle_ = 0;
- has_form_data_ = false;
-
+ bool has_form_data = false;
if (result) {
DCHECK_EQ(AUTOFILL_VALUE_RESULT, result->GetType());
const WDResult<bool>* autofill_result =
static_cast<const WDResult<bool>*>(result);
- has_form_data_ = autofill_result->GetValue();
+ has_form_data = autofill_result->GetValue();
}
- completion_.Signal();
+ QueryMap::const_iterator it = result_map_.find(h);
+ if (it == result_map_.end()) {
+ LOG(WARNING) << "Received unexpected callback from web data service";
+ return;
+ }
+ *(it->second.result) = has_form_data;
+ it->second.completion->Signal();
+ result_map_.erase(h);
}
} // namespace android_webview
diff --git a/android_webview/browser/aw_form_database_service.h b/android_webview/browser/aw_form_database_service.h
index c1cbc37..d0b7b48 100644
--- a/android_webview/browser/aw_form_database_service.h
+++ b/android_webview/browser/aw_form_database_service.h
@@ -7,11 +7,14 @@
#include "base/basictypes.h"
#include "base/files/file_path.h"
-#include "base/synchronization/waitable_event.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/webdata/common/web_data_service_consumer.h"
#include "components/webdata/common/web_database_service.h"
+namespace base {
+class WaitableEvent;
+};
+
namespace android_webview {
// Handles the database operations necessary to implement the autocomplete
@@ -42,15 +45,16 @@
const WDTypedResult* result) OVERRIDE;
private:
- // Cancels the currently pending WebDataService query, if there is one.
- void CancelPendingQuery();
+ struct PendingQuery {
+ bool* result;
+ base::WaitableEvent* completion;
+ };
+ typedef std::map<WebDataServiceBase::Handle, PendingQuery> QueryMap;
- void HasFormDataImpl();
+ void ClearFormDataImpl();
+ void HasFormDataImpl(base::WaitableEvent* completion, bool* result);
- // Stores the query handle when an async database query is executed.
- WebDataServiceBase::Handle pending_query_handle_;
- bool has_form_data_;
- base::WaitableEvent completion_;
+ QueryMap result_map_;
scoped_refptr<autofill::AutofillWebDataService> autofill_data_;
scoped_refptr<WebDatabaseService> web_database_;
diff --git a/ash/system/chromeos/network/network_icon.cc b/ash/system/chromeos/network/network_icon.cc
index efe7e07..bd32a9f 100644
--- a/ash/system/chromeos/network/network_icon.cc
+++ b/ash/system/chromeos/network/network_icon.cc
@@ -620,8 +620,9 @@
// For networks that are always in roaming don't show roaming badge.
const DeviceState* device =
handler->GetDeviceState(network->device_path());
- DCHECK(device);
- if (!device->provider_requires_roaming()) {
+ LOG_IF(WARNING, !device) << "Could not find device state for "
+ << network->device_path();
+ if (!device || !device->provider_requires_roaming()) {
badges->bottom_right = rb.GetImageSkiaNamed(
IconTypeIsDark(icon_type_) ?
IDR_AURA_UBER_TRAY_NETWORK_ROAMING_DARK :
diff --git a/build/util/LASTCHANGE b/build/util/LASTCHANGE
index cbaafd0..0ea7e89 100644
--- a/build/util/LASTCHANGE
+++ b/build/util/LASTCHANGE
@@ -1 +1 @@
-LASTCHANGE=222137
+LASTCHANGE=222409
diff --git a/build/util/LASTCHANGE.blink b/build/util/LASTCHANGE.blink
index 14ed93f..7a0a5ff 100644
--- a/build/util/LASTCHANGE.blink
+++ b/build/util/LASTCHANGE.blink
@@ -1 +1 @@
-LASTCHANGE=157465
+LASTCHANGE=157551
diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc
index a9beeb1..9bf2efe 100644
--- a/cc/output/software_renderer.cc
+++ b/cc/output/software_renderer.cc
@@ -314,9 +314,10 @@
// TODO(aelias): This isn't correct in all cases. We should detect these
// cases and fall back to a persistent bitmap backing
// (http://crbug.com/280374).
+ skia::RefPtr<SkDrawFilter> opacity_filter =
+ skia::AdoptRef(new skia::OpacityDrawFilter(quad->opacity(), true));
DCHECK(!current_canvas_->getDrawFilter());
- current_canvas_->setDrawFilter(new skia::OpacityDrawFilter(quad->opacity(),
- true));
+ current_canvas_->setDrawFilter(opacity_filter.get());
TRACE_EVENT0("cc",
"SoftwareRenderer::DrawPictureQuad");
diff --git a/chrome/VERSION b/chrome/VERSION
index 22090b2..71496bd 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
MAJOR=30
MINOR=0
BUILD=1599
-PATCH=36
+PATCH=38
diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc
index 2b72037..260c94b 100644
--- a/chrome/browser/printing/print_view_manager.cc
+++ b/chrome/browser/printing/print_view_manager.cc
@@ -97,7 +97,8 @@
}
void PrintViewManager::PrintPreviewForWebNode() {
- DCHECK_EQ(NOT_PREVIEWING, print_preview_state_);
+ if (print_preview_state_ != NOT_PREVIEWING)
+ return;
print_preview_state_ = USER_INITIATED_PREVIEW;
}
@@ -133,8 +134,7 @@
observer_->OnPrintDialogShown();
}
-void PrintViewManager::OnScriptedPrintPreview(bool source_is_modifiable,
- IPC::Message* reply_msg) {
+void PrintViewManager::OnSetupScriptedPrintPreview(IPC::Message* reply_msg) {
BrowserThread::CurrentlyOn(BrowserThread::UI);
ScriptedPrintPreviewClosureMap& map =
g_scripted_print_preview_closure_map.Get();
@@ -168,7 +168,15 @@
reply_msg);
map[rph] = callback;
scripted_print_preview_rph_ = rph;
+}
+void PrintViewManager::OnShowScriptedPrintPreview(bool source_is_modifiable) {
+ PrintPreviewDialogController* dialog_controller =
+ PrintPreviewDialogController::GetInstance();
+ if (!dialog_controller) {
+ PrintPreviewDone();
+ return;
+ }
dialog_controller->PrintPreview(web_contents());
PrintHostMsg_RequestPrintPreview_Params params;
params.is_modifiable = source_is_modifiable;
@@ -185,8 +193,10 @@
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PrintViewManager, message)
IPC_MESSAGE_HANDLER(PrintHostMsg_DidShowPrintDialog, OnDidShowPrintDialog)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrintPreview,
- OnScriptedPrintPreview)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_SetupScriptedPrintPreview,
+ OnSetupScriptedPrintPreview)
+ IPC_MESSAGE_HANDLER(PrintHostMsg_ShowScriptedPrintPreview,
+ OnShowScriptedPrintPreview)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
diff --git a/chrome/browser/printing/print_view_manager.h b/chrome/browser/printing/print_view_manager.h
index 6e24e98..333fb6a 100644
--- a/chrome/browser/printing/print_view_manager.h
+++ b/chrome/browser/printing/print_view_manager.h
@@ -74,8 +74,8 @@
// IPC Message handlers.
void OnDidShowPrintDialog();
- void OnScriptedPrintPreview(bool source_is_modifiable,
- IPC::Message* reply_msg);
+ void OnSetupScriptedPrintPreview(IPC::Message* reply_msg);
+ void OnShowScriptedPrintPreview(bool source_is_modifiable);
void OnScriptedPrintPreviewReply(IPC::Message* reply_msg);
// Weak pointer to an observer that is notified when the print dialog is
diff --git a/chrome/browser/resources/chromeos/speech_synthesis/manifest.json b/chrome/browser/resources/chromeos/speech_synthesis/manifest.json
index a756710..26cce46 100644
--- a/chrome/browser/resources/chromeos/speech_synthesis/manifest.json
+++ b/chrome/browser/resources/chromeos/speech_synthesis/manifest.json
@@ -11,6 +11,7 @@
"voice_data_hmm_es-ES.js",
"voice_data_hmm_fr-FR.js",
"voice_data_hmm_it-IT.js",
+ "tts_controller.js",
"tts_main.js"
]
},
diff --git a/chrome/common/extensions/api/_manifest_features.json b/chrome/common/extensions/api/_manifest_features.json
index 0b75869..0b9097c 100644
--- a/chrome/common/extensions/api/_manifest_features.json
+++ b/chrome/common/extensions/api/_manifest_features.json
@@ -256,7 +256,9 @@
"hkhhlkdconhgemhegnplaldnmnmkaemd", // Get Started App
"nmmhkkegccagdldgiimedpiccmgmieda", // In-app payments support app.
"4B1D0E19C6C43C008C44A8278C8B5BFE15ABEB3C",
- "F7FA7ABC1ECB89BA8EE6656847EFABBF43BB9BCA"
+ "F7FA7ABC1ECB89BA8EE6656847EFABBF43BB9BCA",
+ "1A26E32DE447A17CBE5E9750CDBA78F58539B39C", // TODO(rockot): Kill these.
+ "E61F841D8210B6A9891E5384CB665FBED31FCD7B" // See http://crbug.com/281715
]
},
"offline_enabled": {
diff --git a/chrome/common/print_messages.h b/chrome/common/print_messages.h
index 258ee27..bfc0026 100644
--- a/chrome/common/print_messages.h
+++ b/chrome/common/print_messages.h
@@ -436,8 +436,12 @@
// Run a nested message loop in the renderer until print preview for
// window.print() finishes.
-IPC_SYNC_MESSAGE_ROUTED1_0(PrintHostMsg_ScriptedPrintPreview,
- bool /* is_modifiable */)
+IPC_SYNC_MESSAGE_ROUTED0_0(PrintHostMsg_SetupScriptedPrintPreview)
+
+// Tell the browser to show the print preview, when the document is sufficiently
+// loaded such that the renderer can determine whether it is modifiable or not.
+IPC_MESSAGE_ROUTED1(PrintHostMsg_ShowScriptedPrintPreview,
+ bool /* is_modifiable */)
// Notify the browser that the PDF in the initiator renderer has disabled print
// scaling option.
diff --git a/chrome/renderer/chrome_render_view_observer.cc b/chrome/renderer/chrome_render_view_observer.cc
index c6a45fd..81a7cbf 100644
--- a/chrome/renderer/chrome_render_view_observer.cc
+++ b/chrome/renderer/chrome_render_view_observer.cc
@@ -566,8 +566,7 @@
if (allowed_per_settings || allow_displaying_insecure_content_)
return true;
- if (!IsStrictSecurityHost(origin_host))
- Send(new ChromeViewHostMsg_DidBlockDisplayingInsecureContent(routing_id()));
+ Send(new ChromeViewHostMsg_DidBlockDisplayingInsecureContent(routing_id()));
return false;
}
@@ -631,8 +630,7 @@
SendInsecureContentSignal(INSECURE_CONTENT_RUN_SWF);
if (!allow_running_insecure_content_ && !allowed_per_settings) {
- if (!IsStrictSecurityHost(origin_host))
- content_settings_->DidNotAllowMixedScript();
+ content_settings_->DidNotAllowMixedScript();
return false;
}
diff --git a/chrome/renderer/printing/print_web_view_helper.cc b/chrome/renderer/printing/print_web_view_helper.cc
index 7bb330b..a7f9e7d 100644
--- a/chrome/renderer/printing/print_web_view_helper.cc
+++ b/chrome/renderer/printing/print_web_view_helper.cc
@@ -304,14 +304,16 @@
print_params.desired_dpi);
}
+WebKit::WebPlugin* GetPlugin(const WebKit::WebFrame* frame) {
+ return frame->document().isPluginDocument() ?
+ frame->document().to<WebKit::WebPluginDocument>().plugin() : NULL;
+}
+
bool PrintingNodeOrPdfFrame(const WebKit::WebFrame* frame,
const WebKit::WebNode& node) {
if (!node.isNull())
return true;
- if (!frame->document().isPluginDocument())
- return false;
- WebKit::WebPlugin* plugin =
- frame->document().to<WebKit::WebPluginDocument>().plugin();
+ WebKit::WebPlugin* plugin = GetPlugin(frame);
return plugin && plugin->supportsPaginatedPrint();
}
@@ -741,7 +743,10 @@
is_scripted_printing_blocked_(false),
notify_browser_of_print_failure_(true),
print_for_preview_(false),
- print_node_in_progress_(false) {
+ print_node_in_progress_(false),
+ is_loading_(false),
+ is_scripted_preview_delayed_(false),
+ weak_ptr_factory_(this) {
}
PrintWebViewHelper::~PrintWebViewHelper() {}
@@ -761,6 +766,15 @@
return true;
}
+void PrintWebViewHelper::DidStartLoading() {
+ is_loading_ = true;
+}
+
+void PrintWebViewHelper::DidStopLoading() {
+ is_loading_ = false;
+ ShowScriptedPrintPreview();
+}
+
// Prints |frame| which called window.print().
void PrintWebViewHelper::PrintPage(WebKit::WebFrame* frame,
bool user_initiated) {
@@ -1664,6 +1678,15 @@
last_cancelled_script_print_ = base::Time::Now();
}
+
+void PrintWebViewHelper::ShowScriptedPrintPreview() {
+ if (is_scripted_preview_delayed_) {
+ is_scripted_preview_delayed_ = false;
+ Send(new PrintHostMsg_ShowScriptedPrintPreview(routing_id(),
+ print_preview_context_.IsModifiable()));
+ }
+}
+
void PrintWebViewHelper::RequestPrintPreview(PrintPreviewRequestType type) {
const bool is_modifiable = print_preview_context_.IsModifiable();
const bool has_selection = print_preview_context_.HasSelection();
@@ -1673,10 +1696,27 @@
params.has_selection = has_selection;
switch (type) {
case PRINT_PREVIEW_SCRIPTED: {
+ // Shows scripted print preview in two stages.
+ // 1. PrintHostMsg_SetupScriptedPrintPreview blocks this call and JS by
+ // pumping messages here.
+ // 2. PrintHostMsg_ShowScriptedPrintPreview shows preview once the
+ // document has been loaded.
+ is_scripted_preview_delayed_ = true;
+ if (is_loading_ && GetPlugin(print_preview_context_.source_frame())) {
+ // Wait for DidStopLoading. Plugins may not know the correct
+ // |is_modifiable| value until they are fully loaded, which occurs when
+ // DidStopLoading() is called. Defer showing the preview until then.
+ } else {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&PrintWebViewHelper::ShowScriptedPrintPreview,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
IPC::SyncMessage* msg =
- new PrintHostMsg_ScriptedPrintPreview(routing_id(), is_modifiable);
+ new PrintHostMsg_SetupScriptedPrintPreview(routing_id());
msg->EnableMessagePumping();
Send(msg);
+ is_scripted_preview_delayed_ = false;
return;
}
case PRINT_PREVIEW_USER_INITIATED_ENTIRE_FRAME: {
diff --git a/chrome/renderer/printing/print_web_view_helper.h b/chrome/renderer/printing/print_web_view_helper.h
index d10db97..bad03aa 100644
--- a/chrome/renderer/printing/print_web_view_helper.h
+++ b/chrome/renderer/printing/print_web_view_helper.h
@@ -10,6 +10,7 @@
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
+#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "content/public/renderer/render_view_observer.h"
#include "content/public/renderer/render_view_observer_tracker.h"
@@ -112,6 +113,8 @@
// RenderViewObserver implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
virtual void PrintPage(WebKit::WebFrame* frame, bool user_initiated) OVERRIDE;
+ virtual void DidStartLoading() OVERRIDE;
+ virtual void DidStopLoading() OVERRIDE;
// Message handlers ---------------------------------------------------------
@@ -326,6 +329,9 @@
// Scripted printing will be blocked for a limited amount of time.
void IncrementScriptedPrintCount();
+ // Shows scripted print preview when options from plugin are availible.
+ void ShowScriptedPrintPreview();
+
void RequestPrintPreview(PrintPreviewRequestType type);
// Checks whether print preview should continue or not.
@@ -478,6 +484,9 @@
bool print_node_in_progress_;
PrintPreviewContext print_preview_context_;
+ bool is_loading_;
+ bool is_scripted_preview_delayed_;
+ base::WeakPtrFactory<PrintWebViewHelper> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(PrintWebViewHelper);
};
diff --git a/chromeos/audio/cras_audio_handler.cc b/chromeos/audio/cras_audio_handler.cc
index 3fa81cb..00ab2af 100644
--- a/chromeos/audio/cras_audio_handler.cc
+++ b/chromeos/audio/cras_audio_handler.cc
@@ -517,9 +517,29 @@
}
}
+bool CrasAudioHandler::HasDeviceChange(const AudioNodeList& new_nodes,
+ bool is_input) {
+ size_t num_old_devices = 0;
+ size_t num_new_devices = 0;
+ for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
+ it != audio_devices_.end(); ++it) {
+ if (is_input == it->second.is_input)
+ ++num_old_devices;
+ }
+
+ for (AudioNodeList::const_iterator it = new_nodes.begin();
+ it != new_nodes.end(); ++it) {
+ if (is_input == it->is_input)
+ ++num_new_devices;
+ }
+ return num_old_devices != num_new_devices;
+}
+
void CrasAudioHandler::UpdateDevicesAndSwitchActive(
const AudioNodeList& nodes) {
size_t old_audio_devices_size = audio_devices_.size();
+ bool output_devices_changed = HasDeviceChange(nodes, false);
+ bool input_devices_changed = HasDeviceChange(nodes, true);
audio_devices_.clear();
has_alternative_input_ = false;
has_alternative_output_ = false;
@@ -552,12 +572,14 @@
// If audio nodes change is caused by unplugging some non-active audio
// devices, the previously set active audio device will stay active.
// Otherwise, switch to a new active audio device according to their priority.
- if (!NonActiveDeviceUnplugged(old_audio_devices_size,
+ if (input_devices_changed &&
+ !NonActiveDeviceUnplugged(old_audio_devices_size,
audio_devices_.size(),
active_input_node_id_) &&
!input_devices_pq_.empty())
SwitchToDevice(input_devices_pq_.top());
- if (!NonActiveDeviceUnplugged(old_audio_devices_size,
+ if (output_devices_changed &&
+ !NonActiveDeviceUnplugged(old_audio_devices_size,
audio_devices_.size(),
active_output_node_id_) &&
!output_devices_pq_.empty()) {
diff --git a/chromeos/audio/cras_audio_handler.h b/chromeos/audio/cras_audio_handler.h
index b95f123..e5e9f66 100644
--- a/chromeos/audio/cras_audio_handler.h
+++ b/chromeos/audio/cras_audio_handler.h
@@ -230,6 +230,10 @@
size_t new_device_size,
uint64 current_active_node);
+ // Returns true if there is any device change for for input or output,
+ // specified by |is_input|.
+ bool HasDeviceChange(const AudioNodeList& new_nodes, bool is_input);
+
// Handles dbus callback for GetNodes.
void HandleGetNodes(const chromeos::AudioNodeList& node_list, bool success);
diff --git a/chromeos/audio/cras_audio_handler_unittest.cc b/chromeos/audio/cras_audio_handler_unittest.cc
index 48a1200..267296f 100644
--- a/chromeos/audio/cras_audio_handler_unittest.cc
+++ b/chromeos/audio/cras_audio_handler_unittest.cc
@@ -948,7 +948,7 @@
EXPECT_EQ(init_nodes_size, audio_devices.size());
EXPECT_EQ(0, test_observer_->audio_nodes_changed_count());
- // Verify the internal mic is selected as the active output.
+ // Verify the internal mic is selected as the active input.
EXPECT_EQ(0, test_observer_->active_input_node_changed_count());
EXPECT_EQ(kInternalMic.id, cras_audio_handler_->GetActiveInputNode());
EXPECT_FALSE(cras_audio_handler_->has_alternative_input());
@@ -1006,6 +1006,65 @@
EXPECT_FALSE(cras_audio_handler_->has_alternative_input());
}
+TEST_F(CrasAudioHandlerTest, PlugUSBMicNotAffectActiveOutput) {
+ // Set up initial audio devices.
+ AudioNodeList audio_nodes;
+ audio_nodes.push_back(kInternalSpeaker);
+ audio_nodes.push_back(kHeadphone);
+ audio_nodes.push_back(kInternalMic);
+ SetUpCrasAudioHandler(audio_nodes);
+ const size_t init_nodes_size = audio_nodes.size();
+
+ // Verify the audio devices size.
+ EXPECT_EQ(0, test_observer_->audio_nodes_changed_count());
+ AudioDeviceList audio_devices;
+ cras_audio_handler_->GetAudioDevices(&audio_devices);
+ EXPECT_EQ(init_nodes_size, audio_devices.size());
+
+ // Verify the internal mic is selected as the active input.
+ EXPECT_EQ(0, test_observer_->active_input_node_changed_count());
+ EXPECT_EQ(kInternalMicId, cras_audio_handler_->GetActiveInputNode());
+ EXPECT_FALSE(cras_audio_handler_->has_alternative_input());
+
+ // Verify the headphone is selected as the active output.
+ EXPECT_EQ(0, test_observer_->active_output_node_changed_count());
+ EXPECT_EQ(kHeadphoneId, cras_audio_handler_->GetActiveOutputNode());
+ EXPECT_TRUE(cras_audio_handler_->has_alternative_output());
+
+ // Switch the active output to internal speaker.
+ AudioDevice internal_speaker(kInternalSpeaker);
+ cras_audio_handler_->SwitchToDevice(internal_speaker);
+
+ // Verify the active output is switched to internal speaker, and the
+ // ActiveOutputNodeChanged event is fired.
+ EXPECT_EQ(1, test_observer_->active_output_node_changed_count());
+ AudioDevice active_output;
+ EXPECT_TRUE(cras_audio_handler_->GetActiveOutputDevice(&active_output));
+ EXPECT_EQ(kInternalSpeaker.id, active_output.id);
+ EXPECT_EQ(kInternalSpeaker.id, cras_audio_handler_->GetActiveOutputNode());
+
+ // Plug the USB Mic.
+ audio_nodes.push_back(kUSBMic);
+ ChangeAudioNodes(audio_nodes);
+
+ // Verify the AudioNodesChanged event is fired, one new device is added.
+ EXPECT_EQ(1, test_observer_->audio_nodes_changed_count());
+ cras_audio_handler_->GetAudioDevices(&audio_devices);
+ EXPECT_EQ(init_nodes_size + 1, audio_devices.size());
+
+ // Verify the active input device is switched to USB mic, and
+ // and ActiveInputChanged event is fired.
+ EXPECT_EQ(1, test_observer_->active_input_node_changed_count());
+ EXPECT_EQ(kUSBMic.id, cras_audio_handler_->GetActiveInputNode());
+ EXPECT_TRUE(cras_audio_handler_->has_alternative_input());
+
+ // Verify the active output device is not changed.
+ EXPECT_EQ(1, test_observer_->active_output_node_changed_count());
+ EXPECT_TRUE(cras_audio_handler_->GetActiveOutputDevice(&active_output));
+ EXPECT_EQ(kInternalSpeaker.id, active_output.id);
+ EXPECT_EQ(kInternalSpeaker.id, cras_audio_handler_->GetActiveOutputNode());
+}
+
TEST_F(CrasAudioHandlerTest, SetOutputMute) {
AudioNodeList audio_nodes;
audio_nodes.push_back(kInternalSpeaker);
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc
index 06c94cc..5f1ec69 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -347,7 +347,8 @@
pending_lock_request_(false),
embedder_visible_(true),
next_permission_request_id_(browser_plugin::kInvalidPermissionRequestID),
- has_render_view_(has_render_view) {
+ has_render_view_(has_render_view),
+ is_in_destruction_(false) {
DCHECK(web_contents);
web_contents->SetDelegate(this);
if (opener)
@@ -421,6 +422,7 @@
}
void BrowserPluginGuest::Destroy() {
+ is_in_destruction_ = true;
if (!attached() && opener())
opener()->pending_new_windows_.erase(this);
DestroyUnattachedWindows();
diff --git a/content/browser/browser_plugin/browser_plugin_guest.h b/content/browser/browser_plugin/browser_plugin_guest.h
index 2044e49..6098cac 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/content/browser/browser_plugin/browser_plugin_guest.h
@@ -136,6 +136,7 @@
bool focused() const { return focused_; }
bool visible() const { return guest_visible_; }
void clear_damage_buffer() { damage_buffer_.reset(); }
+ bool is_in_destruction() { return is_in_destruction_; }
BrowserPluginGuest* opener() const { return opener_.get(); }
@@ -515,6 +516,8 @@
// this guest is attached.
bool has_render_view_;
+ bool is_in_destruction_;
+
// This is a queue of messages that are destined to be sent to the embedder
// once the guest is attached to a particular embedder.
std::queue<IPC::Message*> pending_messages_;
diff --git a/content/browser/renderer_host/render_widget_host_view_guest.cc b/content/browser/renderer_host/render_widget_host_view_guest.cc
index 097468f..b49ca41 100644
--- a/content/browser/renderer_host/render_widget_host_view_guest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_guest.cc
@@ -67,14 +67,22 @@
}
void RenderWidgetHostViewGuest::WasShown() {
- if (!is_hidden_)
+ // If the WebContents associated with us showed an interstitial page in the
+ // beginning, the teardown path might call WasShown() while |host_| is in
+ // the process of destruction. Avoid calling WasShown below in this case.
+ // TODO(lazyboy): We shouldn't be showing interstitial pages in guests in the
+ // first place: http://crbug.com/273089.
+ //
+ // |guest_| is NULL during test.
+ if (!is_hidden_ || (guest_ && guest_->is_in_destruction()))
return;
is_hidden_ = false;
host_->WasShown();
}
void RenderWidgetHostViewGuest::WasHidden() {
- if (is_hidden_)
+ // |guest_| is NULL during test.
+ if (is_hidden_ || (guest_ && guest_->is_in_destruction()))
return;
is_hidden_ = true;
host_->WasHidden();
diff --git a/content/browser/web_contents/touch_editable_impl_aura.cc b/content/browser/web_contents/touch_editable_impl_aura.cc
index fb430d0..d38f5f5 100644
--- a/content/browser/web_contents/touch_editable_impl_aura.cc
+++ b/content/browser/web_contents/touch_editable_impl_aura.cc
@@ -53,7 +53,7 @@
// there is non-zero selection on the page. And the current event is a
// gesture event (we dont want to show handles if the user is selecting
// using mouse or keyboard).
- if (selection_gesture_in_process_ &&
+ if (selection_gesture_in_process_ && !scroll_in_progress_ &&
selection_anchor_rect_ != selection_focus_rect_)
StartTouchEditing();
@@ -66,6 +66,29 @@
}
}
+void TouchEditableImplAura::OverscrollStarted() {
+ overscroll_in_progress_ = true;
+}
+
+void TouchEditableImplAura::OverscrollCompleted() {
+ // We might receive multiple OverscrollStarted() and OverscrollCompleted()
+ // during the same scroll session (for example, when the scroll direction
+ // changes). We want to show the handles only when:
+ // 1. Overscroll has completed
+ // 2. Scrolling session is over, i.e. we have received ET_GESTURE_SCROLL_END.
+ // 3. If we had hidden the handles when scrolling started
+ // 4. If there is still a need to show handles (there is a non-empty selection
+ // or non-NONE |text_input_type_|)
+ if (overscroll_in_progress_ && !scroll_in_progress_ &&
+ handles_hidden_due_to_scroll_ &&
+ (selection_anchor_rect_ != selection_focus_rect_ ||
+ text_input_type_ != ui::TEXT_INPUT_TYPE_NONE)) {
+ StartTouchEditing();
+ UpdateEditingController();
+ }
+ overscroll_in_progress_ = false;
+}
+
////////////////////////////////////////////////////////////////////////////////
// TouchEditableImplAura, RenderWidgetHostViewAura::TouchEditingClient
// implementation:
@@ -145,18 +168,24 @@
// when scrolling ends. So we set |handles_hidden_due_to_scroll_| so that
// we can re-start touch editing when we call |UpdateEditingController()|
// on scroll end gesture.
+ scroll_in_progress_ = true;
handles_hidden_due_to_scroll_ = false;
if (touch_selection_controller_)
handles_hidden_due_to_scroll_ = true;
EndTouchEditing();
break;
case ui::ET_GESTURE_SCROLL_END:
- if (handles_hidden_due_to_scroll_ &&
+ // Scroll has ended, but we might still be in overscroll animation.
+ if (handles_hidden_due_to_scroll_ && !overscroll_in_progress_ &&
(selection_anchor_rect_ != selection_focus_rect_ ||
text_input_type_ != ui::TEXT_INPUT_TYPE_NONE)) {
StartTouchEditing();
UpdateEditingController();
}
+ // fall through to reset |scroll_in_progress_|.
+ case ui::ET_SCROLL_FLING_START:
+ selection_gesture_in_process_ = false;
+ scroll_in_progress_ = false;
break;
default:
break;
@@ -330,6 +359,8 @@
rwhva_(NULL),
selection_gesture_in_process_(false),
handles_hidden_due_to_scroll_(false),
+ scroll_in_progress_(false),
+ overscroll_in_progress_(false),
is_tap_on_focused_textfield_(false) {
}
@@ -338,7 +369,11 @@
rwhva_->set_touch_editing_client(NULL);
rwhva_ = NULL;
}
+ text_input_type_ = ui::TEXT_INPUT_TYPE_NONE;
touch_selection_controller_.reset();
+ handles_hidden_due_to_scroll_ = false;
+ scroll_in_progress_ = false;
+ overscroll_in_progress_ = false;
}
} // namespace content
diff --git a/content/browser/web_contents/touch_editable_impl_aura.h b/content/browser/web_contents/touch_editable_impl_aura.h
index c31d86a..7f1ea84 100644
--- a/content/browser/web_contents/touch_editable_impl_aura.h
+++ b/content/browser/web_contents/touch_editable_impl_aura.h
@@ -37,6 +37,9 @@
// depending on the current selection and cursor state.
void UpdateEditingController();
+ void OverscrollStarted();
+ void OverscrollCompleted();
+
// Overridden from RenderWidgetHostViewAura::TouchEditingClient.
virtual void StartTouchEditing() OVERRIDE;
virtual void EndTouchEditing() OVERRIDE;
@@ -87,8 +90,16 @@
// change in selection (long press, double tap or triple tap).
bool selection_gesture_in_process_;
+ // Set to true if handles are hidden when user is scrolling. Used to determine
+ // whether to re-show handles after a scrolling session.
bool handles_hidden_due_to_scroll_;
+ // Keeps track of when the user is scrolling.
+ bool scroll_in_progress_;
+
+ // Set to true when the page starts an overscroll.
+ bool overscroll_in_progress_;
+
// Used to track if the current tap gesture is on a focused textfield.
bool is_tap_on_focused_textfield_;
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index 043efca..013edc7 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -1362,6 +1362,9 @@
// Reset any in-progress overscroll animation first.
ResetOverscrollTransform();
+ if (new_mode != OVERSCROLL_NONE && touch_editable_)
+ touch_editable_->OverscrollStarted();
+
if (new_mode == OVERSCROLL_NONE ||
!GetContentNativeView() ||
((new_mode == OVERSCROLL_EAST || new_mode == OVERSCROLL_WEST) &&
@@ -1402,6 +1405,9 @@
completed_overscroll_gesture_)) {
PrepareOverscrollNavigationOverlay();
web_contents_->GetController().GoBack();
+ } else {
+ if (touch_editable_)
+ touch_editable_->OverscrollCompleted();
}
aura::Window* content = GetContentNativeView();
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc
index 6810002..964206d 100644
--- a/content/public/browser/web_contents_delegate.cc
+++ b/content/public/browser/web_contents_delegate.cc
@@ -149,6 +149,13 @@
return NULL;
}
+void WebContentsDelegate::RequestMediaAccessPermission(
+ WebContents* web_contents,
+ const MediaStreamRequest& request,
+ const MediaResponseCallback& callback) {
+ callback.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>());
+}
+
bool WebContentsDelegate::RequestPpapiBrokerPermission(
WebContents* web_contents,
const GURL& url,
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
index 23d2336..aa1bb4e 100644
--- a/content/public/browser/web_contents_delegate.h
+++ b/content/public/browser/web_contents_delegate.h
@@ -424,7 +424,7 @@
virtual void RequestMediaAccessPermission(
WebContents* web_contents,
const MediaStreamRequest& request,
- const MediaResponseCallback& callback) {}
+ const MediaResponseCallback& callback);
// Requests permission to access the PPAPI broker. The delegate should return
// true and call the passed in |callback| with the result, or return false
diff --git a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
index ed5d947..a34b0ab 100644
--- a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
+++ b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
@@ -29,6 +29,7 @@
// Error code for MediaCodecBridge. Keep this value in sync with
// INFO_MEDIA_CODEC_ERROR in media_codec_bridge.h.
+ private static final int MEDIA_CODEC_OK = 0;
private static final int MEDIA_CODEC_ERROR = -1000;
// After a flush(), dequeueOutputBuffer() can often produce empty presentation timestamps
@@ -115,12 +116,18 @@
}
@CalledByNative
- private void flush() {
- mMediaCodec.flush();
- mFlushed = true;
- if (mAudioTrack != null) {
- mAudioTrack.flush();
+ private int flush() {
+ try {
+ mFlushed = true;
+ if (mAudioTrack != null) {
+ mAudioTrack.flush();
+ }
+ mMediaCodec.flush();
+ } catch(IllegalStateException e) {
+ Log.e(TAG, "Failed to flush MediaCodec " + e.toString());
+ return MEDIA_CODEC_ERROR;
}
+ return MEDIA_CODEC_OK;
}
@CalledByNative
diff --git a/media/base/android/media_codec_bridge.cc b/media/base/android/media_codec_bridge.cc
index ab54936..67ae335 100644
--- a/media/base/android/media_codec_bridge.cc
+++ b/media/base/android/media_codec_bridge.cc
@@ -94,9 +94,9 @@
GetOutputBuffers();
}
-void MediaCodecBridge::Reset() {
+int MediaCodecBridge::Reset() {
JNIEnv* env = AttachCurrentThread();
- Java_MediaCodecBridge_flush(env, j_media_codec_.obj());
+ return Java_MediaCodecBridge_flush(env, j_media_codec_.obj());
}
void MediaCodecBridge::Stop() {
diff --git a/media/base/android/media_codec_bridge.h b/media/base/android/media_codec_bridge.h
index 3469b18..a0edcb9 100644
--- a/media/base/android/media_codec_bridge.h
+++ b/media/base/android/media_codec_bridge.h
@@ -45,7 +45,9 @@
// DequeueInputBuffer() and DequeueOutputBuffer() become invalid.
// Please note that this clears all the inputs in the media codec. In other
// words, there will be no outputs until new input is provided.
- void Reset();
+ // Returns MEDIA_CODEC_ERROR if an unexpected error happens, or Media_CODEC_OK
+ // otherwise.
+ int Reset();
// Finishes the decode/encode session. The instance remains active
// and ready to be StartAudio/Video()ed again. HOWEVER, due to the buggy
diff --git a/media/base/android/media_source_player.cc b/media/base/android/media_source_player.cc
index 979d1cc..3af8a2b 100644
--- a/media/base/android/media_source_player.cc
+++ b/media/base/android/media_source_player.cc
@@ -161,7 +161,12 @@
if (needs_flush) {
DVLOG(1) << "DecodeInternal needs flush.";
input_eos_encountered_ = false;
- media_codec_bridge_->Reset();
+ int reset_status = media_codec_bridge_->Reset();
+ if (0 != reset_status) {
+ ui_loop_->PostTask(FROM_HERE, base::Bind(
+ callback, DECODE_FAILED, start_presentation_timestamp, 0));
+ return;
+ }
}
DecodeStatus decode_status = DECODE_INPUT_END_OF_STREAM;
diff --git a/sync/internal_api/public/engine/model_safe_worker.cc b/sync/internal_api/public/engine/model_safe_worker.cc
index 7179ed5..5c91715 100644
--- a/sync/internal_api/public/engine/model_safe_worker.cc
+++ b/sync/internal_api/public/engine/model_safe_worker.cc
@@ -134,11 +134,17 @@
<< " worker stops on destruction of its working thread.";
}
+ {
+ base::AutoLock l(working_loop_lock_);
+ working_loop_ = NULL;
+ }
+
if (observer_)
observer_->OnWorkerLoopDestroyed(GetModelSafeGroup());
}
void ModelSafeWorker::SetWorkingLoopToCurrent() {
+ base::AutoLock l(working_loop_lock_);
DCHECK(!working_loop_);
working_loop_ = base::MessageLoop::current();
working_loop_set_wait_.Signal();
@@ -150,19 +156,29 @@
// loop.
working_loop_set_wait_.Wait();
- // Should be called on sync loop.
- DCHECK_NE(base::MessageLoop::current(), working_loop_);
- DCHECK(working_loop_);
- working_loop_->PostTask(
- FROM_HERE,
- base::Bind(&ModelSafeWorker::UnregisterForLoopDestructionAsync,
- this, unregister_done_callback));
+ {
+ base::AutoLock l(working_loop_lock_);
+ if (working_loop_ != NULL) {
+ // Should be called on sync loop.
+ DCHECK_NE(base::MessageLoop::current(), working_loop_);
+ working_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&ModelSafeWorker::UnregisterForLoopDestructionAsync,
+ this, unregister_done_callback));
+ }
+ }
}
void ModelSafeWorker::UnregisterForLoopDestructionAsync(
base::Callback<void(ModelSafeGroup)> unregister_done_callback) {
+ {
+ base::AutoLock l(working_loop_lock_);
+ if (!working_loop_)
+ return;
+ DCHECK_EQ(base::MessageLoop::current(), working_loop_);
+ }
+
DCHECK(stopped_);
- DCHECK_EQ(base::MessageLoop::current(), working_loop_);
base::MessageLoop::current()->RemoveDestructionObserver(this);
unregister_done_callback.Run(GetModelSafeGroup());
}
diff --git a/sync/internal_api/public/engine/model_safe_worker.h b/sync/internal_api/public/engine/model_safe_worker.h
index f6b7ea6..0f41594 100644
--- a/sync/internal_api/public/engine/model_safe_worker.h
+++ b/sync/internal_api/public/engine/model_safe_worker.h
@@ -132,6 +132,7 @@
// Remember working loop for posting task to unregister destruction
// observation from sync thread when shutting down sync.
+ base::Lock working_loop_lock_;
base::MessageLoop* working_loop_;
base::WaitableEvent working_loop_set_wait_;
};
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc
index 4c10788..34f4848 100644
--- a/ui/views/controls/combobox/combobox.cc
+++ b/ui/views/controls/combobox/combobox.cc
@@ -14,6 +14,7 @@
#include "ui/views/controls/combobox/combobox_listener.h"
#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/controls/prefix_selector.h"
+#include "ui/views/ime/input_method.h"
#include "ui/views/widget/widget.h"
namespace views {
@@ -140,6 +141,7 @@
}
void Combobox::OnFocus() {
+ GetInputMethod()->OnFocus();
// Forward the focus to the wrapper.
if (native_wrapper_) {
native_wrapper_->SetFocus();
@@ -151,6 +153,7 @@
}
void Combobox::OnBlur() {
+ GetInputMethod()->OnBlur();
if (selector_)
selector_->OnViewBlur();
if (native_wrapper_)
diff --git a/ui/views/controls/tree/tree_view.cc b/ui/views/controls/tree/tree_view.cc
index 1d550a2..0157902 100644
--- a/ui/views/controls/tree/tree_view.cc
+++ b/ui/views/controls/tree/tree_view.cc
@@ -598,6 +598,7 @@
}
void TreeView::OnFocus() {
+ GetInputMethod()->OnFocus();
View::OnFocus();
SchedulePaintForNode(selected_node_);
@@ -607,6 +608,7 @@
}
void TreeView::OnBlur() {
+ GetInputMethod()->OnBlur();
SchedulePaintForNode(selected_node_);
if (selector_)
selector_->OnViewBlur();
diff --git a/webkit/renderer/webpreferences_renderer.cc b/webkit/renderer/webpreferences_renderer.cc
index 0b07385..fd057c9 100644
--- a/webkit/renderer/webpreferences_renderer.cc
+++ b/webkit/renderer/webpreferences_renderer.cc
@@ -331,6 +331,8 @@
ASCIIToUTF16(prefs.default_video_poster_url.spec()));
settings->setSupportDeprecatedTargetDensityDPI(
prefs.support_deprecated_target_density_dpi);
+ settings->setUseLegacyBackgroundSizeShorthandBehavior(
+ prefs.use_legacy_background_size_shorthand_behavior);
settings->setUseWideViewport(prefs.use_wide_viewport);
#endif