diff options
author | Kristian Monsen <kristianm@google.com> | 2011-07-26 12:15:06 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2011-07-26 20:41:55 +0100 |
commit | 3dff810fe0cc4962a5fa554318e9bf8bc45f5274 (patch) | |
tree | a9fffa9ab7d061ab00538c18beb77403547378d0 /chrome | |
parent | 67d814a5d5c8d7df4740db4d2d74d0a41f94bece (diff) | |
download | external_chromium-3dff810fe0cc4962a5fa554318e9bf8bc45f5274.zip external_chromium-3dff810fe0cc4962a5fa554318e9bf8bc45f5274.tar.gz external_chromium-3dff810fe0cc4962a5fa554318e9bf8bc45f5274.tar.bz2 |
Merge Chromium at 12.0.742.130: Initial merge by git
Fix for bug 5080607 Update external/chromium to latest revision
Change-Id: I5c98b0d2845fccca4cbcdcea506e8f1759ba5416
Diffstat (limited to 'chrome')
33 files changed, 754 insertions, 295 deletions
diff --git a/chrome/browser/chrome_browser_application_mac.mm b/chrome/browser/chrome_browser_application_mac.mm index 7ba8cda..601d9c4 100644 --- a/chrome/browser/chrome_browser_application_mac.mm +++ b/chrome/browser/chrome_browser_application_mac.mm @@ -7,6 +7,7 @@ #import "base/logging.h" #import "base/metrics/histogram.h" #import "base/memory/scoped_nsobject.h" +#include "base/sys_info.h" #import "base/sys_string_conversions.h" #import "chrome/app/breakpad_mac.h" #import "chrome/browser/app_controller_mac.h" @@ -194,9 +195,15 @@ BOOL SwizzleNSExceptionInit() { @implementation BrowserCrApplication + (void)initialize { - // Turn all deallocated Objective-C objects into zombies, keeping - // the most recent 10,000 of them on the treadmill. - ObjcEvilDoers::ZombieEnable(YES, 10000); + // Whitelist releases that are compatible with objc zombies. + int32 major_version = 0, minor_version = 0, bugfix_version = 0; + base::SysInfo::OperatingSystemVersionNumbers( + &major_version, &minor_version, &bugfix_version); + if (major_version == 10 && (minor_version == 5 || minor_version == 6)) { + // Turn all deallocated Objective-C objects into zombies, keeping + // the most recent 10,000 of them on the treadmill. + ObjcEvilDoers::ZombieEnable(YES, 10000); + } } - init { diff --git a/chrome/browser/chromeos/cros/network_library.cc b/chrome/browser/chromeos/cros/network_library.cc index 31ebe0e..85e0f94 100644 --- a/chrome/browser/chromeos/cros/network_library.cc +++ b/chrome/browser/chromeos/cros/network_library.cc @@ -679,7 +679,7 @@ static ConnectionError ParseError(const std::string& error) { { kErrorAaaFailed, ERROR_AAA_FAILED }, }; static StringToEnum<ConnectionError> parser( - table, arraysize(table), ERROR_UNKNOWN); + table, arraysize(table), ERROR_NO_ERROR); return parser.Get(error); } @@ -1201,8 +1201,9 @@ std::string Network::GetStateString() const { std::string Network::GetErrorString() const { switch (error_) { - case ERROR_UNKNOWN: - return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN); + case ERROR_NO_ERROR: + // TODO(nkostylev): Introduce new error message "None" instead. + return std::string(); case ERROR_OUT_OF_RANGE: return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_OUT_OF_RANGE); case ERROR_PIN_MISSING: diff --git a/chrome/browser/chromeos/cros/network_library.h b/chrome/browser/chromeos/cros/network_library.h index 77d6c46..e485660 100644 --- a/chrome/browser/chromeos/cros/network_library.h +++ b/chrome/browser/chromeos/cros/network_library.h @@ -129,7 +129,7 @@ enum PinOperationError { // connection errors (see flimflam/include/service.h) enum ConnectionError { - ERROR_UNKNOWN = 0, + ERROR_NO_ERROR = 0, ERROR_OUT_OF_RANGE = 1, ERROR_PIN_MISSING = 2, ERROR_DHCP_FAILED = 3, @@ -329,7 +329,7 @@ class Network { protected: Network(const std::string& service_path, ConnectionType type) : state_(STATE_UNKNOWN), - error_(ERROR_UNKNOWN), + error_(ERROR_NO_ERROR), connectable_(true), is_active_(false), favorite_(false), diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc index 6b58f77..7f05eb3 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.cc +++ b/chrome/browser/chromeos/login/existing_user_controller.cc @@ -393,12 +393,13 @@ void ExistingUserController::OnPasswordChangeDetected( // Another attempt will be invoked after verification completion. return; } - // TODO(altimofeev): remove this constrain when full sync for the owner will - // be correctly handled. - bool full_sync_disabled = (UserCrosSettingsProvider::cached_owner() == - last_login_attempt_username_); - PasswordChangedView* view = new PasswordChangedView(this, full_sync_disabled); + // Passing 'false' here enables "full sync" mode in the dialog, + // which disables the requirement for the old owner password, + // allowing us to recover from a lost owner password/homedir. + // TODO(gspencer): We shouldn't have to erase stateful data when + // doing this. See http://crosbug.com/9115 http://crosbug.com/7792 + PasswordChangedView* view = new PasswordChangedView(this, false); views::Window* window = browser::CreateViewsWindow(GetNativeWindow(), gfx::Rect(), view); diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index 9cd4a4f..1e88799 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc @@ -496,11 +496,6 @@ void WizardController::OnEulaAccepted() { MarkEulaAccepted(); chromeos::MetricsCrosSettingsProvider::SetMetricsStatus( usage_statistics_reporting_); - if (chromeos::CrosLibrary::Get()->EnsureLoaded()) { - // TPM password could be seen on EULA screen, now it's safe to clear it. - chromeos::CrosLibrary::Get()-> - GetCryptohomeLibrary()->TpmClearStoredPassword(); - } InitiateOOBEUpdate(); } diff --git a/chrome/browser/download/download_extensions.cc b/chrome/browser/download/download_extensions.cc index b9cac1b..90f704a 100644 --- a/chrome/browser/download/download_extensions.cc +++ b/chrome/browser/download/download_extensions.cc @@ -105,6 +105,7 @@ static const struct Executables { { "drv", Dangerous }, { "exe", AllowOnUserGesture }, { "fxp", AllowOnUserGesture }, + { "grp", Dangerous }, { "hlp", AllowOnUserGesture }, { "hta", AllowOnUserGesture }, { "htt", AllowOnUserGesture }, diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc index 7155001..02e554a 100644 --- a/chrome/browser/download/download_manager.cc +++ b/chrome/browser/download/download_manager.cc @@ -539,7 +539,12 @@ void DownloadManager::OnResponseCompleted(int32 download_id, int os_error, const std::string& hash) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (os_error == 0) { + // ERR_CONNECTION_CLOSED is allowed since a number of servers in the wild + // advertise a larger Content-Length than the amount of bytes in the message + // body, and then close the connection. Other browsers - IE8, Firefox 4.0.1, + // and Safari 5.0.4 - treat the download as complete in this case, so we + // follow their lead. + if (os_error == 0 || os_error == net::ERR_CONNECTION_CLOSED) { OnAllDataSaved(download_id, size, hash); } else { OnDownloadError(download_id, size, os_error); diff --git a/chrome/browser/importer/firefox2_importer.cc b/chrome/browser/importer/firefox2_importer.cc index f0dbcfd..9b1b4f2 100644 --- a/chrome/browser/importer/firefox2_importer.cc +++ b/chrome/browser/importer/firefox2_importer.cc @@ -266,9 +266,11 @@ void Firefox2Importer::ImportBookmarksFile( entry.title = folder_title; if (import_to_bookmark_bar && toolbar_folder) { // Flatten the folder in toolbar. - entry.in_toolbar = true; - entry.path.assign(path.begin() + toolbar_folder, path.end()); - toolbar_bookmarks.push_back(entry); + if (toolbar_folder <= path.size()) { + entry.in_toolbar = true; + entry.path.assign(path.begin() + toolbar_folder, path.end()); + toolbar_bookmarks.push_back(entry); + } } else { // Insert the folder into the "Imported from Firefox" folder. entry.path.assign(path.begin(), path.end()); diff --git a/chrome/browser/password_manager/password_manager_unittest.cc b/chrome/browser/password_manager/password_manager_unittest.cc index 0db4973..a22d81b 100644 --- a/chrome/browser/password_manager/password_manager_unittest.cc +++ b/chrome/browser/password_manager/password_manager_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -38,11 +38,14 @@ class TestingProfileWithPasswordStore : public TestingProfile { public: explicit TestingProfileWithPasswordStore(PasswordStore* store) : store_(store) {} + virtual ~TestingProfileWithPasswordStore() { + store_->Shutdown(); + } virtual PasswordStore* GetPasswordStore(ServiceAccessType access) { return store_; } private: - PasswordStore* store_; + scoped_refptr<PasswordStore> store_; }; class MockPasswordStore : public PasswordStore { diff --git a/chrome/browser/password_manager/password_store.cc b/chrome/browser/password_manager/password_store.cc index 4d00b23..09ed969 100644 --- a/chrome/browser/password_manager/password_store.cc +++ b/chrome/browser/password_manager/password_store.cc @@ -34,6 +34,9 @@ bool PasswordStore::Init() { return true; } +void PasswordStore::Shutdown() { +} + void PasswordStore::AddLogin(const PasswordForm& form) { Task* task = NewRunnableMethod(this, &PasswordStore::AddLoginImpl, form); ScheduleTask( @@ -98,6 +101,7 @@ PasswordStore::GetLoginsRequest* PasswordStore::NewGetLoginsRequest( void PasswordStore::ScheduleTask(Task* task) { BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, task); } + void PasswordStore::ForwardLoginsResult(GetLoginsRequest* request) { request->ForwardResult(GetLoginsRequest::TupleType(request->handle(), request->value)); diff --git a/chrome/browser/password_manager/password_store.h b/chrome/browser/password_manager/password_store.h index 75a3e80..1e7f69d 100644 --- a/chrome/browser/password_manager/password_store.h +++ b/chrome/browser/password_manager/password_store.h @@ -74,6 +74,9 @@ class PasswordStore // Reimplement this to add custom initialization. Always call this too. virtual bool Init(); + // Invoked from the profiles destructor to shutdown the PasswordStore. + virtual void Shutdown(); + // Adds the given PasswordForm to the secure password store asynchronously. virtual void AddLogin(const webkit_glue::PasswordForm& form); diff --git a/chrome/browser/password_manager/password_store_default.cc b/chrome/browser/password_manager/password_store_default.cc index 2be5207..d99ba4a 100644 --- a/chrome/browser/password_manager/password_store_default.cc +++ b/chrome/browser/password_manager/password_store_default.cc @@ -4,7 +4,7 @@ #include "chrome/browser/password_manager/password_store_default.h" -#include <vector> +#include <set> #include "base/logging.h" #include "base/stl_util-inl.h" @@ -19,6 +19,85 @@ using webkit_glue::PasswordForm; +// MigrateHelper handles migration from WebDB to PasswordStore. It runs +// entirely on the UI thread and is owned by PasswordStoreDefault. +class PasswordStoreDefault::MigrateHelper : public WebDataServiceConsumer { + public: + MigrateHelper(Profile* profile, + WebDataService* web_data_service, + PasswordStore* password_store) + : profile_(profile), + web_data_service_(web_data_service), + password_store_(password_store) { + } + ~MigrateHelper(); + + void Init(); + + // WebDataServiceConsumer: + virtual void OnWebDataServiceRequestDone( + WebDataService::Handle handle, + const WDTypedResult *result) OVERRIDE; + + private: + typedef std::set<WebDataService::Handle> Handles; + + Profile* profile_; + + scoped_refptr<WebDataService> web_data_service_; + + // This creates a cycle between us and PasswordStore. The cycle is broken + // from PasswordStoreDefault::Shutdown, which deletes us. + scoped_refptr<PasswordStore> password_store_; + + // Set of handles from requesting data from the WebDB. + Handles handles_; + + DISALLOW_COPY_AND_ASSIGN(MigrateHelper); +}; + +PasswordStoreDefault::MigrateHelper::~MigrateHelper() { + for (Handles::const_iterator i = handles_.begin(); i != handles_.end(); ++i) + web_data_service_->CancelRequest(*i); + handles_.clear(); +} + +void PasswordStoreDefault::MigrateHelper::Init() { + handles_.insert(web_data_service_->GetAutofillableLogins(this)); + handles_.insert(web_data_service_->GetBlacklistLogins(this)); +} + +void PasswordStoreDefault::MigrateHelper::OnWebDataServiceRequestDone( + WebDataService::Handle handle, + const WDTypedResult* result) { + typedef std::vector<const PasswordForm*> PasswordForms; + + DCHECK(handles_.end() != handles_.find(handle)); + DCHECK(password_store_); + + handles_.erase(handle); + if (!result) + return; + + if (PASSWORD_RESULT != result->GetType()) { + NOTREACHED(); + return; + } + + const PasswordForms& forms = + static_cast<const WDResult<PasswordForms>*>(result)->GetValue(); + for (PasswordForms::const_iterator it = forms.begin(); + it != forms.end(); ++it) { + password_store_->AddLogin(**it); + web_data_service_->RemoveLogin(**it); + delete *it; + } + if (handles_.empty()) { + profile_->GetPrefs()->RegisterBooleanPref(prefs::kLoginDatabaseMigrated, + true); + } +} + PasswordStoreDefault::PasswordStoreDefault(LoginDatabase* login_db, Profile* profile, WebDataService* web_data_service) @@ -31,6 +110,13 @@ PasswordStoreDefault::PasswordStoreDefault(LoginDatabase* login_db, } PasswordStoreDefault::~PasswordStoreDefault() { + // MigrateHelper should always be NULL as Shutdown should be invoked before + // the destructor. + DCHECK(!migrate_helper_.get()); +} + +void PasswordStoreDefault::Shutdown() { + migrate_helper_.reset(); } void PasswordStoreDefault::ReportMetricsImpl() { @@ -125,36 +211,7 @@ void PasswordStoreDefault::MigrateIfNecessary() { PrefService* prefs = profile_->GetPrefs(); if (prefs->FindPreference(prefs::kLoginDatabaseMigrated)) return; - handles_.insert(web_data_service_->GetAutofillableLogins(this)); - handles_.insert(web_data_service_->GetBlacklistLogins(this)); -} - -typedef std::vector<const PasswordForm*> PasswordForms; - -void PasswordStoreDefault::OnWebDataServiceRequestDone( - WebDataService::Handle handle, - const WDTypedResult* result) { - DCHECK(handles_.end() != handles_.find(handle)); - - handles_.erase(handle); - if (!result) - return; - - if (PASSWORD_RESULT != result->GetType()) { - NOTREACHED(); - return; - } - - const PasswordForms& forms = - static_cast<const WDResult<PasswordForms>*>(result)->GetValue(); - for (PasswordForms::const_iterator it = forms.begin(); - it != forms.end(); ++it) { - AddLogin(**it); - web_data_service_->RemoveLogin(**it); - delete *it; - } - if (handles_.empty()) { - profile_->GetPrefs()->RegisterBooleanPref(prefs::kLoginDatabaseMigrated, - true); - } + DCHECK(!migrate_helper_.get()); + migrate_helper_.reset(new MigrateHelper(profile_, web_data_service_, this)); + migrate_helper_->Init(); } diff --git a/chrome/browser/password_manager/password_store_default.h b/chrome/browser/password_manager/password_store_default.h index c819b14..4c6163a 100644 --- a/chrome/browser/password_manager/password_store_default.h +++ b/chrome/browser/password_manager/password_store_default.h @@ -6,21 +6,19 @@ #define CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_STORE_DEFAULT_H_ #pragma once -#include <set> #include <vector> #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "chrome/browser/password_manager/login_database.h" #include "chrome/browser/password_manager/password_store.h" -#include "chrome/browser/webdata/web_data_service.h" class Profile; +class WebDataService; // Simple password store implementation that delegates everything to // the LoginDatabase. -class PasswordStoreDefault : public PasswordStore, - public WebDataServiceConsumer { +class PasswordStoreDefault : public PasswordStore { public: // Takes ownership of |login_db|. PasswordStoreDefault(LoginDatabase* login_db, @@ -31,6 +29,7 @@ class PasswordStoreDefault : public PasswordStore, virtual ~PasswordStoreDefault(); // Implements PasswordStore interface. + virtual void Shutdown(); virtual void ReportMetricsImpl(); virtual void AddLoginImpl(const webkit_glue::PasswordForm& form); virtual void UpdateLoginImpl(const webkit_glue::PasswordForm& form); @@ -48,23 +47,21 @@ class PasswordStoreDefault : public PasswordStore, scoped_refptr<WebDataService> web_data_service_; - // Implements the WebDataService consumer interface. - virtual void OnWebDataServiceRequestDone(WebDataService::Handle handle, - const WDTypedResult *result); - protected: inline bool DeleteAndRecreateDatabaseFile() { return login_db_->DeleteAndRecreateDatabaseFile(); } private: + class MigrateHelper; + // Migrates logins from the WDS to the LoginDatabase. void MigrateIfNecessary(); scoped_ptr<LoginDatabase> login_db_; Profile* profile_; - std::set<WebDataService::Handle> handles_; + scoped_ptr<MigrateHelper> migrate_helper_; DISALLOW_COPY_AND_ASSIGN(PasswordStoreDefault); }; diff --git a/chrome/browser/password_manager/password_store_default_unittest.cc b/chrome/browser/password_manager/password_store_default_unittest.cc index 19b70a1..212de2f 100644 --- a/chrome/browser/password_manager/password_store_default_unittest.cc +++ b/chrome/browser/password_manager/password_store_default_unittest.cc @@ -285,7 +285,7 @@ TEST_F(PasswordStoreDefaultTest, Migration) { done.Wait(); // Initializing the PasswordStore should trigger a migration. - scoped_refptr<PasswordStoreDefault> store( + scoped_refptr<PasswordStore> store( new PasswordStoreDefault(login_db_.release(), profile_.get(), wds_.get())); store->Init(); @@ -364,6 +364,8 @@ TEST_F(PasswordStoreDefaultTest, Migration) { STLDeleteElements(&expected_autofillable); STLDeleteElements(&expected_blacklisted); + + store->Shutdown(); } TEST_F(PasswordStoreDefaultTest, MigrationAlreadyDone) { @@ -400,7 +402,7 @@ TEST_F(PasswordStoreDefaultTest, MigrationAlreadyDone) { true); // Initializing the PasswordStore shouldn't trigger a migration. - scoped_refptr<PasswordStoreDefault> store( + scoped_refptr<PasswordStore> store( new PasswordStoreDefault(login_db_.release(), profile_.get(), wds_.get())); store->Init(); @@ -421,6 +423,8 @@ TEST_F(PasswordStoreDefaultTest, MigrationAlreadyDone) { MessageLoop::current()->Run(); STLDeleteElements(&unexpected_autofillable); + + store->Shutdown(); } TEST_F(PasswordStoreDefaultTest, Notifications) { @@ -429,7 +433,7 @@ TEST_F(PasswordStoreDefaultTest, Notifications) { true); // Initializing the PasswordStore shouldn't trigger a migration. - scoped_refptr<PasswordStoreDefault> store( + scoped_refptr<PasswordStore> store( new PasswordStoreDefault(login_db_.release(), profile_.get(), wds_.get())); store->Init(); @@ -511,4 +515,6 @@ TEST_F(PasswordStoreDefaultTest, Notifications) { BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, new SignalingTask(&done)); done.Wait(); + + store->Shutdown(); } diff --git a/chrome/browser/password_manager/password_store_mac_unittest.cc b/chrome/browser/password_manager/password_store_mac_unittest.cc index 3deabb3..01a5b6f 100644 --- a/chrome/browser/password_manager/password_store_mac_unittest.cc +++ b/chrome/browser/password_manager/password_store_mac_unittest.cc @@ -913,6 +913,7 @@ class PasswordStoreMacTest : public testing::Test { } virtual void TearDown() { + store_->Shutdown(); MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask); MessageLoop::current()->Run(); } diff --git a/chrome/browser/password_manager/password_store_win.cc b/chrome/browser/password_manager/password_store_win.cc index 415fbc4..a1100fc 100644 --- a/chrome/browser/password_manager/password_store_win.cc +++ b/chrome/browser/password_manager/password_store_win.cc @@ -4,12 +4,15 @@ #include "chrome/browser/password_manager/password_store_win.h" +#include <map> + #include "base/logging.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "chrome/browser/password_manager/ie7_password.h" #include "chrome/browser/password_manager/password_manager.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/webdata/web_data_service.h" using webkit_glue::PasswordForm; @@ -36,100 +39,73 @@ class FormGetLoginsRequest : public PasswordStore::GetLoginsRequest { private: scoped_ptr<PasswordForm> form_; }; -} -PasswordStoreWin::PasswordStoreWin(LoginDatabase* login_database, - Profile* profile, - WebDataService* web_data_service) - : PasswordStoreDefault(login_database, profile, web_data_service) { -} - -PasswordStoreWin::~PasswordStoreWin() { - DCHECK(pending_requests_.empty() || - BrowserThread::CurrentlyOn(BrowserThread::DB)); +} // namespace - for (PendingRequestMap::const_iterator it = pending_requests_.begin(); - it != pending_requests_.end(); ++it) { - web_data_service_->CancelRequest(it->first); +// Handles requests to WebDataService. +class PasswordStoreWin::DBHandler : public WebDataServiceConsumer { + public: + DBHandler(WebDataService* web_data_service, + PasswordStoreWin* password_store) + : web_data_service_(web_data_service), + password_store_(password_store) { } -} -PasswordStore::GetLoginsRequest* PasswordStoreWin::NewGetLoginsRequest( - GetLoginsCallback* callback) { - return new FormGetLoginsRequest(callback); -} + ~DBHandler(); -void PasswordStoreWin::ForwardLoginsResult(GetLoginsRequest* request) { - if (static_cast<FormGetLoginsRequest*>(request)->IsLoginsRequest() && - request->value.empty()) { - IE7PasswordInfo info; - std::wstring url = ASCIIToWide( - static_cast<FormGetLoginsRequest*>(request)->form()->origin.spec()); - info.url_hash = ie7_password::GetUrlHash(url); - WebDataService::Handle handle = web_data_service_->GetIE7Login(info, - this); - TrackRequest(handle, request); - } else { - PasswordStore::ForwardLoginsResult(request); - } -} + // Requests the IE7 login for |url| and |request|. This is async. The request + // is processed when complete. + void GetIE7Login(const GURL& url, GetLoginsRequest* request); -void PasswordStoreWin::OnWebDataServiceRequestDone( - WebDataService::Handle handle, const WDTypedResult* result) { - if (!result) - return; // The WDS returns NULL if it is shutting down. + private: + // Holds requests associated with in-flight GetLogin queries. + typedef std::map<WebDataService::Handle, + scoped_refptr<GetLoginsRequest> > PendingRequestMap; - if (PASSWORD_IE7_RESULT == result->GetType()) { - scoped_refptr<GetLoginsRequest> request(TakeRequestWithHandle(handle)); + // Gets logins from IE7 if no others are found. Also copies them into + // Chrome's WebDatabase so we don't need to look next time. + PasswordForm* GetIE7Result(const WDTypedResult* result, + const PasswordForm& form); - // If the request was cancelled, we are done. - if (!request.get()) - return; + // WebDataServiceConsumer. + virtual void OnWebDataServiceRequestDone( + WebDataService::Handle handle, + const WDTypedResult* result) OVERRIDE; - // This is a response from WebDataService::GetIE7Login. - PasswordForm* form = static_cast<FormGetLoginsRequest*>( - request.get())->form(); - DCHECK(form); - PasswordForm* ie7_form = GetIE7Result(result, *form); + scoped_refptr<WebDataService> web_data_service_; - if (ie7_form) - request->value.push_back(ie7_form); + // This creates a cycle between us and PasswordStore. The cycle is broken + // from PasswordStoreWin::Shutdown, which deletes us. + scoped_refptr<PasswordStoreWin> password_store_; - PasswordStore::ForwardLoginsResult(request.get()); - } else { - PasswordStoreDefault::OnWebDataServiceRequestDone(handle, result); - } -} + // Holds requests associated with in-flight GetLogin queries. + PendingRequestMap pending_requests_; -void PasswordStoreWin::GetLoginsImpl(GetLoginsRequest* request, - const PasswordForm& form) { - static_cast<FormGetLoginsRequest*>(request)->SetLoginsRequestForm(form); + DISALLOW_COPY_AND_ASSIGN(DBHandler); +}; - PasswordStoreDefault::GetLoginsImpl(request, form); +PasswordStoreWin::DBHandler::~DBHandler() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); + for (PendingRequestMap::const_iterator i = pending_requests_.begin(); + i != pending_requests_.end(); ++i) { + web_data_service_->CancelRequest(i->first); + } } -void PasswordStoreWin::TrackRequest(WebDataService::Handle handle, - GetLoginsRequest* request) { +void PasswordStoreWin::DBHandler::GetIE7Login(const GURL& url, + GetLoginsRequest* request) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); - + IE7PasswordInfo info; + info.url_hash = ie7_password::GetUrlHash(UTF8ToWide(url.spec())); + WebDataService::Handle handle = web_data_service_->GetIE7Login(info, this); pending_requests_.insert(PendingRequestMap::value_type(handle, request)); } -PasswordStoreDefault::GetLoginsRequest* PasswordStoreWin::TakeRequestWithHandle( - WebDataService::Handle handle) { +PasswordForm* PasswordStoreWin::DBHandler::GetIE7Result( + const WDTypedResult *result, + const PasswordForm& form) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); - PendingRequestMap::iterator it(pending_requests_.find(handle)); - if (it == pending_requests_.end()) - return NULL; - - GetLoginsRequest* request = it->second; - pending_requests_.erase(it); - return request; -} - -PasswordForm* PasswordStoreWin::GetIE7Result(const WDTypedResult *result, - const PasswordForm& form) { const WDResult<IE7PasswordInfo>* r = static_cast<const WDResult<IE7PasswordInfo>*>(result); IE7PasswordInfo info = r->GetValue(); @@ -153,9 +129,82 @@ PasswordForm* PasswordStoreWin::GetIE7Result(const WDTypedResult *result, autofill->preferred = true; autofill->ssl_valid = form.origin.SchemeIsSecure(); autofill->date_created = info.date_created; - // Add this PasswordForm to the saved password table. - AddLogin(*autofill); + // Add this PasswordForm to the saved password table. We're on the DB thread + // already, so we use AddLoginImpl. + password_store_->AddLoginImpl(*autofill); return autofill; } return NULL; } + +void PasswordStoreWin::DBHandler::OnWebDataServiceRequestDone( + WebDataService::Handle handle, + const WDTypedResult* result) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); + + PendingRequestMap::iterator i(pending_requests_.find(handle)); + DCHECK(i != pending_requests_.end()); + scoped_refptr<GetLoginsRequest> request(i->second); + pending_requests_.erase(i); + + if (!result) + return; // The WDS returns NULL if it is shutting down. + + DCHECK_EQ(PASSWORD_IE7_RESULT, result->GetType()); + PasswordForm* form = + static_cast<FormGetLoginsRequest*>(request.get())->form(); + DCHECK(form); + PasswordForm* ie7_form = GetIE7Result(result, *form); + + if (ie7_form) + request->value.push_back(ie7_form); + + request->ForwardResult(GetLoginsRequest::TupleType(request->handle(), + request->value)); +} + +PasswordStoreWin::PasswordStoreWin(LoginDatabase* login_database, + Profile* profile, + WebDataService* web_data_service) + : PasswordStoreDefault(login_database, profile, web_data_service) { + db_handler_.reset(new DBHandler(web_data_service, this)); +} + +PasswordStoreWin::~PasswordStoreWin() { +} + +void PasswordStoreWin::ShutdownOnDBThread() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); + db_handler_.reset(); +} + +PasswordStore::GetLoginsRequest* PasswordStoreWin::NewGetLoginsRequest( + GetLoginsCallback* callback) { + return new FormGetLoginsRequest(callback); +} + +void PasswordStoreWin::Shutdown() { + BrowserThread::PostTask( + BrowserThread::DB, FROM_HERE, + NewRunnableMethod(this, &PasswordStoreWin::ShutdownOnDBThread)); + PasswordStoreDefault::Shutdown(); +} + +void PasswordStoreWin::ForwardLoginsResult(GetLoginsRequest* request) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); + if (static_cast<FormGetLoginsRequest*>(request)->IsLoginsRequest() && + request->value.empty() && db_handler_.get()) { + db_handler_->GetIE7Login( + static_cast<FormGetLoginsRequest*>(request)->form()->origin, + request); + } else { + PasswordStore::ForwardLoginsResult(request); + } +} + +void PasswordStoreWin::GetLoginsImpl(GetLoginsRequest* request, + const PasswordForm& form) { + static_cast<FormGetLoginsRequest*>(request)->SetLoginsRequestForm(form); + + PasswordStoreDefault::GetLoginsImpl(request, form); +} diff --git a/chrome/browser/password_manager/password_store_win.h b/chrome/browser/password_manager/password_store_win.h index 2cf238d..f08bbcd 100644 --- a/chrome/browser/password_manager/password_store_win.h +++ b/chrome/browser/password_manager/password_store_win.h @@ -6,8 +6,7 @@ #define CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_STORE_WIN_H_ #pragma once -#include <map> - +#include "base/scoped_ptr.h" #include "chrome/browser/password_manager/password_store_default.h" class LoginDatabase; @@ -28,38 +27,25 @@ class PasswordStoreWin : public PasswordStoreDefault { WebDataService* web_data_service); private: + class DBHandler; + virtual ~PasswordStoreWin(); + // Invoked from Shutdown, but run on the DB thread. + void ShutdownOnDBThread(); + virtual GetLoginsRequest* NewGetLoginsRequest( GetLoginsCallback* callback) OVERRIDE; // See PasswordStoreDefault. + virtual void Shutdown() OVERRIDE; virtual void ForwardLoginsResult(GetLoginsRequest* request) OVERRIDE; - virtual void OnWebDataServiceRequestDone( - WebDataService::Handle h, const WDTypedResult* result) OVERRIDE; // Overridden so that we can save the form for later use. virtual void GetLoginsImpl(GetLoginsRequest* request, const webkit_glue::PasswordForm& form) OVERRIDE; - // Takes ownership of |request| and tracks it under |handle|. - void TrackRequest(WebDataService::Handle handle, GetLoginsRequest* request); - - // Finds the GetLoginsRequest associated with the in-flight WebDataService - // request identified by |handle|, removes it from the tracking list, and - // returns it. Ownership of the GetLoginsRequest passes to the caller. - // Returns NULL if the request has been cancelled. - GetLoginsRequest* TakeRequestWithHandle(WebDataService::Handle handle); - - // Gets logins from IE7 if no others are found. Also copies them into - // Chrome's WebDatabase so we don't need to look next time. - webkit_glue::PasswordForm* GetIE7Result( - const WDTypedResult* result, - const webkit_glue::PasswordForm& form); - - // Holds requests associated with in-flight GetLogin queries. - typedef std::map<WebDataService::Handle, GetLoginsRequest*> PendingRequestMap; - PendingRequestMap pending_requests_; + scoped_ptr<DBHandler> db_handler_; DISALLOW_COPY_AND_ASSIGN(PasswordStoreWin); }; diff --git a/chrome/browser/password_manager/password_store_win_unittest.cc b/chrome/browser/password_manager/password_store_win_unittest.cc index 98ad2be..6477b12 100644 --- a/chrome/browser/password_manager/password_store_win_unittest.cc +++ b/chrome/browser/password_manager/password_store_win_unittest.cc @@ -18,6 +18,7 @@ #include "chrome/browser/password_manager/password_store_win.h" #include "chrome/browser/password_manager/ie7_password.h" #include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/webdata/web_data_service.h" #include "chrome/common/pref_names.h" #include "chrome/test/signaling_task.h" #include "chrome/test/testing_profile.h" @@ -171,7 +172,7 @@ TEST_F(PasswordStoreWinTest, DISABLED_ConvertIE7Login) { true); // Initializing the PasswordStore shouldn't trigger a migration. - scoped_refptr<PasswordStoreWin> store( + scoped_refptr<PasswordStore> store( new PasswordStoreWin(login_db_.release(), profile_.get(), wds_.get())); EXPECT_TRUE(store->Init()); @@ -220,6 +221,8 @@ TEST_F(PasswordStoreWinTest, DISABLED_ConvertIE7Login) { MessageLoop::current()->Run(); STLDeleteElements(&forms); + + store->Shutdown(); } TEST_F(PasswordStoreWinTest, OutstandingWDSQueries) { @@ -228,7 +231,7 @@ TEST_F(PasswordStoreWinTest, OutstandingWDSQueries) { true); // Initializing the PasswordStore shouldn't trigger a migration. - scoped_refptr<PasswordStoreWin> store( + scoped_refptr<PasswordStore> store( new PasswordStoreWin(login_db_.release(), profile_.get(), wds_.get())); EXPECT_TRUE(store->Init()); @@ -250,6 +253,7 @@ TEST_F(PasswordStoreWinTest, OutstandingWDSQueries) { store->GetLogins(*form, &consumer); // Release the PSW and the WDS before the query can return. + store->Shutdown(); store = NULL; wds_->Shutdown(); wds_ = NULL; @@ -277,7 +281,7 @@ TEST_F(PasswordStoreWinTest, DISABLED_MultipleWDSQueriesOnDifferentThreads) { true); // Initializing the PasswordStore shouldn't trigger a migration. - scoped_refptr<PasswordStoreWin> store( + scoped_refptr<PasswordStore> store( new PasswordStoreWin(login_db_.release(), profile_.get(), wds_.get())); EXPECT_TRUE(store->Init()); @@ -338,6 +342,8 @@ TEST_F(PasswordStoreWinTest, DISABLED_MultipleWDSQueriesOnDifferentThreads) { MessageLoop::current()->Run(); STLDeleteElements(&forms); + + store->Shutdown(); } TEST_F(PasswordStoreWinTest, Migration) { @@ -426,7 +432,7 @@ TEST_F(PasswordStoreWinTest, Migration) { done.Wait(); // Initializing the PasswordStore should trigger a migration. - scoped_refptr<PasswordStoreWin> store( + scoped_refptr<PasswordStore> store( new PasswordStoreWin(login_db_.release(), profile_.get(), wds_.get())); store->Init(); @@ -507,7 +513,7 @@ TEST_F(PasswordStoreWinTest, Migration) { } TEST_F(PasswordStoreWinTest, EmptyLogins) { - scoped_refptr<PasswordStoreWin> store( + scoped_refptr<PasswordStore> store( new PasswordStoreWin(login_db_.release(), profile_.get(), wds_.get())); store->Init(); @@ -539,10 +545,12 @@ TEST_F(PasswordStoreWinTest, EmptyLogins) { store->GetLogins(*form, &consumer); MessageLoop::current()->Run(); + + store->Shutdown(); } TEST_F(PasswordStoreWinTest, EmptyBlacklistLogins) { - scoped_refptr<PasswordStoreWin> store( + scoped_refptr<PasswordStore> store( new PasswordStoreWin(login_db_.release(), profile_.get(), wds_.get())); store->Init(); @@ -560,10 +568,12 @@ TEST_F(PasswordStoreWinTest, EmptyBlacklistLogins) { store->GetBlacklistLogins(&consumer); MessageLoop::current()->Run(); + + store->Shutdown(); } TEST_F(PasswordStoreWinTest, EmptyAutofillableLogins) { - scoped_refptr<PasswordStoreWin> store( + scoped_refptr<PasswordStore> store( new PasswordStoreWin(login_db_.release(), profile_.get(), wds_.get())); store->Init(); @@ -581,4 +591,6 @@ TEST_F(PasswordStoreWinTest, EmptyAutofillableLogins) { store->GetAutofillableLogins(&consumer); MessageLoop::current()->Run(); + + store->Shutdown(); } diff --git a/chrome/browser/password_manager/password_store_x_unittest.cc b/chrome/browser/password_manager/password_store_x_unittest.cc index 80eaa6a..721368d 100644 --- a/chrome/browser/password_manager/password_store_x_unittest.cc +++ b/chrome/browser/password_manager/password_store_x_unittest.cc @@ -436,6 +436,8 @@ TEST_P(PasswordStoreXTest, WDSMigration) { STLDeleteElements(&expected_autofillable); STLDeleteElements(&expected_blacklisted); + + store->Shutdown(); } TEST_P(PasswordStoreXTest, WDSMigrationAlreadyDone) { @@ -499,6 +501,8 @@ TEST_P(PasswordStoreXTest, WDSMigrationAlreadyDone) { MessageLoop::current()->Run(); STLDeleteElements(&unexpected_autofillable); + + store->Shutdown(); } TEST_P(PasswordStoreXTest, Notifications) { @@ -591,6 +595,8 @@ TEST_P(PasswordStoreXTest, Notifications) { BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, new SignalingTask(&done)); done.Wait(); + + store->Shutdown(); } TEST_P(PasswordStoreXTest, NativeMigration) { @@ -730,6 +736,8 @@ TEST_P(PasswordStoreXTest, NativeMigration) { STLDeleteElements(&expected_autofillable); STLDeleteElements(&expected_blacklisted); + + store->Shutdown(); } INSTANTIATE_TEST_CASE_P(NoBackend, diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 9f507eb..9e8adce 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc @@ -609,6 +609,10 @@ ProfileImpl::~ProfileImpl() { // The sync service needs to be deleted before the services it calls. sync_service_.reset(); + // Password store uses WebDB, shut it down before the WebDB has been shutdown. + if (password_store_.get()) + password_store_->Shutdown(); + // Both HistoryService and WebDataService maintain threads for background // processing. Its possible each thread still has tasks on it that have // increased the ref count of the service. In such a situation, when we diff --git a/chrome/browser/resources/options/chromeos/internet_options.js b/chrome/browser/resources/options/chromeos/internet_options.js index 4902f1d..a802a9b 100644 --- a/chrome/browser/resources/options/chromeos/internet_options.js +++ b/chrome/browser/resources/options/chromeos/internet_options.js @@ -404,9 +404,18 @@ cr.define('options', function() { $('operatorName').textContent = data.operatorName; $('operatorCode').textContent = data.operatorCode; $('imsi').textContent = data.imsi; - $('cellularApn').value = data.apn; - $('cellularApnUsername').value = data.apn_username; - $('cellularApnPassword').value = data.apn_password; + // If there's no custom APN show default APN that is used. These will be + // displayed differently when http://crosbug.com/14290 is fixed. + // See also http://crosbug.com/p/4058 for context. + if (data.apn != '') { + $('cellularApn').value = data.apn; + $('cellularApnUsername').value = data.apn_username; + $('cellularApnPassword').value = data.apn_password; + } else { + $('cellularApn').value = data.last_good_apn; + $('cellularApnUsername').value = data.last_good_apn_username; + $('cellularApnPassword').value = data.last_good_apn_password; + } $('sim-card-lock-enabled').checked = data.simCardLockEnabled; InternetOptions.enableSecurityTab(true); page.setAttribute('gsm', true); diff --git a/chrome/browser/sync/profile_sync_service_password_unittest.cc b/chrome/browser/sync/profile_sync_service_password_unittest.cc index 16cb99e..2f0f719 100644 --- a/chrome/browser/sync/profile_sync_service_password_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_password_unittest.cc @@ -169,6 +169,7 @@ class ProfileSyncServicePasswordTest : public AbstractProfileSyncServiceTest { } virtual void TearDown() { + password_store_->Shutdown(); service_.reset(); notification_service_->TearDown(); db_thread_.Stop(); diff --git a/chrome/browser/tab_contents/web_contents_unittest.cc b/chrome/browser/tab_contents/web_contents_unittest.cc index 6057195..dc18b54 100644 --- a/chrome/browser/tab_contents/web_contents_unittest.cc +++ b/chrome/browser/tab_contents/web_contents_unittest.cc @@ -702,40 +702,40 @@ TEST_F(TabContentsTest, CrossSiteNavigationNotPreemptedByFrame) { EXPECT_TRUE(contents()->cross_navigation_pending()); } -// Test that the original renderer can preempt a cross-site navigation while the -// beforeunload request is in flight. -TEST_F(TabContentsTest, CrossSitePreemptDuringBeforeUnload) { +// Test that a cross-site navigation is not preempted if the previous +// renderer sends a FrameNavigate message just before being told to stop. +// We should only preempt the cross-site navigation if the previous renderer +// has started a new navigation. See http://crbug.com/79176. +TEST_F(TabContentsTest, CrossSiteNotPreemptedDuringBeforeUnload) { contents()->transition_cross_site = true; - TestRenderViewHost* orig_rvh = rvh(); - SiteInstance* instance1 = contents()->GetSiteInstance(); - // Navigate to URL. First URL should use first RenderViewHost. - const GURL url("http://www.google.com"); + // Navigate to NTP URL. + const GURL url("chrome://newtab"); controller().LoadURL(url, GURL(), PageTransition::TYPED); - ViewHostMsg_FrameNavigate_Params params1; - InitNavigateParams(¶ms1, 1, url); - contents()->TestDidNavigate(orig_rvh, params1); + TestRenderViewHost* orig_rvh = rvh(); EXPECT_FALSE(contents()->cross_navigation_pending()); - EXPECT_EQ(orig_rvh, contents()->render_view_host()); - // Navigate to new site, with the befureunload request in flight. + // Navigate to new site, with the beforeunload request in flight. const GURL url2("http://www.yahoo.com"); controller().LoadURL(url2, GURL(), PageTransition::TYPED); + TestRenderViewHost* pending_rvh = contents()->pending_rvh(); + EXPECT_TRUE(contents()->cross_navigation_pending()); + EXPECT_TRUE(orig_rvh->is_waiting_for_beforeunload_ack()); - // Suppose the original renderer navigates now, while the beforeunload request - // is in flight. We must cancel the pending navigation and show this new - // page, because the beforeunload handler might return false. - orig_rvh->SendNavigate(2, GURL("http://www.google.com/foo")); + // Suppose the first navigation tries to commit now, with a + // ViewMsg_Stop in flight. This should not cancel the pending navigation, + // but it should act as if the beforeunload ack arrived. + orig_rvh->SendNavigate(1, GURL("chrome://newtab")); + EXPECT_TRUE(contents()->cross_navigation_pending()); + EXPECT_EQ(orig_rvh, contents()->render_view_host()); + EXPECT_FALSE(orig_rvh->is_waiting_for_beforeunload_ack()); - // Verify that the pending navigation is cancelled. - SiteInstance* instance2 = contents()->GetSiteInstance(); + // The pending navigation should be able to commit successfully. + ViewHostMsg_FrameNavigate_Params params2; + InitNavigateParams(¶ms2, 1, url2, PageTransition::TYPED); + contents()->TestDidNavigate(pending_rvh, params2); EXPECT_FALSE(contents()->cross_navigation_pending()); - EXPECT_EQ(orig_rvh, rvh()); - EXPECT_EQ(instance1, instance2); - EXPECT_TRUE(contents()->pending_rvh() == NULL); - - // Make sure the beforeunload ack doesn't cause problems if it arrives here. - orig_rvh->TestOnMessageReceived(ViewHostMsg_ShouldClose_ACK(0, true)); + EXPECT_EQ(pending_rvh, contents()->render_view_host()); } // Test that the original renderer cannot preempt a cross-site navigation once diff --git a/chrome/browser/ui/browser_init.cc b/chrome/browser/ui/browser_init.cc index 920b830..12eb45a 100644 --- a/chrome/browser/ui/browser_init.cc +++ b/chrome/browser/ui/browser_init.cc @@ -1186,7 +1186,7 @@ void BrowserInit::LaunchWithProfile::AddStartupURLs( while (it != browser_init_->first_run_tabs_.end()) { // Replace magic names for the actual urls. if (it->host() == "new_tab_page") { - startup_urls->push_back(GURL()); + startup_urls->push_back(GURL(chrome::kChromeUINewTabURL)); } else if (it->host() == "welcome_page") { startup_urls->push_back(GetWelcomePageURL()); } else { diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm index d0bfe00..8ba6eae 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller.mm @@ -156,19 +156,9 @@ MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 @interface NSWindow (LionSDKDeclarations) -- (void)toggleFullScreen:(id)sender; - (void)setRestorable:(BOOL)flag; @end -enum { - NSWindowCollectionBehaviorFullScreenPrimary = 1 << 7, - NSWindowCollectionBehaviorFullScreenAuxiliary = 1 << 8 -}; - -enum { - NSWindowFullScreenButton = 7 -}; - #endif // MAC_OS_X_VERSION_10_7 // IncognitoImageView subclasses NSView to allow mouse events to pass through it @@ -417,20 +407,7 @@ enum { if ([self hasToolbar]) // Do not create the buttons in popups. [toolbarController_ createBrowserActionButtons]; - // For versions of Mac OS that provide an "enter fullscreen" button, make - // one appear (in a rather hacky manner). http://crbug.com/74065 : When - // switching the fullscreen implementation to the new API, revisit how much - // of this hacky code is necessary. - if ([window respondsToSelector:@selector(toggleFullScreen:)]) { - NSWindowCollectionBehavior behavior = [window collectionBehavior]; - behavior |= NSWindowCollectionBehaviorFullScreenPrimary; - [window setCollectionBehavior:behavior]; - - NSButton* fullscreenButton = - [window standardWindowButton:NSWindowFullScreenButton]; - [fullscreenButton setAction:@selector(enterFullscreen:)]; - [fullscreenButton setTarget:self]; - } + [self setUpOSFullScreenButton]; // We are done initializing now. initializing_ = NO; @@ -2057,6 +2034,10 @@ willAnimateFromState:(bookmarks::VisualState)oldState // We're done moving focus, so re-enable bar visibility changes. [self enableBarVisibilityUpdates]; + // This needs to be done when leaving full-screen mode to ensure that the + // button's action is set properly. + [self setUpOSFullScreenButton]; + // Fade back in. if (didFadeOut) { CGDisplayFade(token, kFadeDurationSeconds / 2, kCGDisplayBlendSolidColor, diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.h b/chrome/browser/ui/cocoa/browser_window_controller_private.h index 8757126..48d39f6 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_private.h +++ b/chrome/browser/ui/cocoa/browser_window_controller_private.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -113,6 +113,12 @@ - (void)enableBarVisibilityUpdates; - (void)disableBarVisibilityUpdates; +// For versions of Mac OS that provide an "enter fullscreen" button, make one +// appear (in a rather hacky manner). http://crbug.com/74065 : When switching +// the fullscreen implementation to the new API, revisit how much of this +// hacky code is necessary. +- (void)setUpOSFullScreenButton; + @end // @interface BrowserWindowController(Private) diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.mm b/chrome/browser/ui/cocoa/browser_window_controller_private.mm index 2eac331..52532cc 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_private.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller_private.mm @@ -28,6 +28,26 @@ #include "content/browser/tab_contents/tab_contents.h" #include "content/browser/tab_contents/tab_contents_view.h" +// Provide the forward-declarations of new 10.7 SDK symbols so they can be +// called when building with the 10.5 SDK. +#if !defined(MAC_OS_X_VERSION_10_7) || \ + MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 + +@interface NSWindow (LionSDKDeclarations) +- (void)toggleFullScreen:(id)sender; +@end + +enum { + NSWindowCollectionBehaviorFullScreenPrimary = 1 << 7, + NSWindowCollectionBehaviorFullScreenAuxiliary = 1 << 8 +}; + +enum { + NSWindowFullScreenButton = 7 +}; + +#endif // MAC_OS_X_VERSION_10_7 + namespace { // Space between the incognito badge and the right edge of the window. @@ -40,22 +60,7 @@ const CGFloat kLocBarLeftRightInset = 1; const CGFloat kLocBarTopInset = 0; const CGFloat kLocBarBottomInset = 1; -} // end namespace - -// 10.7 adds public APIs for full-screen support. Provide the declaration so it -// can be called below when building with the 10.5 SDK. -#if !defined(MAC_OS_X_VERSION_10_7) || \ -MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 - -@interface NSWindow (LionSDKDeclarations) -- (void)toggleFullScreen:(id)sender; -@end - -enum { - NSWindowFullScreenButton = 7 -}; - -#endif // MAC_OS_X_VERSION_10_7 +} // namespace @implementation BrowserWindowController(Private) @@ -537,4 +542,18 @@ willPositionSheet:(NSWindow*)sheet [fullscreenController_ cancelAnimationAndTimers]; } +- (void)setUpOSFullScreenButton { + NSWindow* window = [self window]; + if ([window respondsToSelector:@selector(toggleFullScreen:)]) { + NSWindowCollectionBehavior behavior = [window collectionBehavior]; + behavior |= NSWindowCollectionBehaviorFullScreenPrimary; + [window setCollectionBehavior:behavior]; + + NSButton* fullscreenButton = + [window standardWindowButton:NSWindowFullScreenButton]; + [fullscreenButton setAction:@selector(enterFullscreen:)]; + [fullscreenButton setTarget:self]; + } +} + @end // @implementation BrowserWindowController(Private) diff --git a/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc b/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc index 16da1e5..7be689a 100644 --- a/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc +++ b/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc @@ -939,7 +939,7 @@ void MobileSetupHandler::EvaluateCellularNetwork( if ((network->activation_state() == chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED || network->activation_state() == chromeos::ACTIVATION_STATE_ACTIVATING) && - (network->error() == chromeos::ERROR_UNKNOWN || + (network->error() == chromeos::ERROR_NO_ERROR || network->error() == chromeos::ERROR_OTASP_FAILED) && network->state() == chromeos::STATE_ACTIVATION_FAILURE) { LOG(WARNING) << "Activation failure detected " diff --git a/chrome/common/extensions/docs/css/ApiRefStyles.css b/chrome/common/extensions/docs/css/ApiRefStyles.css index 3a7040f..ef33312 100644 --- a/chrome/common/extensions/docs/css/ApiRefStyles.css +++ b/chrome/common/extensions/docs/css/ApiRefStyles.css @@ -84,6 +84,10 @@ pre b { background:yellow } +.linenumber { + color: #999999; +} + code,pre { font-family:monospace; color:#007000 diff --git a/chrome/common/extensions/docs/overview.html b/chrome/common/extensions/docs/overview.html index f91d3aa..e5c7c8d 100644 --- a/chrome/common/extensions/docs/overview.html +++ b/chrome/common/extensions/docs/overview.html @@ -287,6 +287,17 @@ </li> </ol> </li><li> + <a href="#apis"> Using the chrome.* APIs </a> + <ol> + <li> + <a href="#sync"> Asynchronous vs. synchronous methods </a> + </li><li> + <a href="#sync-example"> Example: Using a callback </a> + </li><li> + <a href="#chrome-more"> More details </a> + </li> + </ol> + </li><li> <a href="#pageComm">Communication between pages </a> <ol> <li style="display: none; "> @@ -628,7 +639,7 @@ Here are some examples of extensions that usually An extension with a content script that doesn't use cross-origin XMLHttpRequests or localStorage, and that doesn't need to use - <a href="api_index.html">extension APIs</a>. + <a href="#apis">extension APIs</a>. </li> <li> An extension that has no UI except for an options page. @@ -650,7 +661,7 @@ Any extension can have an options page, which lets users customize how the extension works. Another type of special page is the override page. And finally, you can -use <a href="tabs.html#method-create"><code>chrome.tabs.create()</code></a> +use <a href="tabs.html#method-create">chrome.tabs.create()</a> or <code>window.open()</code> to display any other HTML files that are in the extension. </p> @@ -743,6 +754,138 @@ see <a href="content_scripts.html">Content Scripts</a>. </p> +<h2 id="apis"> Using the chrome.* APIs </h2> + +<p> +In addition to having access to all the APIs that web pages and apps can use, +extensions can also use Chrome-only APIs +(often called <em>chrome.* APIs</em>) +that allow tight integration with the browser. +For example, any extension or web app can use the +standard <code>window.open()</code> method to open a URL. +But if you want to specify which window that URL should be displayed in, +your extension can use the Chrome-only +<a href="tabs.html#method-create">chrome.tabs.create()</a> +method instead. +</p> + +<h3 id="sync"> Asynchronous vs. synchronous methods </h3> +<p> +Most methods in the chrome.* APIs are <b>asynchronous</b>: +they return immediately, without waiting for the operation to finish. +If you need to know the outcome of that operation, +then you pass a callback function into the method. +That callback is executed later (potentially <em>much</em> later), +sometime after the method returns. +Here's an example of the signature for an asynchronous method: +</p> + +<p> +<code> +chrome.tabs.create(object <em>createProperties</em>, function <em>callback</em>) +</code> +</p> + +<p> +Other chrome.* methods are <b>synchronous</b>. +Synchronous methods never have a callback +because they don't return until they've completed all their work. +Often, synchronous methods have a return type. +Consider the +<a href="extension.html#method-getBackgroundPage">chrome.extensions.getBackgroundPage()</a> method: +</p> + +<p> +<code> +DOMWindow chrome.extension.getBackgroundPage() +</code> +</p> + +<p> +This method has no callback and a return type of <code>DOMWindow</code> +because it synchronously returns the background page +and performs no other, asynchronous work. +</p> + + +<h3 id="sync-example"> Example: Using a callback </h3> + +<p> +Say you want to navigate +the user's currently selected tab to a new URL. +To do this, you need to get the current tab's ID +(using <a href="tabs.html#method-getSelected">chrome.tabs.getSelected()</a>) +and then make that tab go to the new URL +(using <a href="tabs.html#method-update">chrome.tabs.update()</a>). +</p> + +<p> +If <code>getSelected()</code> were synchronous, +you might write code like this: +</p> + +<pre> <b>//THIS CODE DOESN'T WORK</b> +<span class="linenumber">1: </span>var tab = chrome.tabs.getSelected(null); <b>//WRONG!!!</b> +<span class="linenumber">2: </span>chrome.tabs.update(tab.id, {url:newUrl}); +<span class="linenumber">3: </span>someOtherFunction(); +</pre> + +<p> +That approach fails +because <code>getSelected()</code> is asynchronous. +It returns without waiting for its work to complete, +and it doesn't even return a value +(although some asynchronous methods do). +You can tell that <code>getSelected()</code> is asynchronous +by the <em>callback</em> parameter in its signature: + +</p><p> +<code> +chrome.tabs.getSelected(integer <em>windowId</em>, function <em>callback</em>) +</code> +</p> + +<p> +To fix the preceding code, +you must use that callback parameter. +The following code shows +how to define a callback function +that gets the results from <code>getSelected()</code> +(as a parameter named <code>tab</code>) +and calls <code>update()</code>. +</p> + +<pre> <b>//THIS CODE WORKS</b> +<span class="linenumber">1: </span>chrome.tabs.getSelected(null, <b>function(tab) {</b> +<span class="linenumber">2: </span> chrome.tabs.update(tab.id, {url:newUrl}); +<span class="linenumber">3: </span><b>}</b>); +<span class="linenumber">4: </span>someOtherFunction(); +</pre> + +<p> +In this example, the lines are executed in the following order: 1, 4, 2. +The callback function specified to <code>getSelected</code> is called +(and line 2 executed) +only after information about the currently selected tab is available, +which is sometime after <code>getSelected()</code> returns. +Although <code>update()</code> is asynchronous, +this example doesn't use its callback parameter, +since we don't do anything about the results of the update. +</p> + + +<h3 id="chrome-more"> More details </h3> + +<p> +For more information, see the +<a href="api_index.html">chrome.* API docs</a> +and watch this video: +</p> + +<p> +<iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/bmxr75CV36A?rel=0" frameborder="0" allowfullscreen=""></iframe> +</p> + <h2 id="pageComm">Communication between pages </h2> <p> diff --git a/chrome/common/extensions/docs/static/overview.html b/chrome/common/extensions/docs/static/overview.html index dabc217..1da4f38 100644 --- a/chrome/common/extensions/docs/static/overview.html +++ b/chrome/common/extensions/docs/static/overview.html @@ -283,7 +283,7 @@ Here are some examples of extensions that usually An extension with a content script that doesn't use cross-origin XMLHttpRequests or localStorage, and that doesn't need to use - <a href="api_index.html">extension APIs</a>. + <a href="#apis">extension APIs</a>. </li> <li> An extension that has no UI except for an options page. @@ -305,7 +305,7 @@ Any extension can have an options page, which lets users customize how the extension works. Another type of special page is the override page. And finally, you can -use <a href="tabs.html#method-create"><code>chrome.tabs.create()</code></a> +use <a href="tabs.html#method-create">chrome.tabs.create()</a> or <code>window.open()</code> to display any other HTML files that are in the extension. </p> @@ -404,6 +404,140 @@ see <a href="content_scripts.html">Content Scripts</a>. </p> +<h2 id="apis"> Using the chrome.* APIs </h2> + +<p> +In addition to having access to all the APIs that web pages and apps can use, +extensions can also use Chrome-only APIs +(often called <em>chrome.* APIs</em>) +that allow tight integration with the browser. +For example, any extension or web app can use the +standard <code>window.open()</code> method to open a URL. +But if you want to specify which window that URL should be displayed in, +your extension can use the Chrome-only +<a href="tabs.html#method-create">chrome.tabs.create()</a> +method instead. +</p> + +<h3 id="sync"> Asynchronous vs. synchronous methods </h3> +<p> +Most methods in the chrome.* APIs are <b>asynchronous</b>: +they return immediately, without waiting for the operation to finish. +If you need to know the outcome of that operation, +then you pass a callback function into the method. +That callback is executed later (potentially <em>much</em> later), +sometime after the method returns. +Here's an example of the signature for an asynchronous method: +</p> + +<p> +<code> +chrome.tabs.create(object <em>createProperties</em>, function <em>callback</em>) +</code> +</p> + +<p> +Other chrome.* methods are <b>synchronous</b>. +Synchronous methods never have a callback +because they don't return until they've completed all their work. +Often, synchronous methods have a return type. +Consider the +<a href="extension.html#method-getBackgroundPage">chrome.extensions.getBackgroundPage()</a> method: +</p> + +<p> +<code> +DOMWindow chrome.extension.getBackgroundPage() +</code> +</p> + +<p> +This method has no callback and a return type of <code>DOMWindow</code> +because it synchronously returns the background page +and performs no other, asynchronous work. +</p> + + +<h3 id="sync-example"> Example: Using a callback </h3> + +<p> +Say you want to navigate +the user's currently selected tab to a new URL. +To do this, you need to get the current tab's ID +(using <a href="tabs.html#method-getSelected">chrome.tabs.getSelected()</a>) +and then make that tab go to the new URL +(using <a href="tabs.html#method-update">chrome.tabs.update()</a>). +</p> + +<p> +If <code>getSelected()</code> were synchronous, +you might write code like this: +</p> + +<pre> + <b>//THIS CODE DOESN'T WORK</b> +<span class="linenumber">1: </span>var tab = chrome.tabs.getSelected(null); <b>//WRONG!!!</b> +<span class="linenumber">2: </span>chrome.tabs.update(tab.id, {url:newUrl}); +<span class="linenumber">3: </span>someOtherFunction(); +</pre> + +<p> +That approach fails +because <code>getSelected()</code> is asynchronous. +It returns without waiting for its work to complete, +and it doesn't even return a value +(although some asynchronous methods do). +You can tell that <code>getSelected()</code> is asynchronous +by the <em>callback</em> parameter in its signature: + +<p> +<code> +chrome.tabs.getSelected(integer <em>windowId</em>, function <em>callback</em>) +</code> +</p> + +<p> +To fix the preceding code, +you must use that callback parameter. +The following code shows +how to define a callback function +that gets the results from <code>getSelected()</code> +(as a parameter named <code>tab</code>) +and calls <code>update()</code>. +</p> + +<pre> + <b>//THIS CODE WORKS</b> +<span class="linenumber">1: </span>chrome.tabs.getSelected(null, <b>function(tab) {</b> +<span class="linenumber">2: </span> chrome.tabs.update(tab.id, {url:newUrl}); +<span class="linenumber">3: </span><b>}</b>); +<span class="linenumber">4: </span>someOtherFunction(); +</pre> + +<p> +In this example, the lines are executed in the following order: 1, 4, 2. +The callback function specified to <code>getSelected</code> is called +(and line 2 executed) +only after information about the currently selected tab is available, +which is sometime after <code>getSelected()</code> returns. +Although <code>update()</code> is asynchronous, +this example doesn't use its callback parameter, +since we don't do anything about the results of the update. +</p> + + +<h3 id="chrome-more"> More details </h3> + +<p> +For more information, see the +<a href="api_index.html">chrome.* API docs</a> +and watch this video: +</p> + +<p> +<iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/bmxr75CV36A?rel=0" frameborder="0" allowfullscreen></iframe> +</p> + <h2 id="pageComm">Communication between pages </h2> <p> diff --git a/chrome/common/extensions/docs/static/whats_new.html b/chrome/common/extensions/docs/static/whats_new.html index 437e9cd..5c1bd6e 100644 --- a/chrome/common/extensions/docs/static/whats_new.html +++ b/chrome/common/extensions/docs/static/whats_new.html @@ -7,6 +7,7 @@ made in recent releases. </p> <ul> + <li> <a href="#12">Google Chrome 12</a> </li> <li> <a href="#11">Google Chrome 11</a> </li> <li> <a href="#10">Google Chrome 10</a> </li> <li> <a href="#9">Google Chrome 9</a> </li> @@ -16,6 +17,38 @@ made in recent releases. </ul> +<h2 id="12"> Google Chrome 12 </h2> + +<h4> Additions to existing APIs </h4> + <ul> + <li> Two new <code>chrome.extension</code> + methods—<a href="extension.html#method-isAllowedFileSchemeAccess">isAllowedFileSchemeAccess()</a> and + <a href="extension.html#method-isAllowedIncognitoAccess">isAllowedIncognitoAccess()</a>—let you + determine whether your extension has increased access, + which the user specifies using the extensions management page + (<b>chrome://extensions</b>). + </li> + <li> The <a href="windows.html#method-create">chrome.windows.create()</a> + method can now take a <code>focused</code> value. + Previously, all new windows had the keyboard focus; + now you can create windows without interrupting the user's typing. + </li> + <li> If the manifest specifies "experimental" permission, + your extension can specify "panel" as the value of + the <code>type</code> field in + the <a href="windows.html#method-create">chrome.windows.create()</a> + method + or the <a href="windows.html#type-Window">Window</a> type. + </li> + <li> The <a href="cookies.html#event-onChanged">onChanged</a> + event of <code>chrome.cookies</code> + now has a <code>cause</code> parameter. </li> + <li> The <code>chrome.contextMenus</code> + <a href="contextMenus.html#method-create">create()</a> and + <a href="contextMenus.html#method-update">update()</a> + methods now let you specify a context value of "frame". + </ul> + <h2 id="11"> Google Chrome 11 </h2> <h4> Changes to existing APIs </h4> @@ -66,7 +99,7 @@ made in recent releases. <h4> Additions to existing APIs </h4> <ul> <li> The <a href="windows.html#method-create">chrome.windows.create()</a> - method now has a <code>tabId</code> parameter. + method now has a <code>tabId</code> field. You can use it to move a tab or panel into a new window. <p class="note"> <b>Note:</b> @@ -88,9 +121,6 @@ made in recent releases. <li> The <a href="manifest.html#homepage_url">homepage_url</a> field lets you specify the extension or app's homepage. </li> </ul> -</h4> - -<!-- <h4> New experimental APIs </h4> --> <h4> Additions to existing APIs </h4> <ul> @@ -143,18 +173,6 @@ No API or manifest changes worth noting. </li> </ul> -<!-- -<h4> New experimental APIs </h4> - <ul> - <li> a change </li> - </ul> - -<h4> Additions to existing APIs </h4> - <ul> - <li> a change </li> - </ul> ---> - <h2 id="6">Google Chrome 6</h2> @@ -168,14 +186,6 @@ No API or manifest changes worth noting. machine's idle state changes. </li> </ul> -<h4> New experimental APIs </h4> - <ul> - <li>The <a href="experimental.omnibox.html">omnibox API</a> allows you to - add functionality to the browser's address bar. </li> - <li>The <a href="experimental.infobars.html">infobars API</a> allows you - to add a UI panel across the top of a tab. </li> - </ul> - <h4> Additions to existing APIs </h4> <ul> <li>The <a diff --git a/chrome/common/extensions/docs/whats_new.html b/chrome/common/extensions/docs/whats_new.html index 6e45782..6924f51 100644 --- a/chrome/common/extensions/docs/whats_new.html +++ b/chrome/common/extensions/docs/whats_new.html @@ -321,6 +321,7 @@ made in recent releases. </p> <ul> + <li> <a href="#12">Google Chrome 12</a> </li> <li> <a href="#11">Google Chrome 11</a> </li> <li> <a href="#10">Google Chrome 10</a> </li> <li> <a href="#9">Google Chrome 9</a> </li> @@ -330,6 +331,38 @@ made in recent releases. </ul> +<h2 id="12"> Google Chrome 12 </h2> + +<h4> Additions to existing APIs </h4> + <ul> + <li> Two new <code>chrome.extension</code> + methods—<a href="extension.html#method-isAllowedFileSchemeAccess">isAllowedFileSchemeAccess()</a> and + <a href="extension.html#method-isAllowedIncognitoAccess">isAllowedIncognitoAccess()</a>—let you + determine whether your extension has increased access, + which the user specifies using the extensions management page + (<b>chrome://extensions</b>). + </li> + <li> The <a href="windows.html#method-create">chrome.windows.create()</a> + method can now take a <code>focused</code> value. + Previously, all new windows had the keyboard focus; + now you can create windows without interrupting the user's typing. + </li> + <li> If the manifest specifies "experimental" permission, + your extension can specify "panel" as the value of + the <code>type</code> field in + the <a href="windows.html#method-create">chrome.windows.create()</a> + method + or the <a href="windows.html#type-Window">Window</a> type. + </li> + <li> The <a href="cookies.html#event-onChanged">onChanged</a> + event of <code>chrome.cookies</code> + now has a <code>cause</code> parameter. </li> + <li> The <code>chrome.contextMenus</code> + <a href="contextMenus.html#method-create">create()</a> and + <a href="contextMenus.html#method-update">update()</a> + methods now let you specify a context value of "frame". + </li></ul> + <h2 id="11"> Google Chrome 11 </h2> <h4> Changes to existing APIs </h4> @@ -380,7 +413,7 @@ made in recent releases. <h4> Additions to existing APIs </h4> <ul> <li> The <a href="windows.html#method-create">chrome.windows.create()</a> - method now has a <code>tabId</code> parameter. + method now has a <code>tabId</code> field. You can use it to move a tab or panel into a new window. <p class="note"> <b>Note:</b> @@ -403,9 +436,6 @@ made in recent releases. lets you specify the extension or app's homepage. </li> </ul> - -<!-- <h4> New experimental APIs </h4> --> - <h4> Additions to existing APIs </h4> <ul> <li> The <a href="tabs.html#type-Tab">Tab</a> object @@ -457,18 +487,6 @@ No API or manifest changes worth noting. </li> </ul> -<!-- -<h4> New experimental APIs </h4> - <ul> - <li> a change </li> - </ul> - -<h4> Additions to existing APIs </h4> - <ul> - <li> a change </li> - </ul> ---> - <h2 id="6">Google Chrome 6</h2> @@ -482,14 +500,6 @@ No API or manifest changes worth noting. machine's idle state changes. </li> </ul> -<h4> New experimental APIs </h4> - <ul> - <li>The <a href="experimental.omnibox.html">omnibox API</a> allows you to - add functionality to the browser's address bar. </li> - <li>The <a href="experimental.infobars.html">infobars API</a> allows you - to add a UI panel across the top of a tab. </li> - </ul> - <h4> Additions to existing APIs </h4> <ul> <li>The <a href="extension.html#method-getViews">chrome.extension.getViews()</a> |