summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorKristian Monsen <kristianm@google.com>2011-07-26 12:15:06 +0100
committerKristian Monsen <kristianm@google.com>2011-07-26 20:41:55 +0100
commit3dff810fe0cc4962a5fa554318e9bf8bc45f5274 (patch)
treea9fffa9ab7d061ab00538c18beb77403547378d0 /chrome
parent67d814a5d5c8d7df4740db4d2d74d0a41f94bece (diff)
downloadexternal_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')
-rw-r--r--chrome/browser/chrome_browser_application_mac.mm13
-rw-r--r--chrome/browser/chromeos/cros/network_library.cc7
-rw-r--r--chrome/browser/chromeos/cros/network_library.h4
-rw-r--r--chrome/browser/chromeos/login/existing_user_controller.cc11
-rw-r--r--chrome/browser/chromeos/login/wizard_controller.cc5
-rw-r--r--chrome/browser/download/download_extensions.cc1
-rw-r--r--chrome/browser/download/download_manager.cc7
-rw-r--r--chrome/browser/importer/firefox2_importer.cc8
-rw-r--r--chrome/browser/password_manager/password_manager_unittest.cc7
-rw-r--r--chrome/browser/password_manager/password_store.cc4
-rw-r--r--chrome/browser/password_manager/password_store.h3
-rw-r--r--chrome/browser/password_manager/password_store_default.cc123
-rw-r--r--chrome/browser/password_manager/password_store_default.h15
-rw-r--r--chrome/browser/password_manager/password_store_default_unittest.cc12
-rw-r--r--chrome/browser/password_manager/password_store_mac_unittest.cc1
-rw-r--r--chrome/browser/password_manager/password_store_win.cc199
-rw-r--r--chrome/browser/password_manager/password_store_win.h30
-rw-r--r--chrome/browser/password_manager/password_store_win_unittest.cc26
-rw-r--r--chrome/browser/password_manager/password_store_x_unittest.cc8
-rw-r--r--chrome/browser/profiles/profile_impl.cc4
-rw-r--r--chrome/browser/resources/options/chromeos/internet_options.js15
-rw-r--r--chrome/browser/sync/profile_sync_service_password_unittest.cc1
-rw-r--r--chrome/browser/tab_contents/web_contents_unittest.cc48
-rw-r--r--chrome/browser/ui/browser_init.cc2
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller.mm29
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller_private.h8
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller_private.mm51
-rw-r--r--chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc2
-rw-r--r--chrome/common/extensions/docs/css/ApiRefStyles.css4
-rw-r--r--chrome/common/extensions/docs/overview.html147
-rw-r--r--chrome/common/extensions/docs/static/overview.html138
-rw-r--r--chrome/common/extensions/docs/static/whats_new.html58
-rw-r--r--chrome/common/extensions/docs/whats_new.html58
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(&params1, 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(&params2, 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&mdash;<a href="extension.html#method-isAllowedFileSchemeAccess">isAllowedFileSchemeAccess()</a> and
+ <a href="extension.html#method-isAllowedIncognitoAccess">isAllowedIncognitoAccess()</a>&mdash;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>