1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tabs/pinned_tab_codec.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/values.h" 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_tab_helper.h" 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h" 1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tabs/tab_strip_model.h" 124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h" 1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h" 17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/page_transition_types.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef BrowserInit::LaunchWithProfile::Tab Tab; 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Key used in dictionaries for the app id. 233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic const char kAppID[] = "app_id"; 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Key used in dictionaries for the url. 263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic const char kURL[] = "url"; 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns true if |browser| has any pinned tabs. 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool HasPinnedTabs(Browser* browser) { 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* tab_model = browser->tabstrip_model(); 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < tab_model->count(); ++i) { 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_model->IsTabPinned(i)) 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Adds a DictionaryValue to |values| representing the pinned tab at the 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// specified index. 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void EncodePinnedTab(TabStripModel* model, 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index, 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue* values) { 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<DictionaryValue> value(new DictionaryValue()); 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 45201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* tab_contents = model->GetTabContentsAt(index); 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (model->IsAppTab(index)) { 47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const Extension* extension = 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_contents->extension_tab_helper()->extension_app(); 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(extension); 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch value->SetString(kAppID, extension->id()); 51731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // For apps we use the launch url. We do this for the following reason: 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // . the user is effectively restarting the app, so that returning them to 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the app's launch page seems closest to what they expect. 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch value->SetString(kURL, extension->GetFullLaunchURL().spec()); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch values->Append(value.release()); 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationEntry* entry = tab_contents->controller().GetActiveEntry(); 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!entry && tab_contents->controller().entry_count()) 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry = tab_contents->controller().GetEntryAtIndex(0); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry) { 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch value->SetString(kURL, entry->url().spec()); 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch values->Append(value.release()); 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Invokes EncodePinnedTab for each pinned tab in browser. 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void EncodePinnedTabs(Browser* browser, ListValue* values) { 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* tab_model = browser->tabstrip_model(); 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < tab_model->count() && tab_model->IsTabPinned(i); ++i) 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EncodePinnedTab(tab_model, i, values); 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Decodes the previously written values in |value| to |tab|, returning true 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// on success. 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool DecodeTab(const DictionaryValue& value, Tab* tab) { 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->is_app = false; 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string url_string; 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!value.GetString(kURL, &url_string)) 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->url = GURL(url_string); 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (value.GetString(kAppID, &(tab->app_id))) 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->is_app = true; 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PinnedTabCodec::RegisterUserPrefs(PrefService* prefs) { 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->RegisterListPref(prefs::kPinnedTabs); 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PinnedTabCodec::WritePinnedTabs(Profile* profile) { 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* prefs = profile->GetPrefs(); 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!prefs) 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue values; 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (BrowserList::const_iterator i = BrowserList::begin(); 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != BrowserList::end(); ++i) { 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = *i; 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (browser->type() == Browser::TYPE_NORMAL && 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->profile() == profile && HasPinnedTabs(browser)) { 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EncodePinnedTabs(browser, &values); 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->Set(prefs::kPinnedTabs, values); 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->ScheduleSavePersistentPrefs(); 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::vector<Tab> PinnedTabCodec::ReadPinnedTabs(Profile* profile) { 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<Tab> results; 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* prefs = profile->GetPrefs(); 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!prefs) 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return results; 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ListValue* pref_value = prefs->GetList(prefs::kPinnedTabs); 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!pref_value) 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return results; 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0, max = pref_value->GetSize(); i < max; ++i) { 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* values = NULL; 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (pref_value->GetDictionary(i, &values)) { 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Tab tab; 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (DecodeTab(*values, &tab)) 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch results.push_back(tab); 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return results; 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 136