OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/api/bookmarks/bookmarks_api.h" | 5 #include "chrome/browser/extensions/api/bookmarks/bookmarks_api.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
9 #include "base/i18n/file_util_icu.h" | 9 #include "base/i18n/file_util_icu.h" |
10 #include "base/i18n/time_formatting.h" | 10 #include "base/i18n/time_formatting.h" |
(...skipping 21 matching lines...) Expand all Loading... |
32 #include "chrome/browser/importer/importer_uma.h" | 32 #include "chrome/browser/importer/importer_uma.h" |
33 #include "chrome/browser/platform_util.h" | 33 #include "chrome/browser/platform_util.h" |
34 #include "chrome/browser/profiles/profile.h" | 34 #include "chrome/browser/profiles/profile.h" |
35 #include "chrome/browser/ui/chrome_select_file_policy.h" | 35 #include "chrome/browser/ui/chrome_select_file_policy.h" |
36 #include "chrome/browser/ui/host_desktop.h" | 36 #include "chrome/browser/ui/host_desktop.h" |
37 #include "chrome/common/chrome_paths.h" | 37 #include "chrome/common/chrome_paths.h" |
38 #include "chrome/common/extensions/api/bookmarks.h" | 38 #include "chrome/common/extensions/api/bookmarks.h" |
39 #include "chrome/common/importer/importer_data_types.h" | 39 #include "chrome/common/importer/importer_data_types.h" |
40 #include "chrome/common/pref_names.h" | 40 #include "chrome/common/pref_names.h" |
41 #include "components/user_prefs/user_prefs.h" | 41 #include "components/user_prefs/user_prefs.h" |
| 42 #include "content/public/browser/browser_context.h" |
42 #include "content/public/browser/notification_service.h" | 43 #include "content/public/browser/notification_service.h" |
43 #include "content/public/browser/web_contents.h" | 44 #include "content/public/browser/web_contents.h" |
44 #include "content/public/browser/web_contents_view.h" | 45 #include "content/public/browser/web_contents_view.h" |
45 #include "extensions/browser/event_router.h" | 46 #include "extensions/browser/event_router.h" |
46 #include "extensions/browser/extension_system.h" | 47 #include "extensions/browser/extension_system.h" |
47 #include "extensions/browser/quota_service.h" | 48 #include "extensions/browser/quota_service.h" |
48 #include "grit/generated_resources.h" | 49 #include "grit/generated_resources.h" |
49 #include "ui/base/l10n/l10n_util.h" | 50 #include "ui/base/l10n/l10n_util.h" |
50 | 51 |
51 #if defined(OS_WIN) | 52 #if defined(OS_WIN) |
52 #include "ui/aura/remote_window_tree_host_win.h" | 53 #include "ui/aura/remote_window_tree_host_win.h" |
53 #endif | 54 #endif |
54 | 55 |
55 namespace extensions { | 56 namespace extensions { |
56 | 57 |
57 namespace keys = bookmark_api_constants; | 58 namespace keys = bookmark_api_constants; |
58 namespace bookmarks = api::bookmarks; | 59 namespace bookmarks = api::bookmarks; |
59 | 60 |
60 using base::TimeDelta; | 61 using base::TimeDelta; |
61 using bookmarks::BookmarkTreeNode; | 62 using bookmarks::BookmarkTreeNode; |
| 63 using content::BrowserContext; |
62 using content::BrowserThread; | 64 using content::BrowserThread; |
63 using content::WebContents; | 65 using content::WebContents; |
64 | 66 |
65 typedef QuotaLimitHeuristic::Bucket Bucket; | 67 typedef QuotaLimitHeuristic::Bucket Bucket; |
66 typedef QuotaLimitHeuristic::Config Config; | 68 typedef QuotaLimitHeuristic::Config Config; |
67 typedef QuotaLimitHeuristic::BucketList BucketList; | 69 typedef QuotaLimitHeuristic::BucketList BucketList; |
68 typedef QuotaService::TimedLimit TimedLimit; | 70 typedef QuotaService::TimedLimit TimedLimit; |
69 typedef QuotaService::SustainedLimit SustainedLimit; | 71 typedef QuotaService::SustainedLimit SustainedLimit; |
70 typedef QuotaLimitHeuristic::BucketMapper BucketMapper; | 72 typedef QuotaLimitHeuristic::BucketMapper BucketMapper; |
71 | 73 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 void BookmarksFunction::BookmarkModelChanged() { | 151 void BookmarksFunction::BookmarkModelChanged() { |
150 } | 152 } |
151 | 153 |
152 void BookmarksFunction::BookmarkModelLoaded(BookmarkModel* model, | 154 void BookmarksFunction::BookmarkModelLoaded(BookmarkModel* model, |
153 bool ids_reassigned) { | 155 bool ids_reassigned) { |
154 model->RemoveObserver(this); | 156 model->RemoveObserver(this); |
155 Run(); | 157 Run(); |
156 Release(); // Balanced in Run(). | 158 Release(); // Balanced in Run(). |
157 } | 159 } |
158 | 160 |
159 BookmarkEventRouter::BookmarkEventRouter(Profile* profile, BookmarkModel* model) | 161 BookmarkEventRouter::BookmarkEventRouter(BrowserContext* context, |
160 : profile_(profile), | 162 BookmarkModel* model) |
161 model_(model) { | 163 : browser_context_(context), model_(model) { |
162 model_->AddObserver(this); | 164 model_->AddObserver(this); |
163 } | 165 } |
164 | 166 |
165 BookmarkEventRouter::~BookmarkEventRouter() { | 167 BookmarkEventRouter::~BookmarkEventRouter() { |
166 if (model_) { | 168 if (model_) { |
167 model_->RemoveObserver(this); | 169 model_->RemoveObserver(this); |
168 } | 170 } |
169 } | 171 } |
170 | 172 |
171 void BookmarkEventRouter::DispatchEvent( | 173 void BookmarkEventRouter::DispatchEvent( |
172 const std::string& event_name, | 174 const std::string& event_name, |
173 scoped_ptr<base::ListValue> event_args) { | 175 scoped_ptr<base::ListValue> event_args) { |
174 if (extensions::ExtensionSystem::Get(profile_)->event_router()) { | 176 if (extensions::ExtensionSystem::Get(browser_context_)->event_router()) { |
175 extensions::ExtensionSystem::Get(profile_)->event_router()->BroadcastEvent( | 177 extensions::ExtensionSystem::Get(browser_context_) |
176 make_scoped_ptr(new extensions::Event(event_name, event_args.Pass()))); | 178 ->event_router() |
| 179 ->BroadcastEvent(make_scoped_ptr( |
| 180 new extensions::Event(event_name, event_args.Pass()))); |
177 } | 181 } |
178 } | 182 } |
179 | 183 |
180 void BookmarkEventRouter::BookmarkModelLoaded(BookmarkModel* model, | 184 void BookmarkEventRouter::BookmarkModelLoaded(BookmarkModel* model, |
181 bool ids_reassigned) { | 185 bool ids_reassigned) { |
182 // TODO(erikkay): Perhaps we should send this event down to the extension | 186 // TODO(erikkay): Perhaps we should send this event down to the extension |
183 // so they know when it's safe to use the API? | 187 // so they know when it's safe to use the API? |
184 } | 188 } |
185 | 189 |
186 void BookmarkEventRouter::BookmarkModelBeingDeleted(BookmarkModel* model) { | 190 void BookmarkEventRouter::BookmarkModelBeingDeleted(BookmarkModel* model) { |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 BookmarkModel* model) { | 294 BookmarkModel* model) { |
291 scoped_ptr<base::ListValue> args(new base::ListValue()); | 295 scoped_ptr<base::ListValue> args(new base::ListValue()); |
292 DispatchEvent(bookmarks::OnImportBegan::kEventName, args.Pass()); | 296 DispatchEvent(bookmarks::OnImportBegan::kEventName, args.Pass()); |
293 } | 297 } |
294 | 298 |
295 void BookmarkEventRouter::ExtensiveBookmarkChangesEnded(BookmarkModel* model) { | 299 void BookmarkEventRouter::ExtensiveBookmarkChangesEnded(BookmarkModel* model) { |
296 scoped_ptr<base::ListValue> args(new base::ListValue()); | 300 scoped_ptr<base::ListValue> args(new base::ListValue()); |
297 DispatchEvent(bookmarks::OnImportEnded::kEventName, args.Pass()); | 301 DispatchEvent(bookmarks::OnImportEnded::kEventName, args.Pass()); |
298 } | 302 } |
299 | 303 |
300 BookmarksAPI::BookmarksAPI(Profile* profile) : profile_(profile) { | 304 BookmarksAPI::BookmarksAPI(BrowserContext* context) |
301 ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( | 305 : browser_context_(context) { |
302 this, bookmarks::OnCreated::kEventName); | 306 EventRouter* event_router = |
303 ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( | 307 ExtensionSystem::Get(browser_context_)->event_router(); |
304 this, bookmarks::OnRemoved::kEventName); | 308 event_router->RegisterObserver(this, bookmarks::OnCreated::kEventName); |
305 ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( | 309 event_router->RegisterObserver(this, bookmarks::OnRemoved::kEventName); |
306 this, bookmarks::OnChanged::kEventName); | 310 event_router->RegisterObserver(this, bookmarks::OnChanged::kEventName); |
307 ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( | 311 event_router->RegisterObserver(this, bookmarks::OnMoved::kEventName); |
308 this, bookmarks::OnMoved::kEventName); | 312 event_router->RegisterObserver(this, |
309 ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( | 313 bookmarks::OnChildrenReordered::kEventName); |
310 this, bookmarks::OnChildrenReordered::kEventName); | 314 event_router->RegisterObserver(this, bookmarks::OnImportBegan::kEventName); |
311 ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( | 315 event_router->RegisterObserver(this, bookmarks::OnImportEnded::kEventName); |
312 this, bookmarks::OnImportBegan::kEventName); | |
313 ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( | |
314 this, bookmarks::OnImportEnded::kEventName); | |
315 } | 316 } |
316 | 317 |
317 BookmarksAPI::~BookmarksAPI() { | 318 BookmarksAPI::~BookmarksAPI() { |
318 } | 319 } |
319 | 320 |
320 void BookmarksAPI::Shutdown() { | 321 void BookmarksAPI::Shutdown() { |
321 ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this); | 322 ExtensionSystem::Get(browser_context_)->event_router()->UnregisterObserver( |
| 323 this); |
322 } | 324 } |
323 | 325 |
324 static base::LazyInstance<ProfileKeyedAPIFactory<BookmarksAPI> > | 326 static base::LazyInstance<ProfileKeyedAPIFactory<BookmarksAPI> > |
325 g_factory = LAZY_INSTANCE_INITIALIZER; | 327 g_factory = LAZY_INSTANCE_INITIALIZER; |
326 | 328 |
327 // static | 329 // static |
328 ProfileKeyedAPIFactory<BookmarksAPI>* BookmarksAPI::GetFactoryInstance() { | 330 ProfileKeyedAPIFactory<BookmarksAPI>* BookmarksAPI::GetFactoryInstance() { |
329 return g_factory.Pointer(); | 331 return g_factory.Pointer(); |
330 } | 332 } |
331 | 333 |
332 void BookmarksAPI::OnListenerAdded(const EventListenerInfo& details) { | 334 void BookmarksAPI::OnListenerAdded(const EventListenerInfo& details) { |
333 bookmark_event_router_.reset(new BookmarkEventRouter(profile_, | 335 bookmark_event_router_.reset(new BookmarkEventRouter( |
334 BookmarkModelFactory::GetForProfile(profile_))); | 336 browser_context_, |
335 ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this); | 337 BookmarkModelFactory::GetForProfile( |
| 338 Profile::FromBrowserContext(browser_context_)))); |
| 339 ExtensionSystem::Get(browser_context_)->event_router()->UnregisterObserver( |
| 340 this); |
336 } | 341 } |
337 | 342 |
338 bool BookmarksGetFunction::RunImpl() { | 343 bool BookmarksGetFunction::RunImpl() { |
339 scoped_ptr<bookmarks::Get::Params> params( | 344 scoped_ptr<bookmarks::Get::Params> params( |
340 bookmarks::Get::Params::Create(*args_)); | 345 bookmarks::Get::Params::Create(*args_)); |
341 EXTENSION_FUNCTION_VALIDATE(params.get()); | 346 EXTENSION_FUNCTION_VALIDATE(params.get()); |
342 | 347 |
343 std::vector<linked_ptr<BookmarkTreeNode> > nodes; | 348 std::vector<linked_ptr<BookmarkTreeNode> > nodes; |
344 if (params->id_or_id_list.as_strings) { | 349 if (params->id_or_id_list.as_strings) { |
345 std::vector<std::string>& ids = *params->id_or_id_list.as_strings; | 350 std::vector<std::string>& ids = *params->id_or_id_list.as_strings; |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 return b; | 730 return b; |
726 } | 731 } |
727 private: | 732 private: |
728 std::map<BucketIdType, Bucket*> buckets_; | 733 std::map<BucketIdType, Bucket*> buckets_; |
729 }; | 734 }; |
730 | 735 |
731 // Mapper for 'bookmarks.create'. Maps "same input to bookmarks.create" to a | 736 // Mapper for 'bookmarks.create'. Maps "same input to bookmarks.create" to a |
732 // unique bucket. | 737 // unique bucket. |
733 class CreateBookmarkBucketMapper : public BookmarkBucketMapper<std::string> { | 738 class CreateBookmarkBucketMapper : public BookmarkBucketMapper<std::string> { |
734 public: | 739 public: |
735 explicit CreateBookmarkBucketMapper(Profile* profile) : profile_(profile) {} | 740 explicit CreateBookmarkBucketMapper(BrowserContext* context) |
| 741 : browser_context_(context) {} |
736 // TODO(tim): This should share code with BookmarksCreateFunction::RunImpl, | 742 // TODO(tim): This should share code with BookmarksCreateFunction::RunImpl, |
737 // but I can't figure out a good way to do that with all the macros. | 743 // but I can't figure out a good way to do that with all the macros. |
738 virtual void GetBucketsForArgs(const base::ListValue* args, | 744 virtual void GetBucketsForArgs(const base::ListValue* args, |
739 BucketList* buckets) OVERRIDE { | 745 BucketList* buckets) OVERRIDE { |
740 const base::DictionaryValue* json; | 746 const base::DictionaryValue* json; |
741 if (!args->GetDictionary(0, &json)) | 747 if (!args->GetDictionary(0, &json)) |
742 return; | 748 return; |
743 | 749 |
744 std::string parent_id; | 750 std::string parent_id; |
745 if (json->HasKey(keys::kParentIdKey)) { | 751 if (json->HasKey(keys::kParentIdKey)) { |
746 if (!json->GetString(keys::kParentIdKey, &parent_id)) | 752 if (!json->GetString(keys::kParentIdKey, &parent_id)) |
747 return; | 753 return; |
748 } | 754 } |
749 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile_); | 755 BookmarkModel* model = BookmarkModelFactory::GetForProfile( |
| 756 Profile::FromBrowserContext(browser_context_)); |
750 | 757 |
751 int64 parent_id_int64; | 758 int64 parent_id_int64; |
752 base::StringToInt64(parent_id, &parent_id_int64); | 759 base::StringToInt64(parent_id, &parent_id_int64); |
753 const BookmarkNode* parent = model->GetNodeByID(parent_id_int64); | 760 const BookmarkNode* parent = model->GetNodeByID(parent_id_int64); |
754 if (!parent) | 761 if (!parent) |
755 return; | 762 return; |
756 | 763 |
757 std::string bucket_id = base::UTF16ToUTF8(parent->GetTitle()); | 764 std::string bucket_id = base::UTF16ToUTF8(parent->GetTitle()); |
758 std::string title; | 765 std::string title; |
759 json->GetString(keys::kTitleKey, &title); | 766 json->GetString(keys::kTitleKey, &title); |
760 std::string url_string; | 767 std::string url_string; |
761 json->GetString(keys::kUrlKey, &url_string); | 768 json->GetString(keys::kUrlKey, &url_string); |
762 | 769 |
763 bucket_id += title; | 770 bucket_id += title; |
764 bucket_id += url_string; | 771 bucket_id += url_string; |
765 // 20 bytes (SHA1 hash length) is very likely less than most of the | 772 // 20 bytes (SHA1 hash length) is very likely less than most of the |
766 // |bucket_id| strings we construct here, so we hash it to save space. | 773 // |bucket_id| strings we construct here, so we hash it to save space. |
767 buckets->push_back(GetBucket(base::SHA1HashString(bucket_id))); | 774 buckets->push_back(GetBucket(base::SHA1HashString(bucket_id))); |
768 } | 775 } |
769 private: | 776 private: |
770 Profile* profile_; | 777 BrowserContext* browser_context_; |
771 }; | 778 }; |
772 | 779 |
773 // Mapper for 'bookmarks.remove'. | 780 // Mapper for 'bookmarks.remove'. |
774 class RemoveBookmarksBucketMapper : public BookmarkBucketMapper<std::string> { | 781 class RemoveBookmarksBucketMapper : public BookmarkBucketMapper<std::string> { |
775 public: | 782 public: |
776 explicit RemoveBookmarksBucketMapper(Profile* profile) : profile_(profile) {} | 783 explicit RemoveBookmarksBucketMapper(BrowserContext* context) |
| 784 : browser_context_(context) {} |
777 virtual void GetBucketsForArgs(const base::ListValue* args, | 785 virtual void GetBucketsForArgs(const base::ListValue* args, |
778 BucketList* buckets) OVERRIDE { | 786 BucketList* buckets) OVERRIDE { |
779 typedef std::list<int64> IdList; | 787 typedef std::list<int64> IdList; |
780 IdList ids; | 788 IdList ids; |
781 bool invalid_id = false; | 789 bool invalid_id = false; |
782 if (!BookmarksRemoveFunction::ExtractIds(args, &ids, &invalid_id) || | 790 if (!BookmarksRemoveFunction::ExtractIds(args, &ids, &invalid_id) || |
783 invalid_id) { | 791 invalid_id) { |
784 return; | 792 return; |
785 } | 793 } |
786 | 794 |
787 for (IdList::iterator it = ids.begin(); it != ids.end(); ++it) { | 795 for (IdList::iterator it = ids.begin(); it != ids.end(); ++it) { |
788 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile_); | 796 BookmarkModel* model = BookmarkModelFactory::GetForProfile( |
| 797 Profile::FromBrowserContext(browser_context_)); |
789 const BookmarkNode* node = model->GetNodeByID(*it); | 798 const BookmarkNode* node = model->GetNodeByID(*it); |
790 if (!node || node->is_root()) | 799 if (!node || node->is_root()) |
791 return; | 800 return; |
792 | 801 |
793 std::string bucket_id; | 802 std::string bucket_id; |
794 bucket_id += base::UTF16ToUTF8(node->parent()->GetTitle()); | 803 bucket_id += base::UTF16ToUTF8(node->parent()->GetTitle()); |
795 bucket_id += base::UTF16ToUTF8(node->GetTitle()); | 804 bucket_id += base::UTF16ToUTF8(node->GetTitle()); |
796 bucket_id += node->url().spec(); | 805 bucket_id += node->url().spec(); |
797 buckets->push_back(GetBucket(base::SHA1HashString(bucket_id))); | 806 buckets->push_back(GetBucket(base::SHA1HashString(bucket_id))); |
798 } | 807 } |
799 } | 808 } |
800 private: | 809 private: |
801 Profile* profile_; | 810 BrowserContext* browser_context_; |
802 }; | 811 }; |
803 | 812 |
804 // Mapper for any bookmark function accepting bookmark IDs as parameters, where | 813 // Mapper for any bookmark function accepting bookmark IDs as parameters, where |
805 // a distinct ID corresponds to a single item in terms of quota limiting. This | 814 // a distinct ID corresponds to a single item in terms of quota limiting. This |
806 // is inappropriate for bookmarks.remove, for example, since repeated removals | 815 // is inappropriate for bookmarks.remove, for example, since repeated removals |
807 // of the same item will actually have a different ID each time. | 816 // of the same item will actually have a different ID each time. |
808 template <class FunctionType> | 817 template <class FunctionType> |
809 class BookmarkIdMapper : public BookmarkBucketMapper<int64> { | 818 class BookmarkIdMapper : public BookmarkBucketMapper<int64> { |
810 public: | 819 public: |
811 typedef std::list<int64> IdList; | 820 typedef std::list<int64> IdList; |
(...skipping 13 matching lines...) Expand all Loading... |
825 public: | 834 public: |
826 // For id-based bookmark functions. | 835 // For id-based bookmark functions. |
827 template <class FunctionType> | 836 template <class FunctionType> |
828 static void Build(QuotaLimitHeuristics* heuristics) { | 837 static void Build(QuotaLimitHeuristics* heuristics) { |
829 BuildWithMappers(heuristics, new BookmarkIdMapper<FunctionType>(), | 838 BuildWithMappers(heuristics, new BookmarkIdMapper<FunctionType>(), |
830 new BookmarkIdMapper<FunctionType>()); | 839 new BookmarkIdMapper<FunctionType>()); |
831 } | 840 } |
832 | 841 |
833 // For bookmarks.create. | 842 // For bookmarks.create. |
834 static void BuildForCreate(QuotaLimitHeuristics* heuristics, | 843 static void BuildForCreate(QuotaLimitHeuristics* heuristics, |
835 Profile* profile) { | 844 BrowserContext* context) { |
836 BuildWithMappers(heuristics, new CreateBookmarkBucketMapper(profile), | 845 BuildWithMappers(heuristics, |
837 new CreateBookmarkBucketMapper(profile)); | 846 new CreateBookmarkBucketMapper(context), |
| 847 new CreateBookmarkBucketMapper(context)); |
838 } | 848 } |
839 | 849 |
840 // For bookmarks.remove. | 850 // For bookmarks.remove. |
841 static void BuildForRemove(QuotaLimitHeuristics* heuristics, | 851 static void BuildForRemove(QuotaLimitHeuristics* heuristics, |
842 Profile* profile) { | 852 BrowserContext* context) { |
843 BuildWithMappers(heuristics, new RemoveBookmarksBucketMapper(profile), | 853 BuildWithMappers(heuristics, |
844 new RemoveBookmarksBucketMapper(profile)); | 854 new RemoveBookmarksBucketMapper(context), |
| 855 new RemoveBookmarksBucketMapper(context)); |
845 } | 856 } |
846 | 857 |
847 private: | 858 private: |
848 static void BuildWithMappers(QuotaLimitHeuristics* heuristics, | 859 static void BuildWithMappers(QuotaLimitHeuristics* heuristics, |
849 BucketMapper* short_mapper, BucketMapper* long_mapper) { | 860 BucketMapper* short_mapper, BucketMapper* long_mapper) { |
850 const Config kSustainedLimitConfig = { | 861 const Config kSustainedLimitConfig = { |
851 // See bookmarks.json for current value. | 862 // See bookmarks.json for current value. |
852 bookmarks::MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE, | 863 bookmarks::MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE, |
853 TimeDelta::FromMinutes(1) | 864 TimeDelta::FromMinutes(1) |
854 }; | 865 }; |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1015 #if !defined(OS_ANDROID) | 1026 #if !defined(OS_ANDROID) |
1016 // Android does not have support for the standard exporter. | 1027 // Android does not have support for the standard exporter. |
1017 // TODO(jgreenwald): remove ifdef once extensions are no longer built on | 1028 // TODO(jgreenwald): remove ifdef once extensions are no longer built on |
1018 // Android. | 1029 // Android. |
1019 bookmark_html_writer::WriteBookmarks(GetProfile(), path, NULL); | 1030 bookmark_html_writer::WriteBookmarks(GetProfile(), path, NULL); |
1020 #endif | 1031 #endif |
1021 Release(); // Balanced in BookmarksIOFunction::SelectFile() | 1032 Release(); // Balanced in BookmarksIOFunction::SelectFile() |
1022 } | 1033 } |
1023 | 1034 |
1024 } // namespace extensions | 1035 } // namespace extensions |
OLD | NEW |