| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/automation/automation_provider.h" | 5 #include "chrome/browser/automation/automation_provider.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "app/message_box_flags.h" | 9 #include "app/message_box_flags.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 #include "chrome/browser/download/download_item.h" | 51 #include "chrome/browser/download/download_item.h" |
| 52 #include "chrome/browser/download/download_shelf.h" | 52 #include "chrome/browser/download/download_shelf.h" |
| 53 #include "chrome/browser/download/save_package.h" | 53 #include "chrome/browser/download/save_package.h" |
| 54 #include "chrome/browser/extensions/crx_installer.h" | 54 #include "chrome/browser/extensions/crx_installer.h" |
| 55 #include "chrome/browser/extensions/extension_browser_event_router.h" | 55 #include "chrome/browser/extensions/extension_browser_event_router.h" |
| 56 #include "chrome/browser/extensions/extension_host.h" | 56 #include "chrome/browser/extensions/extension_host.h" |
| 57 #include "chrome/browser/extensions/extension_install_ui.h" | 57 #include "chrome/browser/extensions/extension_install_ui.h" |
| 58 #include "chrome/browser/extensions/extension_message_service.h" | 58 #include "chrome/browser/extensions/extension_message_service.h" |
| 59 #include "chrome/browser/extensions/extension_tabs_module.h" | 59 #include "chrome/browser/extensions/extension_tabs_module.h" |
| 60 #include "chrome/browser/extensions/extension_toolbar_model.h" | 60 #include "chrome/browser/extensions/extension_toolbar_model.h" |
| 61 #include "chrome/browser/extensions/extensions_service.h" | 61 #include "chrome/browser/extensions/extension_service.h" |
| 62 #include "chrome/browser/extensions/user_script_master.h" | 62 #include "chrome/browser/extensions/user_script_master.h" |
| 63 #include "chrome/browser/importer/importer.h" | 63 #include "chrome/browser/importer/importer.h" |
| 64 #include "chrome/browser/importer/importer_data_types.h" | 64 #include "chrome/browser/importer/importer_data_types.h" |
| 65 #include "chrome/browser/io_thread.h" | 65 #include "chrome/browser/io_thread.h" |
| 66 #include "chrome/browser/net/url_request_mock_util.h" | 66 #include "chrome/browser/net/url_request_mock_util.h" |
| 67 #include "chrome/browser/platform_util.h" | 67 #include "chrome/browser/platform_util.h" |
| 68 #include "chrome/browser/prefs/pref_service.h" | 68 #include "chrome/browser/prefs/pref_service.h" |
| 69 #include "chrome/browser/printing/print_job.h" | 69 #include "chrome/browser/printing/print_job.h" |
| 70 #include "chrome/browser/profiles/profile_manager.h" | 70 #include "chrome/browser/profiles/profile_manager.h" |
| 71 #include "chrome/browser/renderer_host/render_process_host.h" | 71 #include "chrome/browser/renderer_host/render_process_host.h" |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 return dl_item_value; | 301 return dl_item_value; |
| 302 } | 302 } |
| 303 | 303 |
| 304 const Extension* AutomationProvider::GetExtension(int extension_handle) { | 304 const Extension* AutomationProvider::GetExtension(int extension_handle) { |
| 305 return extension_tracker_->GetResource(extension_handle); | 305 return extension_tracker_->GetResource(extension_handle); |
| 306 } | 306 } |
| 307 | 307 |
| 308 const Extension* AutomationProvider::GetEnabledExtension(int extension_handle) { | 308 const Extension* AutomationProvider::GetEnabledExtension(int extension_handle) { |
| 309 const Extension* extension = | 309 const Extension* extension = |
| 310 extension_tracker_->GetResource(extension_handle); | 310 extension_tracker_->GetResource(extension_handle); |
| 311 ExtensionsService* service = profile_->GetExtensionsService(); | 311 ExtensionService* service = profile_->GetExtensionService(); |
| 312 if (extension && service && | 312 if (extension && service && |
| 313 service->GetExtensionById(extension->id(), false)) | 313 service->GetExtensionById(extension->id(), false)) |
| 314 return extension; | 314 return extension; |
| 315 return NULL; | 315 return NULL; |
| 316 } | 316 } |
| 317 | 317 |
| 318 const Extension* AutomationProvider::GetDisabledExtension( | 318 const Extension* AutomationProvider::GetDisabledExtension( |
| 319 int extension_handle) { | 319 int extension_handle) { |
| 320 const Extension* extension = | 320 const Extension* extension = |
| 321 extension_tracker_->GetResource(extension_handle); | 321 extension_tracker_->GetResource(extension_handle); |
| 322 ExtensionsService* service = profile_->GetExtensionsService(); | 322 ExtensionService* service = profile_->GetExtensionService(); |
| 323 if (extension && service && | 323 if (extension && service && |
| 324 service->GetExtensionById(extension->id(), true) && | 324 service->GetExtensionById(extension->id(), true) && |
| 325 !service->GetExtensionById(extension->id(), false)) | 325 !service->GetExtensionById(extension->id(), false)) |
| 326 return extension; | 326 return extension; |
| 327 return NULL; | 327 return NULL; |
| 328 } | 328 } |
| 329 | 329 |
| 330 void AutomationProvider::OnMessageReceived(const IPC::Message& message) { | 330 void AutomationProvider::OnMessageReceived(const IPC::Message& message) { |
| 331 IPC_BEGIN_MESSAGE_MAP(AutomationProvider, message) | 331 IPC_BEGIN_MESSAGE_MAP(AutomationProvider, message) |
| 332 #if !defined(OS_MACOSX) | 332 #if !defined(OS_MACOSX) |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 | 747 |
| 748 RenderViewHost* view_host = tab_contents->render_view_host(); | 748 RenderViewHost* view_host = tab_contents->render_view_host(); |
| 749 return view_host; | 749 return view_host; |
| 750 } | 750 } |
| 751 | 751 |
| 752 return NULL; | 752 return NULL; |
| 753 } | 753 } |
| 754 | 754 |
| 755 void AutomationProvider::InstallExtension(const FilePath& crx_path, | 755 void AutomationProvider::InstallExtension(const FilePath& crx_path, |
| 756 IPC::Message* reply_message) { | 756 IPC::Message* reply_message) { |
| 757 ExtensionsService* service = profile_->GetExtensionsService(); | 757 ExtensionService* service = profile_->GetExtensionService(); |
| 758 if (service) { | 758 if (service) { |
| 759 // The observer will delete itself when done. | 759 // The observer will delete itself when done. |
| 760 new ExtensionInstallNotificationObserver(this, | 760 new ExtensionInstallNotificationObserver(this, |
| 761 AutomationMsg_InstallExtension::ID, | 761 AutomationMsg_InstallExtension::ID, |
| 762 reply_message); | 762 reply_message); |
| 763 | 763 |
| 764 scoped_refptr<CrxInstaller> installer( | 764 scoped_refptr<CrxInstaller> installer( |
| 765 new CrxInstaller(service, NULL)); // silent install, no UI | 765 new CrxInstaller(service, NULL)); // silent install, no UI |
| 766 installer->InstallCrx(crx_path); | 766 installer->InstallCrx(crx_path); |
| 767 } else { | 767 } else { |
| 768 AutomationMsg_InstallExtension::WriteReplyParams( | 768 AutomationMsg_InstallExtension::WriteReplyParams( |
| 769 reply_message, AUTOMATION_MSG_EXTENSION_INSTALL_FAILED); | 769 reply_message, AUTOMATION_MSG_EXTENSION_INSTALL_FAILED); |
| 770 Send(reply_message); | 770 Send(reply_message); |
| 771 } | 771 } |
| 772 } | 772 } |
| 773 | 773 |
| 774 void AutomationProvider::LoadExpandedExtension( | 774 void AutomationProvider::LoadExpandedExtension( |
| 775 const FilePath& extension_dir, | 775 const FilePath& extension_dir, |
| 776 IPC::Message* reply_message) { | 776 IPC::Message* reply_message) { |
| 777 if (profile_->GetExtensionsService()) { | 777 if (profile_->GetExtensionService()) { |
| 778 // The observer will delete itself when done. | 778 // The observer will delete itself when done. |
| 779 new ExtensionInstallNotificationObserver( | 779 new ExtensionInstallNotificationObserver( |
| 780 this, | 780 this, |
| 781 AutomationMsg_LoadExpandedExtension::ID, | 781 AutomationMsg_LoadExpandedExtension::ID, |
| 782 reply_message); | 782 reply_message); |
| 783 | 783 |
| 784 profile_->GetExtensionsService()->LoadExtension(extension_dir); | 784 profile_->GetExtensionService()->LoadExtension(extension_dir); |
| 785 } else { | 785 } else { |
| 786 AutomationMsg_LoadExpandedExtension::WriteReplyParams( | 786 AutomationMsg_LoadExpandedExtension::WriteReplyParams( |
| 787 reply_message, AUTOMATION_MSG_EXTENSION_INSTALL_FAILED); | 787 reply_message, AUTOMATION_MSG_EXTENSION_INSTALL_FAILED); |
| 788 Send(reply_message); | 788 Send(reply_message); |
| 789 } | 789 } |
| 790 } | 790 } |
| 791 | 791 |
| 792 void AutomationProvider::GetEnabledExtensions( | 792 void AutomationProvider::GetEnabledExtensions( |
| 793 std::vector<FilePath>* result) { | 793 std::vector<FilePath>* result) { |
| 794 ExtensionsService* service = profile_->GetExtensionsService(); | 794 ExtensionService* service = profile_->GetExtensionService(); |
| 795 DCHECK(service); | 795 DCHECK(service); |
| 796 if (service->extensions_enabled()) { | 796 if (service->extensions_enabled()) { |
| 797 const ExtensionList* extensions = service->extensions(); | 797 const ExtensionList* extensions = service->extensions(); |
| 798 DCHECK(extensions); | 798 DCHECK(extensions); |
| 799 for (size_t i = 0; i < extensions->size(); ++i) { | 799 for (size_t i = 0; i < extensions->size(); ++i) { |
| 800 const Extension* extension = (*extensions)[i]; | 800 const Extension* extension = (*extensions)[i]; |
| 801 DCHECK(extension); | 801 DCHECK(extension); |
| 802 if (extension->location() == Extension::INTERNAL || | 802 if (extension->location() == Extension::INTERNAL || |
| 803 extension->location() == Extension::LOAD) { | 803 extension->location() == Extension::LOAD) { |
| 804 result->push_back(extension->path()); | 804 result->push_back(extension->path()); |
| 805 } | 805 } |
| 806 } | 806 } |
| 807 } | 807 } |
| 808 } | 808 } |
| 809 | 809 |
| 810 void AutomationProvider::WaitForExtensionTestResult( | 810 void AutomationProvider::WaitForExtensionTestResult( |
| 811 IPC::Message* reply_message) { | 811 IPC::Message* reply_message) { |
| 812 DCHECK(reply_message_ == NULL); | 812 DCHECK(reply_message_ == NULL); |
| 813 reply_message_ = reply_message; | 813 reply_message_ = reply_message; |
| 814 // Call MaybeSendResult, because the result might have come in before | 814 // Call MaybeSendResult, because the result might have come in before |
| 815 // we were waiting on it. | 815 // we were waiting on it. |
| 816 extension_test_result_observer_->MaybeSendResult(); | 816 extension_test_result_observer_->MaybeSendResult(); |
| 817 } | 817 } |
| 818 | 818 |
| 819 void AutomationProvider::InstallExtensionAndGetHandle( | 819 void AutomationProvider::InstallExtensionAndGetHandle( |
| 820 const FilePath& crx_path, bool with_ui, IPC::Message* reply_message) { | 820 const FilePath& crx_path, bool with_ui, IPC::Message* reply_message) { |
| 821 ExtensionsService* service = profile_->GetExtensionsService(); | 821 ExtensionService* service = profile_->GetExtensionService(); |
| 822 ExtensionProcessManager* manager = profile_->GetExtensionProcessManager(); | 822 ExtensionProcessManager* manager = profile_->GetExtensionProcessManager(); |
| 823 if (service && manager) { | 823 if (service && manager) { |
| 824 // The observer will delete itself when done. | 824 // The observer will delete itself when done. |
| 825 new ExtensionReadyNotificationObserver( | 825 new ExtensionReadyNotificationObserver( |
| 826 manager, | 826 manager, |
| 827 this, | 827 this, |
| 828 AutomationMsg_InstallExtensionAndGetHandle::ID, | 828 AutomationMsg_InstallExtensionAndGetHandle::ID, |
| 829 reply_message); | 829 reply_message); |
| 830 | 830 |
| 831 ExtensionInstallUI* client = | 831 ExtensionInstallUI* client = |
| 832 (with_ui ? new ExtensionInstallUI(profile_) : NULL); | 832 (with_ui ? new ExtensionInstallUI(profile_) : NULL); |
| 833 scoped_refptr<CrxInstaller> installer(new CrxInstaller(service, client)); | 833 scoped_refptr<CrxInstaller> installer(new CrxInstaller(service, client)); |
| 834 installer->InstallCrx(crx_path); | 834 installer->InstallCrx(crx_path); |
| 835 } else { | 835 } else { |
| 836 AutomationMsg_InstallExtensionAndGetHandle::WriteReplyParams( | 836 AutomationMsg_InstallExtensionAndGetHandle::WriteReplyParams( |
| 837 reply_message, 0); | 837 reply_message, 0); |
| 838 Send(reply_message); | 838 Send(reply_message); |
| 839 } | 839 } |
| 840 } | 840 } |
| 841 | 841 |
| 842 void AutomationProvider::UninstallExtension(int extension_handle, | 842 void AutomationProvider::UninstallExtension(int extension_handle, |
| 843 bool* success) { | 843 bool* success) { |
| 844 *success = false; | 844 *success = false; |
| 845 const Extension* extension = GetExtension(extension_handle); | 845 const Extension* extension = GetExtension(extension_handle); |
| 846 ExtensionsService* service = profile_->GetExtensionsService(); | 846 ExtensionService* service = profile_->GetExtensionService(); |
| 847 if (extension && service) { | 847 if (extension && service) { |
| 848 ExtensionUnloadNotificationObserver observer; | 848 ExtensionUnloadNotificationObserver observer; |
| 849 service->UninstallExtension(extension->id(), false); | 849 service->UninstallExtension(extension->id(), false); |
| 850 // The extension unload notification should have been sent synchronously | 850 // The extension unload notification should have been sent synchronously |
| 851 // with the uninstall. Just to be safe, check that it was received. | 851 // with the uninstall. Just to be safe, check that it was received. |
| 852 *success = observer.did_receive_unload_notification(); | 852 *success = observer.did_receive_unload_notification(); |
| 853 } | 853 } |
| 854 } | 854 } |
| 855 | 855 |
| 856 void AutomationProvider::EnableExtension(int extension_handle, | 856 void AutomationProvider::EnableExtension(int extension_handle, |
| 857 IPC::Message* reply_message) { | 857 IPC::Message* reply_message) { |
| 858 const Extension* extension = GetDisabledExtension(extension_handle); | 858 const Extension* extension = GetDisabledExtension(extension_handle); |
| 859 ExtensionsService* service = profile_->GetExtensionsService(); | 859 ExtensionService* service = profile_->GetExtensionService(); |
| 860 ExtensionProcessManager* manager = profile_->GetExtensionProcessManager(); | 860 ExtensionProcessManager* manager = profile_->GetExtensionProcessManager(); |
| 861 // Only enable if this extension is disabled. | 861 // Only enable if this extension is disabled. |
| 862 if (extension && service && manager) { | 862 if (extension && service && manager) { |
| 863 // The observer will delete itself when done. | 863 // The observer will delete itself when done. |
| 864 new ExtensionReadyNotificationObserver( | 864 new ExtensionReadyNotificationObserver( |
| 865 manager, | 865 manager, |
| 866 this, | 866 this, |
| 867 AutomationMsg_EnableExtension::ID, | 867 AutomationMsg_EnableExtension::ID, |
| 868 reply_message); | 868 reply_message); |
| 869 service->EnableExtension(extension->id()); | 869 service->EnableExtension(extension->id()); |
| 870 } else { | 870 } else { |
| 871 AutomationMsg_EnableExtension::WriteReplyParams(reply_message, false); | 871 AutomationMsg_EnableExtension::WriteReplyParams(reply_message, false); |
| 872 Send(reply_message); | 872 Send(reply_message); |
| 873 } | 873 } |
| 874 } | 874 } |
| 875 | 875 |
| 876 void AutomationProvider::DisableExtension(int extension_handle, | 876 void AutomationProvider::DisableExtension(int extension_handle, |
| 877 bool* success) { | 877 bool* success) { |
| 878 *success = false; | 878 *success = false; |
| 879 const Extension* extension = GetEnabledExtension(extension_handle); | 879 const Extension* extension = GetEnabledExtension(extension_handle); |
| 880 ExtensionsService* service = profile_->GetExtensionsService(); | 880 ExtensionService* service = profile_->GetExtensionService(); |
| 881 if (extension && service) { | 881 if (extension && service) { |
| 882 ExtensionUnloadNotificationObserver observer; | 882 ExtensionUnloadNotificationObserver observer; |
| 883 service->DisableExtension(extension->id()); | 883 service->DisableExtension(extension->id()); |
| 884 // The extension unload notification should have been sent synchronously | 884 // The extension unload notification should have been sent synchronously |
| 885 // with the disable. Just to be safe, check that it was received. | 885 // with the disable. Just to be safe, check that it was received. |
| 886 *success = observer.did_receive_unload_notification(); | 886 *success = observer.did_receive_unload_notification(); |
| 887 } | 887 } |
| 888 } | 888 } |
| 889 | 889 |
| 890 void AutomationProvider::ExecuteExtensionActionInActiveTabAsync( | 890 void AutomationProvider::ExecuteExtensionActionInActiveTabAsync( |
| 891 int extension_handle, int browser_handle, | 891 int extension_handle, int browser_handle, |
| 892 IPC::Message* reply_message) { | 892 IPC::Message* reply_message) { |
| 893 bool success = false; | 893 bool success = false; |
| 894 const Extension* extension = GetEnabledExtension(extension_handle); | 894 const Extension* extension = GetEnabledExtension(extension_handle); |
| 895 ExtensionsService* service = profile_->GetExtensionsService(); | 895 ExtensionService* service = profile_->GetExtensionService(); |
| 896 ExtensionMessageService* message_service = | 896 ExtensionMessageService* message_service = |
| 897 profile_->GetExtensionMessageService(); | 897 profile_->GetExtensionMessageService(); |
| 898 Browser* browser = browser_tracker_->GetResource(browser_handle); | 898 Browser* browser = browser_tracker_->GetResource(browser_handle); |
| 899 if (extension && service && message_service && browser) { | 899 if (extension && service && message_service && browser) { |
| 900 int tab_id = ExtensionTabUtil::GetTabId(browser->GetSelectedTabContents()); | 900 int tab_id = ExtensionTabUtil::GetTabId(browser->GetSelectedTabContents()); |
| 901 if (extension->page_action()) { | 901 if (extension->page_action()) { |
| 902 ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted( | 902 ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted( |
| 903 browser->profile(), extension->id(), "action", tab_id, "", 1); | 903 browser->profile(), extension->id(), "action", tab_id, "", 1); |
| 904 success = true; | 904 success = true; |
| 905 } else if (extension->browser_action()) { | 905 } else if (extension->browser_action()) { |
| 906 ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted( | 906 ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted( |
| 907 browser->profile(), extension->id(), browser); | 907 browser->profile(), extension->id(), browser); |
| 908 success = true; | 908 success = true; |
| 909 } | 909 } |
| 910 } | 910 } |
| 911 AutomationMsg_ExecuteExtensionActionInActiveTabAsync::WriteReplyParams( | 911 AutomationMsg_ExecuteExtensionActionInActiveTabAsync::WriteReplyParams( |
| 912 reply_message, success); | 912 reply_message, success); |
| 913 Send(reply_message); | 913 Send(reply_message); |
| 914 } | 914 } |
| 915 | 915 |
| 916 void AutomationProvider::MoveExtensionBrowserAction( | 916 void AutomationProvider::MoveExtensionBrowserAction( |
| 917 int extension_handle, int index, bool* success) { | 917 int extension_handle, int index, bool* success) { |
| 918 *success = false; | 918 *success = false; |
| 919 const Extension* extension = GetEnabledExtension(extension_handle); | 919 const Extension* extension = GetEnabledExtension(extension_handle); |
| 920 ExtensionsService* service = profile_->GetExtensionsService(); | 920 ExtensionService* service = profile_->GetExtensionService(); |
| 921 if (extension && service) { | 921 if (extension && service) { |
| 922 ExtensionToolbarModel* toolbar = service->toolbar_model(); | 922 ExtensionToolbarModel* toolbar = service->toolbar_model(); |
| 923 if (toolbar) { | 923 if (toolbar) { |
| 924 if (index >= 0 && index < static_cast<int>(toolbar->size())) { | 924 if (index >= 0 && index < static_cast<int>(toolbar->size())) { |
| 925 toolbar->MoveBrowserAction(extension, index); | 925 toolbar->MoveBrowserAction(extension, index); |
| 926 *success = true; | 926 *success = true; |
| 927 } else { | 927 } else { |
| 928 DLOG(WARNING) << "Attempted to move browser action to invalid index."; | 928 DLOG(WARNING) << "Attempted to move browser action to invalid index."; |
| 929 } | 929 } |
| 930 } | 930 } |
| 931 } | 931 } |
| 932 } | 932 } |
| 933 | 933 |
| 934 void AutomationProvider::GetExtensionProperty( | 934 void AutomationProvider::GetExtensionProperty( |
| 935 int extension_handle, | 935 int extension_handle, |
| 936 AutomationMsg_ExtensionProperty type, | 936 AutomationMsg_ExtensionProperty type, |
| 937 bool* success, | 937 bool* success, |
| 938 std::string* value) { | 938 std::string* value) { |
| 939 *success = false; | 939 *success = false; |
| 940 const Extension* extension = GetExtension(extension_handle); | 940 const Extension* extension = GetExtension(extension_handle); |
| 941 ExtensionsService* service = profile_->GetExtensionsService(); | 941 ExtensionService* service = profile_->GetExtensionService(); |
| 942 if (extension && service) { | 942 if (extension && service) { |
| 943 ExtensionToolbarModel* toolbar = service->toolbar_model(); | 943 ExtensionToolbarModel* toolbar = service->toolbar_model(); |
| 944 int found_index = -1; | 944 int found_index = -1; |
| 945 int index = 0; | 945 int index = 0; |
| 946 switch (type) { | 946 switch (type) { |
| 947 case AUTOMATION_MSG_EXTENSION_ID: | 947 case AUTOMATION_MSG_EXTENSION_ID: |
| 948 *value = extension->id(); | 948 *value = extension->id(); |
| 949 *success = true; | 949 *success = true; |
| 950 break; | 950 break; |
| 951 case AUTOMATION_MSG_EXTENSION_NAME: | 951 case AUTOMATION_MSG_EXTENSION_NAME: |
| (...skipping 29 matching lines...) Expand all Loading... |
| 981 } | 981 } |
| 982 } | 982 } |
| 983 } | 983 } |
| 984 | 984 |
| 985 void AutomationProvider::SaveAsAsync(int tab_handle) { | 985 void AutomationProvider::SaveAsAsync(int tab_handle) { |
| 986 NavigationController* tab = NULL; | 986 NavigationController* tab = NULL; |
| 987 TabContents* tab_contents = GetTabContentsForHandle(tab_handle, &tab); | 987 TabContents* tab_contents = GetTabContentsForHandle(tab_handle, &tab); |
| 988 if (tab_contents) | 988 if (tab_contents) |
| 989 tab_contents->OnSavePage(); | 989 tab_contents->OnSavePage(); |
| 990 } | 990 } |
| OLD | NEW |