diff options
-rw-r--r-- | chrome/browser/extensions/extension_info_map.cc | 27 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_info_map.h | 9 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_info_map_unittest.cc | 50 | ||||
-rw-r--r-- | chrome/browser/profile_impl.cc | 4 | ||||
-rw-r--r-- | chrome/browser/tabs/tab_strip_model_unittest.cc | 2 | ||||
-rw-r--r-- | chrome/common/extensions/extension.cc | 194 | ||||
-rw-r--r-- | chrome/common/extensions/extension.h | 464 | ||||
-rw-r--r-- | chrome/common/extensions/extension_unittest.cc | 2 |
8 files changed, 414 insertions, 338 deletions
diff --git a/chrome/browser/extensions/extension_info_map.cc b/chrome/browser/extensions/extension_info_map.cc index 313e5737c..f9f90aa 100644 --- a/chrome/browser/extensions/extension_info_map.cc +++ b/chrome/browser/extensions/extension_info_map.cc @@ -5,7 +5,6 @@ #include "chrome/browser/extensions/extension_info_map.h" #include "chrome/browser/browser_thread.h" -#include "chrome/common/extensions/extension.h" #include "chrome/common/url_constants.h" namespace { @@ -22,13 +21,13 @@ ExtensionInfoMap::ExtensionInfoMap() { ExtensionInfoMap::~ExtensionInfoMap() { } -void ExtensionInfoMap::AddExtension(const Extension* extension) { +void ExtensionInfoMap::AddExtension(const Extension::StaticData* data) { CheckOnValidThread(); - extension_info_[extension->id()] = extension; + extension_info_[data->id] = data; // Our map has already added a reference. Balance the reference given at the // call-site. - extension->Release(); + data->Release(); } void ExtensionInfoMap::RemoveExtension(const std::string& id) { @@ -49,7 +48,7 @@ void ExtensionInfoMap::RemoveExtension(const std::string& id) { std::string ExtensionInfoMap::GetNameForExtension(const std::string& id) const { Map::const_iterator iter = extension_info_.find(id); if (iter != extension_info_.end()) - return iter->second->name(); + return iter->second->name; else return std::string(); } @@ -57,22 +56,21 @@ std::string ExtensionInfoMap::GetNameForExtension(const std::string& id) const { FilePath ExtensionInfoMap::GetPathForExtension(const std::string& id) const { Map::const_iterator iter = extension_info_.find(id); if (iter != extension_info_.end()) - return iter->second->path(); + return iter->second->path; else return FilePath(); } bool ExtensionInfoMap::ExtensionHasWebExtent(const std::string& id) const { Map::const_iterator iter = extension_info_.find(id); - return iter != extension_info_.end() && - !iter->second->web_extent().is_empty(); + return iter != extension_info_.end() && !iter->second->extent.is_empty(); } bool ExtensionInfoMap::ExtensionCanLoadInIncognito( const std::string& id) const { Map::const_iterator iter = extension_info_.find(id); // Only split-mode extensions can load in incognito profiles. - return iter != extension_info_.end() && iter->second->incognito_split_mode(); + return iter != extension_info_.end() && iter->second->incognito_split_mode; } std::string ExtensionInfoMap::GetDefaultLocaleForExtension( @@ -80,7 +78,7 @@ std::string ExtensionInfoMap::GetDefaultLocaleForExtension( Map::const_iterator iter = extension_info_.find(id); std::string result; if (iter != extension_info_.end()) - result = iter->second->default_locale(); + result = iter->second->default_locale; return result; } @@ -90,7 +88,7 @@ ExtensionExtent ExtensionInfoMap::GetEffectiveHostPermissionsForExtension( Map::const_iterator iter = extension_info_.find(id); ExtensionExtent result; if (iter != extension_info_.end()) - result = iter->second->GetEffectiveHostPermissions(); + result = iter->second->effective_host_permissions; return result; } @@ -108,14 +106,15 @@ bool ExtensionInfoMap::CheckURLAccessToExtensionPermission( // disallowed, so only one will match. info = extension_info_.begin(); while (info != extension_info_.end() && - !info->second->web_extent().ContainsURL(url)) + !info->second->extent.ContainsURL(url)) ++info; } if (info == extension_info_.end()) return false; - return info->second->api_permissions().count(permission_name) != 0; + const std::set<std::string>& api_permissions = info->second->api_permissions; + return api_permissions.count(permission_name) != 0; } bool ExtensionInfoMap::URLIsForExtensionIcon(const GURL& url) const { @@ -128,5 +127,5 @@ bool ExtensionInfoMap::URLIsForExtensionIcon(const GURL& url) const { std::string path = url.path(); DCHECK(path.length() > 0 && path[0] == '/'); path = path.substr(1); - return iter->second->icons().ContainsPath(path); + return iter->second->icons.ContainsPath(path); } diff --git a/chrome/browser/extensions/extension_info_map.h b/chrome/browser/extensions/extension_info_map.h index 7d872ba..fb03162 100644 --- a/chrome/browser/extensions/extension_info_map.h +++ b/chrome/browser/extensions/extension_info_map.h @@ -12,11 +12,9 @@ #include "base/basictypes.h" #include "base/file_path.h" #include "base/ref_counted.h" -#include "chrome/common/extensions/extension_extent.h" +#include "chrome/common/extensions/extension.h" #include "googleurl/src/gurl.h" -class Extension; - // Contains extension data that needs to be accessed on the IO thread. It can // be created/destroyed on any thread, but all other methods must be called on // the IO thread. @@ -29,7 +27,7 @@ class ExtensionInfoMap : public base::RefCountedThreadSafe<ExtensionInfoMap> { ~ExtensionInfoMap(); // Callback for when new extensions are loaded. - void AddExtension(const Extension* extension); + void AddExtension(const Extension::StaticData* data); // Callback for when an extension is unloaded. void RemoveExtension(const std::string& id); @@ -65,7 +63,8 @@ class ExtensionInfoMap : public base::RefCountedThreadSafe<ExtensionInfoMap> { private: // Map of extension info by extension id. - typedef std::map<std::string, scoped_refptr<const Extension> > Map; + typedef std::map<std::string, scoped_refptr<const Extension::StaticData> > + Map; Map extension_info_; }; diff --git a/chrome/browser/extensions/extension_info_map_unittest.cc b/chrome/browser/extensions/extension_info_map_unittest.cc index d4892d1..e417d23 100644 --- a/chrome/browser/extensions/extension_info_map_unittest.cc +++ b/chrome/browser/extensions/extension_info_map_unittest.cc @@ -7,7 +7,6 @@ #include "chrome/browser/browser_thread.h" #include "chrome/browser/extensions/extension_info_map.h" #include "chrome/common/chrome_paths.h" -#include "chrome/common/extensions/extension.h" #include "chrome/common/json_value_serializer.h" #include "testing/gtest/include/gtest/gtest.h" @@ -74,36 +73,37 @@ static scoped_refptr<Extension> LoadManifest(const std::string& dir, TEST_F(ExtensionInfoMapTest, RefCounting) { scoped_refptr<ExtensionInfoMap> info_map(new ExtensionInfoMap()); - // New extensions should have a single reference holding onto them. + // New extensions should have a single reference holding onto their static + // data. scoped_refptr<Extension> extension1(CreateExtension("extension1")); scoped_refptr<Extension> extension2(CreateExtension("extension2")); scoped_refptr<Extension> extension3(CreateExtension("extension3")); - EXPECT_TRUE(extension1->HasOneRef()); - EXPECT_TRUE(extension2->HasOneRef()); - EXPECT_TRUE(extension3->HasOneRef()); + EXPECT_TRUE(extension1->static_data()->HasOneRef()); + EXPECT_TRUE(extension2->static_data()->HasOneRef()); + EXPECT_TRUE(extension3->static_data()->HasOneRef()); // Add a ref to each extension and give it to the info map. The info map // expects the caller to add a ref for it, but then assumes ownership of that // reference. - extension1->AddRef(); - info_map->AddExtension(extension1); - extension2->AddRef(); - info_map->AddExtension(extension2); - extension3->AddRef(); - info_map->AddExtension(extension3); - - // Release extension1, and the info map should have the only ref. - const Extension* weak_extension1 = extension1; + extension1->static_data()->AddRef(); + info_map->AddExtension(extension1->static_data()); + extension2->static_data()->AddRef(); + info_map->AddExtension(extension2->static_data()); + extension3->static_data()->AddRef(); + info_map->AddExtension(extension3->static_data()); + + // Delete extension1, and the info map should have the only ref. + const Extension::StaticData* data1 = extension1->static_data(); extension1 = NULL; - EXPECT_TRUE(weak_extension1->HasOneRef()); + EXPECT_TRUE(data1->HasOneRef()); // Remove extension2, and the extension2 object should have the only ref. info_map->RemoveExtension(extension2->id()); - EXPECT_TRUE(extension2->HasOneRef()); + EXPECT_TRUE(extension2->static_data()->HasOneRef()); // Delete the info map, and the extension3 object should have the only ref. info_map = NULL; - EXPECT_TRUE(extension3->HasOneRef()); + EXPECT_TRUE(extension3->static_data()->HasOneRef()); } // Tests that we can query a few extension properties from the ExtensionInfoMap. @@ -113,10 +113,10 @@ TEST_F(ExtensionInfoMapTest, Properties) { scoped_refptr<Extension> extension1(CreateExtension("extension1")); scoped_refptr<Extension> extension2(CreateExtension("extension2")); - extension1->AddRef(); - info_map->AddExtension(extension1); - extension2->AddRef(); - info_map->AddExtension(extension2); + extension1->static_data()->AddRef(); + info_map->AddExtension(extension1->static_data()); + extension2->static_data()->AddRef(); + info_map->AddExtension(extension2->static_data()); EXPECT_EQ(extension1->name(), info_map->GetNameForExtension(extension1->id())); @@ -142,10 +142,10 @@ TEST_F(ExtensionInfoMapTest, CheckPermissions) { ASSERT_TRUE(app->is_app()); ASSERT_TRUE(app->web_extent().ContainsURL(app_url)); - app->AddRef(); - info_map->AddExtension(app); - extension->AddRef(); - info_map->AddExtension(extension); + app->static_data()->AddRef(); + info_map->AddExtension(app->static_data()); + extension->static_data()->AddRef(); + info_map->AddExtension(extension->static_data()); // The app should have the notifications permission, either from a // chrome-extension URL or from its web extent. diff --git a/chrome/browser/profile_impl.cc b/chrome/browser/profile_impl.cc index 8b046ed..c60c33b 100644 --- a/chrome/browser/profile_impl.cc +++ b/chrome/browser/profile_impl.cc @@ -778,12 +778,12 @@ void ProfileImpl::RegisterExtensionWithRequestContexts( const Extension* extension) { // AddRef to ensure the data lives until the other thread gets it. Balanced in // OnNewExtensions. - extension->AddRef(); + extension->static_data()->AddRef(); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, NewRunnableMethod(extension_info_map_.get(), &ExtensionInfoMap::AddExtension, - extension)); + extension->static_data())); } void ProfileImpl::UnregisterExtensionWithRequestContexts( diff --git a/chrome/browser/tabs/tab_strip_model_unittest.cc b/chrome/browser/tabs/tab_strip_model_unittest.cc index a08a5bc..906119c 100644 --- a/chrome/browser/tabs/tab_strip_model_unittest.cc +++ b/chrome/browser/tabs/tab_strip_model_unittest.cc @@ -1513,7 +1513,7 @@ TEST_F(TabStripModelTest, Apps) { #endif scoped_refptr<Extension> extension_app(new Extension(path, Extension::INVALID)); - extension_app->launch_web_url_ = "http://www.google.com"; + extension_app->mutable_static_data_->launch_web_url = "http://www.google.com"; TabContents* contents1 = CreateTabContents(); contents1->SetExtensionApp(extension_app); TabContents* contents2 = CreateTabContents(); diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc index 2ba995c..5d87fd0 100644 --- a/chrome/common/extensions/extension.cc +++ b/chrome/common/extensions/extension.cc @@ -249,6 +249,24 @@ const size_t Extension::kNumHostedAppPermissions = const char Extension::kOldUnlimitedStoragePermission[] = "unlimited_storage"; // +// Extension::StaticData +// + +Extension::StaticData::StaticData() + : incognito_split_mode(false), + location(INVALID), + converted_from_user_script(false), + is_theme(false), + is_app(false), + launch_container(extension_misc::LAUNCH_TAB), + launch_width(0), + launch_height(0) { +} + +Extension::StaticData::~StaticData() { +} + +// // Extension::RuntimeData // @@ -776,7 +794,7 @@ bool Extension::ContainsNonThemeKeys(const DictionaryValue& source) const { bool Extension::LoadIsApp(const DictionaryValue* manifest, std::string* error) { if (manifest->HasKey(keys::kApp)) - is_app_ = true; + mutable_static_data_->is_app = true; return true; } @@ -864,7 +882,7 @@ bool Extension::LoadLaunchURL(const DictionaryValue* manifest, return false; } - launch_local_path_ = launch_path; + mutable_static_data_->launch_local_path = launch_path; } else if (manifest->Get(keys::kLaunchWebURL, &temp)) { std::string launch_url; if (!temp->GetAsString(&launch_url)) { @@ -878,7 +896,7 @@ bool Extension::LoadLaunchURL(const DictionaryValue* manifest, return false; } - launch_web_url_ = launch_url; + mutable_static_data_->launch_web_url = launch_url; } else if (is_app()) { *error = errors::kLaunchURLRequired; return false; @@ -894,7 +912,7 @@ bool Extension::LoadLaunchURL(const DictionaryValue* manifest, } pattern.set_host(launch_url.host()); pattern.set_path("/*"); - extent_.AddPattern(pattern); + mutable_static_data_->extent.AddPattern(pattern); } // In order for the --apps-gallery-url switch to work with the gallery @@ -904,12 +922,12 @@ bool Extension::LoadLaunchURL(const DictionaryValue* manifest, GURL gallery_url(CommandLine::ForCurrentProcess()-> GetSwitchValueASCII(switches::kAppsGalleryURL)); if (gallery_url.is_valid()) { - launch_web_url_ = gallery_url.spec(); + mutable_static_data_->launch_web_url = gallery_url.spec(); URLPattern pattern(URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS); pattern.Parse(gallery_url.spec()); pattern.set_path(pattern.path() + '*'); - extent_.AddPattern(pattern); + mutable_static_data_->extent.AddPattern(pattern); } } @@ -929,9 +947,9 @@ bool Extension::LoadLaunchContainer(const DictionaryValue* manifest, } if (launch_container_string == values::kLaunchContainerPanel) { - launch_container_ = extension_misc::LAUNCH_PANEL; + mutable_static_data_->launch_container = extension_misc::LAUNCH_PANEL; } else if (launch_container_string == values::kLaunchContainerTab) { - launch_container_ = extension_misc::LAUNCH_TAB; + mutable_static_data_->launch_container = extension_misc::LAUNCH_TAB; } else { *error = errors::kInvalidLaunchContainer; return false; @@ -944,9 +962,9 @@ bool Extension::LoadLaunchContainer(const DictionaryValue* manifest, *error = errors::kInvalidLaunchWidthContainer; return false; } - if (!temp->GetAsInteger(&launch_width_) || - launch_width_ < 0) { - launch_width_ = 0; + if (!temp->GetAsInteger(&mutable_static_data_->launch_width) || + mutable_static_data_->launch_width < 0) { + mutable_static_data_->launch_width = 0; *error = errors::kInvalidLaunchWidth; return false; } @@ -959,8 +977,9 @@ bool Extension::LoadLaunchContainer(const DictionaryValue* manifest, *error = errors::kInvalidLaunchHeightContainer; return false; } - if (!temp->GetAsInteger(&launch_height_) || launch_height_ < 0) { - launch_height_ = 0; + if (!temp->GetAsInteger(&mutable_static_data_->launch_height) || + mutable_static_data_->launch_height < 0) { + mutable_static_data_->launch_height = 0; *error = errors::kInvalidLaunchHeight; return false; } @@ -989,16 +1008,12 @@ bool Extension::EnsureNotHybridApp(const DictionaryValue* manifest, } Extension::Extension(const FilePath& path, Location location) - : incognito_split_mode_(false), - location_(location), - converted_from_user_script_(false), - is_theme_(false), - is_app_(false), - launch_container_(extension_misc::LAUNCH_TAB), - launch_width_(0), - launch_height_(0) { + : mutable_static_data_(new StaticData) { DCHECK(path.IsAbsolute()); - path_ = MaybeNormalizePath(path); + + static_data_ = mutable_static_data_; + mutable_static_data_->location = location; + mutable_static_data_->path = MaybeNormalizePath(path); } Extension::~Extension() { @@ -1196,13 +1211,17 @@ GURL Extension::GetBaseURLFromExtensionId(const std::string& extension_id) { bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, std::string* error) { + // Unit tests reuse Extension objects, so we need to reset mutable_static_data + // when we re-initialize. + mutable_static_data_ = const_cast<StaticData*>(static_data_.get()); + if (source.HasKey(keys::kPublicKey)) { std::string public_key_bytes; if (!source.GetString(keys::kPublicKey, - &public_key_) || - !ParsePEMKeyBytes(public_key_, + &mutable_static_data_->public_key) || + !ParsePEMKeyBytes(mutable_static_data_->public_key, &public_key_bytes) || - !GenerateId(public_key_bytes, &id_)) { + !GenerateId(public_key_bytes, &mutable_static_data_->id)) { *error = errors::kInvalidKey; return false; } @@ -1213,19 +1232,19 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, // If there is a path, we generate the ID from it. This is useful for // development mode, because it keeps the ID stable across restarts and // reloading the extension. - id_ = Extension::GenerateIdForPath(path()); - if (id_.empty()) { + mutable_static_data_->id = Extension::GenerateIdForPath(path()); + if (mutable_static_data_->id.empty()) { NOTREACHED() << "Could not create ID from path."; return false; } } // Make a copy of the manifest so we can store it in prefs. - manifest_value_.reset( + mutable_static_data_->manifest_value.reset( static_cast<DictionaryValue*>(source.DeepCopy())); // Initialize the URL. - extension_url_ = + mutable_static_data_->extension_url = Extension::GetBaseURLFromExtensionId(id()); // Initialize version. @@ -1234,10 +1253,10 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, *error = errors::kInvalidVersion; return false; } - version_.reset( + mutable_static_data_->version.reset( Version::GetVersionFromString(version_str)); - if (!version_.get() || - version_->components().size() > 4) { + if (!mutable_static_data_->version.get() || + mutable_static_data_->version->components().size() > 4) { *error = errors::kInvalidVersion; return false; } @@ -1249,12 +1268,12 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, return false; } base::i18n::AdjustStringForLocaleDirection(localized_name, &localized_name); - name_ = UTF16ToUTF8(localized_name); + mutable_static_data_->name = UTF16ToUTF8(localized_name); // Initialize description (if present). if (source.HasKey(keys::kDescription)) { if (!source.GetString(keys::kDescription, - &description_)) { + &mutable_static_data_->description)) { *error = errors::kInvalidDescription; return false; } @@ -1268,8 +1287,8 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, errors::kInvalidHomepageURL, ""); return false; } - homepage_url_ = GURL(tmp); - if (!homepage_url_.is_valid()) { + mutable_static_data_->homepage_url = GURL(tmp); + if (!mutable_static_data_->homepage_url.is_valid()) { *error = ExtensionErrorUtils::FormatErrorMessage( errors::kInvalidHomepageURL, tmp); return false; @@ -1284,9 +1303,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, errors::kInvalidUpdateURL, ""); return false; } - update_url_ = GURL(tmp); - if (!update_url_.is_valid() || - update_url_.has_ref()) { + mutable_static_data_->update_url = GURL(tmp); + if (!mutable_static_data_->update_url.is_valid() || + mutable_static_data_->update_url.has_ref()) { *error = ExtensionErrorUtils::FormatErrorMessage( errors::kInvalidUpdateURL, tmp); return false; @@ -1334,7 +1353,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, // Initialize converted_from_user_script (if present) source.GetBoolean(keys::kConvertedFromUserScript, - &converted_from_user_script_); + &mutable_static_data_->converted_from_user_script); // Initialize icons (if present). if (source.HasKey(keys::kIcons)) { @@ -1363,13 +1382,13 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, return false; } - icons_.Add(kIconSizes[i], icon_path); + mutable_static_data_->icons.Add(kIconSizes[i], icon_path); } } } // Initialize themes (if present). - is_theme_ = false; + mutable_static_data_->is_theme = false; if (source.HasKey(keys::kTheme)) { // Themes cannot contain extension keys. if (ContainsNonThemeKeys(source)) { @@ -1382,7 +1401,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, *error = errors::kInvalidTheme; return false; } - is_theme_ = true; + mutable_static_data_->is_theme = true; DictionaryValue* images_value; if (theme_value->GetDictionary(keys::kThemeImages, &images_value)) { @@ -1395,7 +1414,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, return false; } } - theme_images_.reset( + mutable_static_data_->theme_images.reset( static_cast<DictionaryValue*>(images_value->DeepCopy())); } @@ -1424,7 +1443,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, return false; } } - theme_colors_.reset( + mutable_static_data_->theme_colors.reset( static_cast<DictionaryValue*>(colors_value->DeepCopy())); } @@ -1445,14 +1464,14 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, return false; } } - theme_tints_.reset( + mutable_static_data_->theme_tints.reset( static_cast<DictionaryValue*>(tints_value->DeepCopy())); } DictionaryValue* display_properties_value; if (theme_value->GetDictionary(keys::kThemeDisplayProperties, &display_properties_value)) { - theme_display_properties_.reset( + mutable_static_data_->theme_display_properties.reset( static_cast<DictionaryValue*>(display_properties_value->DeepCopy())); } @@ -1500,9 +1519,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, } } - plugins_.push_back(PluginInfo()); - plugins_.back().path = path().AppendASCII(path_str); - plugins_.back().is_public = is_public; + mutable_static_data_->plugins.push_back(PluginInfo()); + mutable_static_data_->plugins.back().path = path().AppendASCII(path_str); + mutable_static_data_->plugins.back().is_public = is_public; } } @@ -1513,7 +1532,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, *error = errors::kInvalidBackground; return false; } - background_url_ = GetResourceURL(background_str); + mutable_static_data_->background_url = GetResourceURL(background_str); } // Initialize toolstrips. This is deprecated for public use. @@ -1548,7 +1567,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, errors::kInvalidToolstrip, base::IntToString(i)); return false; } - toolstrips_.push_back(toolstrip); + mutable_static_data_->toolstrips.push_back(toolstrip); } } @@ -1572,11 +1591,11 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, if (!LoadUserScriptHelper(content_script, i, error, &script)) return false; // Failed to parse script context definition. script.set_extension_id(id()); - if (converted_from_user_script_) { + if (mutable_static_data_->converted_from_user_script) { script.set_emulate_greasemonkey(true); script.set_match_all_frames(true); // Greasemonkey matches all frames. } - content_scripts_.push_back(script); + mutable_static_data_->content_scripts.push_back(script); } } @@ -1613,9 +1632,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, // If page_action_value is not NULL, then there was a valid page action. if (page_action_value) { - page_action_.reset( + mutable_static_data_->page_action.reset( LoadExtensionActionHelper(page_action_value, error)); - if (!page_action_.get()) + if (!mutable_static_data_->page_action.get()) return false; // Failed to parse page action definition. } @@ -1627,25 +1646,25 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, return false; } - browser_action_.reset( + mutable_static_data_->browser_action.reset( LoadExtensionActionHelper(browser_action_value, error)); - if (!browser_action_.get()) + if (!mutable_static_data_->browser_action.get()) return false; // Failed to parse browser action definition. } // Load App settings. - if (!LoadIsApp(manifest_value_.get(), error) || - !LoadExtent(manifest_value_.get(), keys::kWebURLs, - &extent_, + if (!LoadIsApp(mutable_static_data_->manifest_value.get(), error) || + !LoadExtent(mutable_static_data_->manifest_value.get(), keys::kWebURLs, + &mutable_static_data_->extent, errors::kInvalidWebURLs, errors::kInvalidWebURL, error) || - !EnsureNotHybridApp(manifest_value_.get(), error) || - !LoadLaunchURL(manifest_value_.get(), error) || - !LoadLaunchContainer(manifest_value_.get(), error)) { + !EnsureNotHybridApp(mutable_static_data_->manifest_value.get(), error) || + !LoadLaunchURL(mutable_static_data_->manifest_value.get(), error) || + !LoadLaunchContainer(mutable_static_data_->manifest_value.get(), error)) { return false; } // Initialize options page url (optional). - // Funtion LoadIsApp() set is_app_ above. + // Funtion LoadIsApp() set mutable_static_data_->is_app above. if (source.HasKey(keys::kOptionsPage)) { std::string options_str; if (!source.GetString(keys::kOptionsPage, &options_str)) { @@ -1661,7 +1680,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, *error = errors::kInvalidOptionsPageInHostedApp; return false; } - options_url_ = options_url; + mutable_static_data_->options_url = options_url; } else { GURL absolute(options_str); @@ -1669,8 +1688,8 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, *error = errors::kInvalidOptionsPageExpectUrlInPackage; return false; } - options_url_ = GetResourceURL(options_str); - if (!options_url_.is_valid()) { + mutable_static_data_->options_url = GetResourceURL(options_str); + if (!mutable_static_data_->options_url.is_valid()) { *error = errors::kInvalidOptionsPage; return false; } @@ -1698,7 +1717,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, // TODO(asargent) - We want a more general purpose mechanism for this, // and better error messages. (http://crbug.com/54013) if (permission_str == kWebstorePrivatePermission && - location_ != Extension::COMPONENT) { + mutable_static_data_->location != Extension::COMPONENT) { continue; } @@ -1709,13 +1728,13 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, if (web_extent().is_empty() || location() == Extension::COMPONENT) { // Check if it's a module permission. If so, enable that permission. if (IsAPIPermission(permission_str)) { - api_permissions_.insert(permission_str); + mutable_static_data_->api_permissions.insert(permission_str); continue; } } else { // Hosted apps only get access to a subset of the valid permissions. if (IsHostedAppPermission(permission_str)) { - api_permissions_.insert(permission_str); + mutable_static_data_->api_permissions.insert(permission_str); continue; } } @@ -1742,14 +1761,14 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, // match all paths. pattern.set_path("/*"); - host_permissions_.push_back(pattern); + mutable_static_data_->host_permissions.push_back(pattern); } } if (source.HasKey(keys::kDefaultLocale)) { if (!source.GetString(keys::kDefaultLocale, - &default_locale_) || - default_locale_.empty()) { + &mutable_static_data_->default_locale) || + mutable_static_data_->default_locale.empty()) { *error = errors::kInvalidDefaultLocale; return false; } @@ -1780,7 +1799,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, return false; } // Replace the entry with a fully qualified chrome-extension:// URL. - chrome_url_overrides_[page] = GetResourceURL(val); + mutable_static_data_->chrome_url_overrides[page] = GetResourceURL(val); } // An extension may override at most one page. @@ -1792,8 +1811,8 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, if (source.HasKey(keys::kOmniboxKeyword)) { if (!source.GetString(keys::kOmniboxKeyword, - &omnibox_keyword_) || - omnibox_keyword_.empty()) { + &mutable_static_data_->omnibox_keyword) || + mutable_static_data_->omnibox_keyword.empty()) { *error = errors::kInvalidOmniboxKeyword; return false; } @@ -1814,12 +1833,12 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, *error = errors::kDevToolsExperimental; return false; } - devtools_url_ = GetResourceURL(devtools_str); + mutable_static_data_->devtools_url = GetResourceURL(devtools_str); } // Initialize incognito behavior. Apps default to split mode, extensions // default to spanning. - incognito_split_mode_ = is_app(); + mutable_static_data_->incognito_split_mode = is_app(); if (source.HasKey(keys::kIncognito)) { std::string value; if (!source.GetString(keys::kIncognito, &value)) { @@ -1827,9 +1846,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, return false; } if (value == values::kIncognitoSpanning) { - incognito_split_mode_ = false; + mutable_static_data_->incognito_split_mode = false; } else if (value == values::kIncognitoSplit) { - incognito_split_mode_ = true; + mutable_static_data_->incognito_split_mode = true; } else { *error = errors::kInvalidIncognitoBehavior; return false; @@ -1848,7 +1867,10 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, // it calls InitFromValue, passing it up to the browser process which calls // InitFromValue again. As a result, we need to make sure that nobody // accidentally modifies it. - DCHECK(source.Equals(manifest_value_.get())); + DCHECK(source.Equals(mutable_static_data_->manifest_value.get())); + + // Ensure we can't modify our static data anymore. + mutable_static_data_ = NULL; return true; } @@ -1865,8 +1887,8 @@ std::string Extension::ChromeStoreLaunchURL() { } GURL Extension::GetHomepageURL() const { - if (homepage_url_.is_valid()) - return homepage_url_; + if (static_data_->homepage_url.is_valid()) + return static_data_->homepage_url; if (update_url()!= GURL(extension_urls::kGalleryUpdateHttpsUrl) && update_url()!= GURL(extension_urls::kGalleryUpdateHttpUrl)) @@ -2091,7 +2113,7 @@ bool Extension::HasHostPermission(const GURL& url) const { void Extension::InitEffectiveHostPermissions() { for (URLPatternList::const_iterator host = host_permissions().begin(); host != host_permissions().end(); ++host) - effective_host_permissions_.AddPattern(*host); + mutable_static_data_->effective_host_permissions.AddPattern(*host); for (UserScriptList::const_iterator content_script = content_scripts().begin(); @@ -2099,7 +2121,7 @@ void Extension::InitEffectiveHostPermissions() { UserScript::PatternList::const_iterator pattern = content_script->url_patterns().begin(); for (; pattern != content_script->url_patterns().end(); ++pattern) - effective_host_permissions_.AddPattern(*pattern); + mutable_static_data_->effective_host_permissions.AddPattern(*pattern); } } diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h index b96eaec..08e4bbb 100644 --- a/chrome/common/extensions/extension.h +++ b/chrome/common/extensions/extension.h @@ -100,6 +100,151 @@ class Extension : public base::RefCountedThreadSafe<Extension> { bool is_public; // False if only this extension can load this plugin. }; + // Contains a subset of the extension's data that doesn't change once + // initialized, and therefore shareable across threads without locking. + struct StaticData : public base::RefCountedThreadSafe<StaticData> { + StaticData(); + + // A persistent, globally unique ID. An extension's ID is used in things + // like directory structures and URLs, and is expected to not change across + // versions. It is generated as a SHA-256 hash of the extension's public + // key, or as a hash of the path in the case of unpacked extensions. + std::string id; + + // The extension's human-readable name. Name is used for display purpose. It + // might be wrapped with unicode bidi control characters so that it is + // displayed correctly in RTL context. + // NOTE: Name is UTF-8 and may contain non-ascii characters. + std::string name; + + // The absolute path to the directory the extension is stored in. + FilePath path; + + // Default locale for fall back. Can be empty if extension is not localized. + std::string default_locale; + + // If true, a separate process will be used for the extension in incognito + // mode. + bool incognito_split_mode; + + // Defines the set of URLs in the extension's web content. + ExtensionExtent extent; + + // The set of host permissions that the extension effectively has access to, + // which is a merge of host_permissions_ and all of the match patterns in + // any content scripts the extension has. This is used to determine which + // URLs have the ability to load an extension's resources via embedded + // chrome-extension: URLs (see extension_protocols.cc). + ExtensionExtent effective_host_permissions; + + // The set of module-level APIs this extension can use. + std::set<std::string> api_permissions; + + // The icons for the extension. + ExtensionIconSet icons; + + // The base extension url for the extension. + GURL extension_url; + + // The location the extension was loaded from. + Location location; + + // The extension's version. + scoped_ptr<Version> version; + + // An optional longer description of the extension. + std::string description; + + // True if the extension was generated from a user script. (We show slightly + // different UI if so). + bool converted_from_user_script; + + // Paths to the content scripts the extension contains. + UserScriptList content_scripts; + + // The extension's page action, if any. + scoped_ptr<ExtensionAction> page_action; + + // The extension's browser action, if any. + scoped_ptr<ExtensionAction> browser_action; + + // Optional list of NPAPI plugins and associated properties. + std::vector<PluginInfo> plugins; + + // Optional URL to a master page of which a single instance should be always + // loaded in the background. + GURL background_url; + + // Optional URL to a page for setting options/preferences. + GURL options_url; + + // Optional URL to a devtools extension page. + GURL devtools_url; + + // Optional list of toolstrips and associated properties. + std::vector<GURL> toolstrips; + + // The public key used to sign the contents of the crx package. + std::string public_key; + + // A map of resource id's to relative file paths. + scoped_ptr<DictionaryValue> theme_images; + + // A map of color names to colors. + scoped_ptr<DictionaryValue> theme_colors; + + // A map of color names to colors. + scoped_ptr<DictionaryValue> theme_tints; + + // A map of display properties. + scoped_ptr<DictionaryValue> theme_display_properties; + + // Whether the extension is a theme. + bool is_theme; + + // The sites this extension has permission to talk to (using XHR, etc). + URLPatternList host_permissions; + + // The homepage for this extension. Useful if it is not hosted by Google and + // therefore does not have a Gallery URL. + GURL homepage_url; + + // URL for fetching an update manifest + GURL update_url; + + // A copy of the manifest that this extension was created from. + scoped_ptr<DictionaryValue> manifest_value; + + // A map of chrome:// hostnames (newtab, downloads, etc.) to Extension URLs + // which override the handling of those URLs. + URLOverrideMap chrome_url_overrides; + + // Whether this extension uses app features. + bool is_app; + + // The local path inside the extension to use with the launcher. + std::string launch_local_path; + + // A web url to use with the launcher. Note that this might be relative or + // absolute. If relative, it is relative to web_origin. + std::string launch_web_url; + + // The type of container to launch into. + extension_misc::LaunchContainer launch_container; + + // The default size of the container when launching. Only respected for + // containers like panels and windows. + int launch_width; + int launch_height; + + // The Omnibox keyword for this extension, or empty if there is none. + std::string omnibox_keyword; + + protected: + friend class base::RefCountedThreadSafe<StaticData>; + ~StaticData(); + }; + // Contains the subset of the extension's (private) data that can be modified // after initialization. This class should only be accessed on the UI thread. struct RuntimeData { @@ -319,6 +464,46 @@ class Extension : public base::RefCountedThreadSafe<Extension> { // Adds an extension to the scripting whitelist. Used for testing only. static void SetScriptingWhitelist(const ScriptingWhitelist& whitelist); + const StaticData* static_data() const { return static_data_; } + + const FilePath& path() const { return static_data_->path; } + const GURL& url() const { return static_data_->extension_url; } + Location location() const { return static_data_->location; } + const std::string& id() const { return static_data_->id; } + const Version* version() const { return static_data_->version.get(); } + // String representation of the version number. + const std::string VersionString() const; + const std::string& name() const { return static_data_->name; } + const std::string& public_key() const { return static_data_->public_key; } + const std::string& description() const { return static_data_->description; } + bool converted_from_user_script() const { + return static_data_->converted_from_user_script; + } + const UserScriptList& content_scripts() const { + return static_data_->content_scripts; + } + ExtensionAction* page_action() const { + return static_data_->page_action.get(); + } + ExtensionAction* browser_action() const { + return static_data_->browser_action.get(); + } + const std::vector<PluginInfo>& plugins() const { + return static_data_->plugins; + } + const GURL& background_url() const { return static_data_->background_url; } + const GURL& options_url() const { return static_data_->options_url; } + const GURL& devtools_url() const { return static_data_->devtools_url; } + const std::vector<GURL>& toolstrips() const { + return static_data_->toolstrips; + } + const std::set<std::string>& api_permissions() const { + return static_data_->api_permissions; + } + const URLPatternList& host_permissions() const { + return static_data_->host_permissions; + } + // Returns true if the extension has the specified API permission. static bool HasApiPermission(const std::set<std::string>& api_permissions, const std::string& function_name); @@ -328,7 +513,7 @@ class Extension : public base::RefCountedThreadSafe<Extension> { } const ExtensionExtent& GetEffectiveHostPermissions() const { - return effective_host_permissions_; + return static_data_->effective_host_permissions; } // Whether or not the extension is allowed permission for a URL pattern from @@ -347,11 +532,32 @@ class Extension : public base::RefCountedThreadSafe<Extension> { // network, etc.) bool HasEffectiveAccessToAllHosts() const; + const GURL& update_url() const { return static_data_->update_url; } + + const ExtensionIconSet& icons() const { + return static_data_->icons; + } + // Returns the Homepage URL for this extension. If homepage_url was not // specified in the manifest, this returns the Google Gallery URL. For // third-party extensions, this returns a blank GURL. GURL GetHomepageURL() const; + // Theme-related. + DictionaryValue* GetThemeImages() const { + return static_data_->theme_images.get(); + } + DictionaryValue* GetThemeColors() const { + return static_data_->theme_colors.get(); + } + DictionaryValue* GetThemeTints() const { + return static_data_->theme_tints.get(); + } + DictionaryValue* GetThemeDisplayProperties() const { + return static_data_->theme_display_properties.get(); + } + bool is_theme() const { return static_data_->is_theme; } + // Returns a list of paths (relative to the extension dir) for images that // the browser might load (like themes and page action icons). std::set<FilePath> GetBrowserImages() const; @@ -361,85 +567,45 @@ class Extension : public base::RefCountedThreadSafe<Extension> { int size, ExtensionIconSet::MatchType match_type) const; GURL GetIconURL(int size, ExtensionIconSet::MatchType match_type) const; + const DictionaryValue* manifest_value() const { + return static_data_->manifest_value.get(); + } - // Gets the fully resolved absolute launch URL. - GURL GetFullLaunchURL() const; - - // Image cache related methods. These are only valid on the UI thread and - // not maintained by this class. See ImageLoadingTracker for usage. The - // |original_size| parameter should be the size of the image at |source| - // before any scaling may have been done to produce the pixels in |image|. - void SetCachedImage(const ExtensionResource& source, - const SkBitmap& image, - const gfx::Size& original_size) const; - bool HasCachedImage(const ExtensionResource& source, - const gfx::Size& max_size) const; - SkBitmap GetCachedImage(const ExtensionResource& source, - const gfx::Size& max_size) const; - // Returns true if this extension is a COMPONENT extension, or if it is - // on the whitelist of extensions that can script all pages. - bool CanExecuteScriptEverywhere() const; + const std::string default_locale() const { + return static_data_->default_locale; + } - // Accessors: + // Chrome URL overrides (see ExtensionOverrideUI). + const URLOverrideMap& GetChromeURLOverrides() const { + return static_data_->chrome_url_overrides; + } - const FilePath& path() const { return path_; } - const GURL& url() const { return extension_url_; } - Location location() const { return location_; } - const std::string& id() const { return id_; } - const Version* version() const { return version_.get(); } - const std::string VersionString() const; - const std::string& name() const { return name_; } - const std::string& public_key() const { return public_key_; } - const std::string& description() const { return description_; } - bool converted_from_user_script() const { - return converted_from_user_script_; + const std::string omnibox_keyword() const { + return static_data_->omnibox_keyword; } - const UserScriptList& content_scripts() const { return content_scripts_; } - ExtensionAction* page_action() const { return page_action_.get(); } - ExtensionAction* browser_action() const { return browser_action_.get(); } - const std::vector<PluginInfo>& plugins() const { return plugins_; } - const GURL& background_url() const { return background_url_; } - const GURL& options_url() const { return options_url_; } - const GURL& devtools_url() const { return devtools_url_; } - const std::vector<GURL>& toolstrips() const { return toolstrips_; } - const std::set<std::string>& api_permissions() const { - return api_permissions_; + + bool is_app() const { return static_data_->is_app; } + const ExtensionExtent& web_extent() const { + return static_data_->extent; } - const URLPatternList& host_permissions() const { return host_permissions_; } - const GURL& update_url() const { return update_url_; } - const ExtensionIconSet& icons() const { return icons_; } - const DictionaryValue* manifest_value() const { - return manifest_value_.get(); + const std::string& launch_local_path() const { + return static_data_->launch_local_path; } - const std::string default_locale() const { return default_locale_; } - const URLOverrideMap& GetChromeURLOverrides() const { - return chrome_url_overrides_; + const std::string& launch_web_url() const { + return static_data_->launch_web_url; } - const std::string omnibox_keyword() const { return omnibox_keyword_; } - bool incognito_split_mode() const { return incognito_split_mode_; } - - // App-related. - bool is_app() const { return is_app_; } - bool is_hosted_app() const { return is_app() && !web_extent().is_empty(); } - bool is_packaged_app() const { return is_app() && web_extent().is_empty(); } - const ExtensionExtent& web_extent() const { return extent_; } - const std::string& launch_local_path() const { return launch_local_path_; } - const std::string& launch_web_url() const { return launch_web_url_; } extension_misc::LaunchContainer launch_container() const { - return launch_container_; + return static_data_->launch_container; } - int launch_width() const { return launch_width_; } - int launch_height() const { return launch_height_; } - - // Theme-related. - bool is_theme() const { return is_theme_; } - DictionaryValue* GetThemeImages() const { return theme_images_.get(); } - DictionaryValue* GetThemeColors() const {return theme_colors_.get(); } - DictionaryValue* GetThemeTints() const { return theme_tints_.get(); } - DictionaryValue* GetThemeDisplayProperties() const { - return theme_display_properties_.get(); + int launch_width() const { return static_data_->launch_width; } + int launch_height() const { return static_data_->launch_height; } + bool incognito_split_mode() const { + return static_data_->incognito_split_mode; } + // Gets the fully resolved absolute launch URL. + GURL GetFullLaunchURL() const; + // Whether the background page, if any, is ready. We don't load other // components until then. If there is no background page, we consider it to // be ready. @@ -453,6 +619,24 @@ class Extension : public base::RefCountedThreadSafe<Extension> { GetRuntimeData()->being_upgraded = value; } + // Image cache related methods. These are only valid on the UI thread and + // not maintained by this class. See ImageLoadingTracker for usage. The + // |original_size| parameter should be the size of the image at |source| + // before any scaling may have been done to produce the pixels in |image|. + void SetCachedImage(const ExtensionResource& source, + const SkBitmap& image, + const gfx::Size& original_size) const; + bool HasCachedImage(const ExtensionResource& source, + const gfx::Size& max_size) const; + SkBitmap GetCachedImage(const ExtensionResource& source, + const gfx::Size& max_size) const; + bool is_hosted_app() const { return is_app() && !web_extent().is_empty(); } + bool is_packaged_app() const { return is_app() && web_extent().is_empty(); } + + // Returns true if this extension is a COMPONENT extension, or if it is + // on the whitelist of extensions that can script all pages. + bool CanExecuteScriptEverywhere() const; + private: friend class base::RefCountedThreadSafe<Extension>; @@ -536,144 +720,16 @@ class Extension : public base::RefCountedThreadSafe<Extension> { // the UI thread. RuntimeData* GetRuntimeData() const; + // Collection of extension data that doesn't change doesn't change once an + // Extension object has been initialized. The mutable version is valid only + // until InitFromValue finishes, to ensure we don't accidentally modify it + // post-initialization. + StaticData* mutable_static_data_; + scoped_refptr<const StaticData> static_data_; + // Runtime data. const RuntimeData runtime_data_; - // A persistent, globally unique ID. An extension's ID is used in things - // like directory structures and URLs, and is expected to not change across - // versions. It is generated as a SHA-256 hash of the extension's public - // key, or as a hash of the path in the case of unpacked extensions. - std::string id_; - - // The extension's human-readable name. Name is used for display purpose. It - // might be wrapped with unicode bidi control characters so that it is - // displayed correctly in RTL context. - // NOTE: Name is UTF-8 and may contain non-ascii characters. - std::string name_; - - // The absolute path to the directory the extension is stored in. - FilePath path_; - - // Default locale for fall back. Can be empty if extension is not localized. - std::string default_locale_; - - // If true, a separate process will be used for the extension in incognito - // mode. - bool incognito_split_mode_; - - // Defines the set of URLs in the extension's web content. - ExtensionExtent extent_; - - // The set of host permissions that the extension effectively has access to, - // which is a merge of host_permissions_ and all of the match patterns in - // any content scripts the extension has. This is used to determine which - // URLs have the ability to load an extension's resources via embedded - // chrome-extension: URLs (see extension_protocols.cc). - ExtensionExtent effective_host_permissions_; - - // The set of module-level APIs this extension can use. - std::set<std::string> api_permissions_; - - // The icons for the extension. - ExtensionIconSet icons_; - - // The base extension url for the extension. - GURL extension_url_; - - // The location the extension was loaded from. - Location location_; - - // The extension's version. - scoped_ptr<Version> version_; - - // An optional longer description of the extension. - std::string description_; - - // True if the extension was generated from a user script. (We show slightly - // different UI if so). - bool converted_from_user_script_; - - // Paths to the content scripts the extension contains. - UserScriptList content_scripts_; - - // The extension's page action, if any. - scoped_ptr<ExtensionAction> page_action_; - - // The extension's browser action, if any. - scoped_ptr<ExtensionAction> browser_action_; - - // Optional list of NPAPI plugins and associated properties. - std::vector<PluginInfo> plugins_; - - // Optional URL to a master page of which a single instance should be always - // loaded in the background. - GURL background_url_; - - // Optional URL to a page for setting options/preferences. - GURL options_url_; - - // Optional URL to a devtools extension page. - GURL devtools_url_; - - // Optional list of toolstrips and associated properties. - std::vector<GURL> toolstrips_; - - // The public key used to sign the contents of the crx package. - std::string public_key_; - - // A map of resource id's to relative file paths. - scoped_ptr<DictionaryValue> theme_images_; - - // A map of color names to colors. - scoped_ptr<DictionaryValue> theme_colors_; - - // A map of color names to colors. - scoped_ptr<DictionaryValue> theme_tints_; - - // A map of display properties. - scoped_ptr<DictionaryValue> theme_display_properties_; - - // Whether the extension is a theme. - bool is_theme_; - - // The sites this extension has permission to talk to (using XHR, etc). - URLPatternList host_permissions_; - - // The homepage for this extension. Useful if it is not hosted by Google and - // therefore does not have a Gallery URL. - GURL homepage_url_; - - // URL for fetching an update manifest - GURL update_url_; - - // A copy of the manifest that this extension was created from. - scoped_ptr<DictionaryValue> manifest_value_; - - // A map of chrome:// hostnames (newtab, downloads, etc.) to Extension URLs - // which override the handling of those URLs. (see ExtensionOverrideUI). - URLOverrideMap chrome_url_overrides_; - - // Whether this extension uses app features. - bool is_app_; - - // The local path inside the extension to use with the launcher. - std::string launch_local_path_; - - // A web url to use with the launcher. Note that this might be relative or - // absolute. If relative, it is relative to web_origin. - std::string launch_web_url_; - - // The type of container to launch into. - extension_misc::LaunchContainer launch_container_; - - // The default size of the container when launching. Only respected for - // containers like panels and windows. - int launch_width_; - int launch_height_; - - // The Omnibox keyword for this extension, or empty if there is none. - std::string omnibox_keyword_; - FRIEND_TEST_ALL_PREFIXES(ExtensionTest, LoadPageActionHelper); FRIEND_TEST_ALL_PREFIXES(ExtensionTest, InitFromValueInvalid); FRIEND_TEST_ALL_PREFIXES(ExtensionTest, InitFromValueValid); diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc index 3f86bbd..9aec5fe 100644 --- a/chrome/common/extensions/extension_unittest.cc +++ b/chrome/common/extensions/extension_unittest.cc @@ -549,7 +549,7 @@ TEST(ExtensionTest, LoadPageActionHelper) { // LoadExtensionActionHelper expects the extension member |extension_url| // to be set. - extension.extension_url_ = + extension.mutable_static_data_->extension_url = GURL(std::string(chrome::kExtensionScheme) + chrome::kStandardSchemeSeparator + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/"); |