Opera 12.15 Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

autoupdatexml.cpp 30KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  1. /* -*- Mode: c++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*-
  2. *
  3. * Copyright (C) 1995-2012 Opera Software ASA. All rights reserved.
  4. *
  5. * This file is part of the Opera web browser. It may not be distributed
  6. * under any circumstances.
  7. *
  8. * @author Michal Zajaczkowski
  9. */
  10. #include "core/pch.h"
  11. #ifdef AUTO_UPDATE_SUPPORT
  12. #include "adjunct/autoupdate/autoupdater.h"
  13. #include "adjunct/autoupdate/autoupdatexml.h"
  14. #include "adjunct/autoupdate/additionchecker.h"
  15. #include "adjunct/autoupdate/pi/opautoupdatepi.h"
  16. #include "adjunct/desktop_util/resources/ResourceDefines.h"
  17. #include "adjunct/desktop_util/resources/pi/opdesktopproduct.h"
  18. #include "adjunct/desktop_util/resources/pi/opdesktopresources.h"
  19. #include "adjunct/desktop_util/version/operaversion.h"
  20. #include "modules/dochand/win.h"
  21. #include "modules/dochand/winman.h"
  22. #include "modules/xmlutils/xmlnames.h"
  23. #include "modules/util/adt/bytebuffer.h"
  24. #include "modules/prefsfile/prefsfile.h"
  25. #include "modules/xmlutils/xmlfragment.h"
  26. #include "modules/locale/oplanguagemanager.h"
  27. #include "modules/prefs/prefsmanager/prefsmanager.h"
  28. #include "modules/prefs/prefsmanager/collections/pc_files.h"
  29. #include "modules/prefs/prefsmanager/collections/pc_ui.h"
  30. #include "modules/prefs/prefsmanager/collections/pc_network.h"
  31. #include "platforms/vega_backends/vega_blocklist_file.h"
  32. #ifdef INTERNAL_SPELLCHECK_SUPPORT
  33. # include "modules/spellchecker/opspellcheckerapi.h"
  34. #endif // INTERNAL_SPELLCHECK_SUPPORT
  35. #if defined(MSWIN)
  36. # include "platforms/windows/windows_ui/res/#buildnr.rci"
  37. #elif defined(UNIX)
  38. # include "platforms/unix/product/config.h"
  39. #elif defined(_MACINTOSH_)
  40. # include "platforms/mac/Resources/buildnum.h"
  41. #elif defined(WIN_CE)
  42. # include "platforms/win_ce/res/buildnum.h"
  43. #else
  44. # pragma error("include the file where VER_BUILD_NUMBER is defined")
  45. #endif
  46. const uni_char* AutoUpdateXML::AUTOUPDATE_SCHEMA_VERSION = UNI_L("1.0");
  47. const uni_char* AutoUpdateXML::AUTOUPDATE_REQUEST_FILE_NAME = UNI_L("autoupdate_request.xml");
  48. const OpFileFolder AutoUpdateXML::AUTOUPDATE_REQUEST_FILE_FOLDER = OPFILE_TEMPDOWNLOAD_FOLDER;
  49. AutoUpdateXML::AutoUpdateXML()
  50. :m_timestamp_browser_js(0)
  51. ,m_timestamp_override_downloaded_ini(0)
  52. ,m_timestamp_dictionaries_xml(0)
  53. ,m_timestamp_hardware_blocklist(0)
  54. ,m_timestamp_handlers_ignore(0)
  55. ,m_time_since_last_check(0)
  56. ,m_download_all_snapshots(0)
  57. ,m_inited(FALSE)
  58. ,m_dirty(0)
  59. {
  60. }
  61. AutoUpdateXML::~AutoUpdateXML()
  62. {
  63. }
  64. OP_STATUS AutoUpdateXML::Init()
  65. {
  66. RETURN_IF_ERROR(CollectPlatformData());
  67. RETURN_IF_ERROR(CollectBuildData());
  68. RETURN_IF_ERROR(CheckResourceFiles());
  69. EnsureStringsHaveBuffers();
  70. m_inited = TRUE;
  71. return OpStatus::OK;
  72. }
  73. OP_STATUS AutoUpdateXML::CollectPlatformData()
  74. {
  75. // Collect platform data
  76. OpAutoPtr<OpAutoUpdatePI> autoupdate_pi(OpAutoUpdatePI::Create());
  77. RETURN_OOM_IF_NULL(autoupdate_pi.get());
  78. RETURN_IF_ERROR(autoupdate_pi->GetOSName(m_os_name));
  79. RETURN_IF_ERROR(autoupdate_pi->GetOSVersion(m_os_version));
  80. RETURN_IF_ERROR(autoupdate_pi->GetArchitecture(m_architecture));
  81. RETURN_IF_ERROR(autoupdate_pi->GetPackageType(m_package_type));
  82. RETURN_IF_ERROR(autoupdate_pi->GetGccVersion(m_gcc_version));
  83. RETURN_IF_ERROR(autoupdate_pi->GetQTVersion(m_qt_version));
  84. return OpStatus::OK;
  85. }
  86. OP_STATUS AutoUpdateXML::CollectBuildData()
  87. {
  88. // Get the currently running Opera version, allowing it to be overriden by autoupdate.ini.
  89. OperaVersion version;
  90. version.AllowAutoupdateIniOverride();
  91. RETURN_IF_ERROR(m_opera_version.AppendFormat(UNI_L("%d.%02d"), version.GetMajor(), version.GetMinor()));
  92. RETURN_IF_ERROR(m_build_number.AppendFormat(UNI_L("%04d"), version.GetBuild()));
  93. RETURN_IF_ERROR(m_edition.Set(g_pcnet->GetStringPref(PrefsCollectionNetwork::IspUserAgentId)));
  94. return OpStatus::OK;
  95. }
  96. OP_STATUS AutoUpdateXML::CheckResourceFiles()
  97. {
  98. // Check if browser js file exists.
  99. OpFile browserjs;
  100. if(OpStatus::IsSuccess(browserjs.Construct(UNI_L("browser.js"), OPFILE_HOME_FOLDER)))
  101. {
  102. BOOL exists = FALSE;
  103. if(OpStatus::IsSuccess(browserjs.Exists(exists)) && !exists)
  104. {
  105. TRAP_AND_RETURN(err, g_pcui->WriteIntegerL(PrefsCollectionUI::BrowserJSTime, 0));
  106. TRAP_AND_RETURN(err, g_prefsManager->CommitL());
  107. }
  108. }
  109. // Check if spoof file exists.
  110. OpFile spoof;
  111. if(OpStatus::IsSuccess(spoof.Construct(UNI_L("override_downloaded.ini"), OPFILE_HOME_FOLDER)))
  112. {
  113. BOOL exists = FALSE;
  114. if(OpStatus::IsSuccess(spoof.Exists(exists)) && !exists)
  115. {
  116. TRAP_AND_RETURN(err, g_pcui->WriteIntegerL(PrefsCollectionUI::SpoofTime, 0));
  117. TRAP_AND_RETURN(err, g_prefsManager->CommitL());
  118. }
  119. }
  120. // Check if dictionaries file exists.
  121. OpFile dictionaries;
  122. if(OpStatus::IsSuccess(dictionaries.Construct(UNI_L("dictionaries.xml"), OPFILE_DICTIONARY_FOLDER)))
  123. {
  124. BOOL exists = FALSE;
  125. if(OpStatus::IsSuccess(dictionaries.Exists(exists)) && !exists)
  126. {
  127. TRAP_AND_RETURN(err, g_pcui->WriteIntegerL(PrefsCollectionUI::DictionaryTime, 0));
  128. TRAP_AND_RETURN(err, g_prefsManager->CommitL());
  129. }
  130. }
  131. // Check if hardware blocklist files exist.
  132. const VEGABlocklistDevice::BlocklistType hardware_blocklist_types[] = {
  133. #if defined(MSWIN)
  134. VEGABlocklistDevice::D3d10, VEGABlocklistDevice::WinGL
  135. #elif defined(UNIX)
  136. VEGABlocklistDevice::UnixGL
  137. #elif defined(_MACINTOSH_)
  138. VEGABlocklistDevice::MacGL
  139. #endif
  140. };
  141. for (size_t i = 0; i < ARRAY_SIZE(hardware_blocklist_types); i++)
  142. {
  143. OpFile hardware_blocklist;
  144. if(OpStatus::IsSuccess(hardware_blocklist.Construct(VEGABlocklistFile::GetName(hardware_blocklist_types[i]), VEGA_BACKENDS_BLOCKLIST_FETCHED_FOLDER)))
  145. {
  146. BOOL exists = FALSE;
  147. if(OpStatus::IsSuccess(hardware_blocklist.Exists(exists)) && !exists)
  148. {
  149. TRAP_AND_RETURN(err, g_pcui->WriteIntegerL(PrefsCollectionUI::HardwareBlocklistTime, 0));
  150. TRAP_AND_RETURN(err, g_prefsManager->CommitL());
  151. break;
  152. }
  153. }
  154. }
  155. // Check if handlers-ignore file exist.
  156. OpFileFolder ignore;
  157. const uni_char* prefs_filename = 0;
  158. g_pcfiles->GetDefaultFilePref(PrefsCollectionFiles::HandlersIgnoreFile, &ignore, &prefs_filename);
  159. OpFile handlersignore;
  160. if(prefs_filename && OpStatus::IsSuccess(handlersignore.Construct(prefs_filename, OPFILE_HOME_FOLDER)))
  161. {
  162. BOOL exists = FALSE;
  163. if(OpStatus::IsSuccess(handlersignore.Exists(exists)) && !exists)
  164. {
  165. TRAP_AND_RETURN(err, g_pcui->WriteIntegerL(PrefsCollectionUI::HandlersIgnoreTime, 0));
  166. TRAP_AND_RETURN(err, g_prefsManager->CommitL());
  167. }
  168. }
  169. return OpStatus::OK;
  170. }
  171. OP_STATUS AutoUpdateXML::UpdateFragileData()
  172. {
  173. RETURN_IF_ERROR(m_language.Set(g_languageManager->GetLanguage().CStr()));
  174. m_timestamp_browser_js = GetTimeStamp(TSI_BrowserJS);
  175. m_timestamp_override_downloaded_ini = GetTimeStamp(TSI_OverrideDownloaded);
  176. m_timestamp_dictionaries_xml = GetTimeStamp(TSI_DictionariesXML);
  177. m_timestamp_hardware_blocklist = GetTimeStamp(TSI_HardwareBlocklist);
  178. m_timestamp_handlers_ignore = GetTimeStamp(TSI_HandlersIgnore);
  179. int time_of_last_check = GetTimeStamp(TSI_LastUpdateCheck);
  180. if (time_of_last_check > 0)
  181. {
  182. m_time_since_last_check = g_timecache->CurrentTime() - time_of_last_check;
  183. if (m_time_since_last_check <= 0)
  184. SetDirty(DF_TSLC);
  185. }
  186. else
  187. m_time_since_last_check = 0;
  188. if (g_desktop_product->GetProductType() == PRODUCT_TYPE_OPERA_NEXT)
  189. m_download_all_snapshots = g_pcui->GetIntegerPref(PrefsCollectionUI::DownloadAllSnapshots);
  190. return OpStatus::OK;
  191. }
  192. int AutoUpdateXML::GetTimeStamp(TimeStampItem item)
  193. {
  194. switch (item)
  195. {
  196. case TSI_BrowserJS:
  197. return g_pcui->GetIntegerPref(PrefsCollectionUI::BrowserJSTime);
  198. case TSI_OverrideDownloaded:
  199. return g_pcui->GetIntegerPref(PrefsCollectionUI::SpoofTime);
  200. case TSI_DictionariesXML:
  201. return g_pcui->GetIntegerPref(PrefsCollectionUI::DictionaryTime);
  202. case TSI_HardwareBlocklist:
  203. return g_pcui->GetIntegerPref(PrefsCollectionUI::HardwareBlocklistTime);
  204. case TSI_HandlersIgnore:
  205. return g_pcui->GetIntegerPref(PrefsCollectionUI::HandlersIgnoreTime);
  206. case TSI_LastUpdateCheck:
  207. return g_pcui->GetIntegerPref(PrefsCollectionUI::TimeOfLastUpdateCheck);
  208. default:
  209. OP_ASSERT(!"Unknown item");
  210. }
  211. return -1;
  212. }
  213. OP_STATUS AutoUpdateXML::SetPref(int which, int value)
  214. {
  215. TRAP_AND_RETURN(st, g_pcui->WriteIntegerL(PrefsCollectionUI::integerpref(which), value));
  216. TRAP_AND_RETURN(st, g_prefsManager->CommitL());
  217. return OpStatus::OK;
  218. }
  219. void AutoUpdateXML::ClearRequestItems()
  220. {
  221. m_items.Clear();
  222. }
  223. OP_STATUS AutoUpdateXML::AddRequestItem(AdditionCheckerItem* item)
  224. {
  225. return m_items.Add(item);
  226. }
  227. OP_STATUS AutoUpdateXML::GetRequestXML(OpString8 &xml_string, AutoUpdateLevel level, RequestType request_type, AutoUpdateLevel* used_level)
  228. {
  229. OP_ASSERT(m_inited);
  230. XMLFragment fragment;
  231. // Clear the dirty flags that might have been set by the last pass through this method
  232. ClearDirty();
  233. // This method goes through all the places that are suspected to cause problems and tries to fix them, i.e.
  234. // checking if the "First Version Run" preference value is empty and filling it with some default string if it is.
  235. // It also sets appropiate flags stored in m_dirty, so that they can be sent to the server using the <dirty> XML
  236. // element.
  237. CheckDirtyness();
  238. RETURN_IF_ERROR(AdjustUpdateLevel(level));
  239. if (used_level)
  240. *used_level = level;
  241. RETURN_IF_ERROR(UpdateFragileData());
  242. RETURN_IF_ERROR(fragment.OpenElement(XMLCompleteName(UNI_L("urn:OperaAutoupdate"), UNI_L("oau"), UNI_L("versioncheck"))));
  243. RETURN_IF_ERROR(fragment.SetAttribute(UNI_L("schema-version"), AUTOUPDATE_SCHEMA_VERSION));
  244. // Adjust the level to not send requests for packages if the preference to disable it is on (i.e. MacAppStore builds)
  245. if (g_pcui->GetIntegerPref(PrefsCollectionUI::DisableOperaPackageAutoUpdate) && (level == UpdateLevelUpgradeCheck || level == UpdateLevelDefaultCheck))
  246. level = UpdateLevelResourceCheck;
  247. OpString message;
  248. message.AppendFormat("Performing an update check (%d).", level);
  249. Console::WriteMessage(message.CStr());
  250. RETURN_IF_ERROR(fragment.SetAttributeFormat(UNI_L("update-level"), UNI_L("%d"), level));
  251. // See DSK-344690 for the "main" attribute description
  252. RETURN_IF_ERROR(fragment.SetAttributeFormat(UNI_L("main"), UNI_L("%d"), (request_type == RT_Main)?1:0));
  253. RETURN_IF_ERROR(AppendXMLOpera(fragment, level));
  254. RETURN_IF_ERROR(AppendXMLOperatingSystem(fragment, level));
  255. if (level != UpdateLevelCountryCheck)
  256. RETURN_IF_ERROR(AppendXMLPackage(fragment));
  257. fragment.CloseElement();
  258. RETURN_IF_ERROR(EncodeXML(fragment, xml_string));
  259. RETURN_IF_ERROR(DumpXML(xml_string));
  260. return OpStatus::OK;
  261. }
  262. BOOL AutoUpdateXML::NeedsResourceCheck()
  263. {
  264. // If any of these timestamps is 0, we need to make a resource check ASAP in order to get
  265. // the newest resources.
  266. // See the notes found by the declaration of this method. Try to make sure that any resources
  267. // added to this array WILL be sent by the server in response to a resource update check
  268. // request, we WILL end up asking for resources on each startup otherwise.
  269. // The autoupdate servers might suffer from the load in such a case.
  270. TimeStampItem items[] = {
  271. TSI_BrowserJS
  272. ,TSI_OverrideDownloaded
  273. ,TSI_DictionariesXML
  274. };
  275. for (int i=0; i<ARRAY_SIZE(items); i++)
  276. {
  277. if (GetTimeStamp(items[i]) == 0)
  278. {
  279. OpString message;
  280. message.AppendFormat("Resource check needed (%d).", i);
  281. Console::WriteMessage(message.CStr());
  282. return TRUE;
  283. }
  284. }
  285. Console::WriteMessage(UNI_L("Resource check not needed."));
  286. return FALSE;
  287. }
  288. OP_STATUS AutoUpdateXML::AdjustUpdateLevel(AutoUpdateLevel& level)
  289. {
  290. UINT32 item_count = m_items.GetCount();
  291. UpdatableResource::UpdatableResourceType item_type = UpdatableResource::RTEmpty;
  292. /*
  293. Determine:
  294. a) if the addition checked items held currently in the m_items vector are consistent according to their type (i.e. the types can't be mixed);
  295. b) the type of the addition items;
  296. */
  297. for (UINT32 i=0; i<item_count; i++)
  298. {
  299. AdditionCheckerItem* item = m_items.Get(i);
  300. OP_ASSERT(item);
  301. if (item_type == 0)
  302. {
  303. /*
  304. The type of the first found addition checker item will be the type that we expect all the remaining items to have and it's also the type
  305. we'll use to determine the autoupdate level later on.
  306. */
  307. item_type = item->GetType();
  308. continue;
  309. }
  310. else
  311. {
  312. /*
  313. We only allow one type of resources per one XML request. This limitation comes from the way the autoupdate server
  314. works today, it could be well possible to check for any kind of resources using the ResourceCheck update level, however
  315. the way the server works is having different update levels for dictionaries and plugins, both being completely different
  316. from "resource check" meaning updating the browser.js, override_downloaded.ini, dictionaries.xml and settings.
  317. This could perhaps be changed with future development of the autoupdate server however is not possible currently due to
  318. the amount of time needed to have virtually any change related to the autoupdate server implemented.
  319. */
  320. if (!item->IsType(item_type))
  321. return OpStatus::ERR;
  322. }
  323. }
  324. if (UpdateLevelChooseAuto == level)
  325. {
  326. if (0 == item_count)
  327. {
  328. // In case there are no request items and the update level is set to auto, choose the default level (i.e. browser and resources update check)
  329. level = UpdateLevelDefaultCheck;
  330. }
  331. else
  332. {
  333. // In case the update level is set to auto and there are any addition checker items, we want to choose the level basing on the items type.
  334. switch (item_type)
  335. {
  336. case UpdatableResource::RTDictionary:
  337. level = UpdateLevelInstallDictionaries;
  338. break;
  339. case UpdatableResource::RTPlugin:
  340. level = UpdateLevelInstallPlugins;
  341. break;
  342. default:
  343. // Did you add a new resource type? You need to add a case here.
  344. OP_ASSERT(!"Don't know how to choose autoupdate level for this resource type!");
  345. break;
  346. }
  347. }
  348. if (UpdateLevelChooseAuto == level)
  349. // If were not able to determine the update level then we fail right here.
  350. return OpStatus::ERR;
  351. else
  352. return OpStatus::OK;
  353. }
  354. else
  355. {
  356. // An update level was chosen explicitly, verify it against the m_items contents.
  357. switch (level)
  358. {
  359. case UpdateLevelUpgradeCheck:
  360. case UpdateLevelResourceCheck:
  361. case UpdateLevelDefaultCheck:
  362. case UpdateLevelCountryCheck:
  363. /*
  364. For update levels 1-3,6 the m_items *must* be empty. We can't request any addition check with the browser/resources update, the autoupdate
  365. server doesn't work this way.
  366. */
  367. if (item_count == 0)
  368. return OpStatus::OK;
  369. break;
  370. /*
  371. Check if the update level is in pair with the type of the items found in the m_items vector.
  372. */
  373. case UpdateLevelInstallPlugins:
  374. if (item_type == UpdatableResource::RTPlugin)
  375. return OpStatus::OK;
  376. break;
  377. case UpdateLevelInstallDictionaries:
  378. if (item_type == UpdatableResource::RTDictionary)
  379. return OpStatus::OK;
  380. break;
  381. default:
  382. // Also add a new update level here if you added it higher.
  383. OP_ASSERT(!"Unknown autoupdate level!");
  384. break;
  385. };
  386. return OpStatus::ERR;
  387. }
  388. }
  389. OP_STATUS AutoUpdateXML::DumpXML(OpString8& xml_string)
  390. {
  391. // If the option is set dump the XML file to disk
  392. if (g_pcui->GetIntegerPref(PrefsCollectionUI::SaveAutoUpdateXML))
  393. {
  394. OpFile xml_request_dump_file;
  395. RETURN_IF_ERROR(xml_request_dump_file.Construct(AUTOUPDATE_REQUEST_FILE_NAME, AUTOUPDATE_REQUEST_FILE_FOLDER));
  396. RETURN_IF_ERROR(xml_request_dump_file.Open(OPFILE_WRITE));
  397. RETURN_IF_ERROR(xml_request_dump_file.Write(xml_string.CStr(), xml_string.Length()));
  398. RETURN_IF_ERROR(xml_request_dump_file.Close());
  399. #ifdef _DEBUG
  400. // Open the XML request in a tab
  401. OpString url_string;
  402. OpString resolved;
  403. BOOL successful;
  404. RETURN_IF_ERROR(url_string.Set(UNI_L("file:")));
  405. RETURN_IF_ERROR(url_string.Append(xml_request_dump_file.GetFullPath()));
  406. TRAP_AND_RETURN(err, successful = g_url_api->ResolveUrlNameL(url_string, resolved));
  407. if (successful && resolved.Find("file://") == 0)
  408. {
  409. URL url = g_url_api->GetURL(resolved.CStr());
  410. URL ref_url_empty = URL();
  411. Window* feedback_window = windowManager->GetAWindow(TRUE, YES, YES);
  412. RETURN_VALUE_IF_NULL(feedback_window, OpStatus::ERR);
  413. RETURN_IF_ERROR(feedback_window->OpenURL(url, DocumentReferrer(ref_url_empty), TRUE, FALSE, -1, TRUE));
  414. }
  415. #endif // _DEBUG
  416. }
  417. return OpStatus::OK;
  418. }
  419. OP_STATUS AutoUpdateXML::EncodeXML(XMLFragment& fragment, OpString8& xml_string)
  420. {
  421. UINT32 chunk = 0;
  422. ByteBuffer buffer;
  423. unsigned int bytes = 0;
  424. RETURN_IF_ERROR(fragment.GetEncodedXML(buffer, TRUE, "utf-8", FALSE));
  425. for (chunk=0; chunk<buffer.GetChunkCount(); chunk++)
  426. {
  427. char *chunk_ptr = buffer.GetChunk(chunk, &bytes);
  428. if (chunk_ptr)
  429. RETURN_IF_ERROR(xml_string.Append(chunk_ptr, bytes));
  430. }
  431. return OpStatus::OK;
  432. }
  433. OP_STATUS AutoUpdateXML::AppendXMLOperatingSystem(XMLFragment& fragment, AutoUpdateLevel level)
  434. {
  435. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("operating-system")));
  436. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("platform")));
  437. RETURN_IF_ERROR(fragment.AddText(m_os_name.CStr()));
  438. fragment.CloseElement();
  439. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("version")));
  440. RETURN_IF_ERROR(fragment.AddText(m_os_version.CStr()));
  441. fragment.CloseElement();
  442. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("architecture")));
  443. RETURN_IF_ERROR(fragment.AddText(m_architecture.CStr()));
  444. fragment.CloseElement();
  445. if (level != UpdateLevelCountryCheck)
  446. {
  447. // send country code so that we can collect stats on region settings (DSK-347797)
  448. OpDesktopResources *dr_temp = NULL;
  449. RETURN_IF_ERROR(OpDesktopResources::Create(&dr_temp));
  450. OpAutoPtr<OpDesktopResources> desktop_resources(dr_temp);
  451. OpString country_code;
  452. RETURN_IF_ERROR(desktop_resources->GetCountryCode(country_code));
  453. if (country_code.IsEmpty())
  454. {
  455. RETURN_IF_ERROR(country_code.Set(UNI_L("empty")));
  456. }
  457. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("country")));
  458. RETURN_IF_ERROR(fragment.AddText(country_code.CStr()));
  459. fragment.CloseElement();
  460. }
  461. fragment.CloseElement();
  462. return OpStatus::OK;
  463. }
  464. OP_STATUS AutoUpdateXML::AppendXMLPackage(XMLFragment& fragment)
  465. {
  466. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("package")));
  467. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("package-type")));
  468. RETURN_IF_ERROR(fragment.AddText(m_package_type.CStr()));
  469. fragment.CloseElement();
  470. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("gcc")));
  471. RETURN_IF_ERROR(fragment.AddText(m_gcc_version.CStr()));
  472. fragment.CloseElement();
  473. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("qt")));
  474. RETURN_IF_ERROR(fragment.AddText(m_qt_version.CStr()));
  475. fragment.CloseElement();
  476. fragment.CloseElement();
  477. return OpStatus::OK;
  478. }
  479. OP_STATUS AutoUpdateXML::AppendXMLOpera(XMLFragment& fragment, AutoUpdateLevel level)
  480. {
  481. OpString product, string_time_since_last_check, download_all_snapshots, first_version;
  482. OpString string_timestamp_browser_js, string_timestamp_override_downloaded_ini, string_timestamp_dictionaries_xml, string_timestamp_hardware_blocklist, string_timestamp_handlers_ignore;
  483. RETURN_IF_ERROR(string_timestamp_browser_js.AppendFormat(UNI_L("%d"), m_timestamp_browser_js));
  484. RETURN_IF_ERROR(string_timestamp_override_downloaded_ini.AppendFormat(UNI_L("%d"), m_timestamp_override_downloaded_ini));
  485. RETURN_IF_ERROR(string_timestamp_dictionaries_xml.AppendFormat(UNI_L("%d"), m_timestamp_dictionaries_xml));
  486. RETURN_IF_ERROR(string_timestamp_hardware_blocklist.AppendFormat(UNI_L("%d"), m_timestamp_hardware_blocklist));
  487. RETURN_IF_ERROR(string_timestamp_handlers_ignore.AppendFormat(UNI_L("%d"), m_timestamp_handlers_ignore));
  488. DesktopProductType product_type = g_desktop_product->GetProductType();
  489. if (PRODUCT_TYPE_OPERA == product_type)
  490. RETURN_IF_ERROR(product.Set("Opera"));
  491. else if (PRODUCT_TYPE_OPERA_NEXT == product_type)
  492. RETURN_IF_ERROR(product.Set("Opera Next"));
  493. else if (PRODUCT_TYPE_OPERA_LABS == product_type)
  494. {
  495. OpString labs_name_wide;
  496. RETURN_IF_ERROR(labs_name_wide.Set(g_desktop_product->GetLabsProductName()));
  497. RETURN_IF_ERROR(product.AppendFormat("Opera Labs %s", labs_name_wide.CStr()));
  498. }
  499. else
  500. {
  501. OP_ASSERT(!"Unknown product type!");
  502. RETURN_IF_ERROR(product.Set("Opera"));
  503. }
  504. RETURN_IF_ERROR(first_version.Set(g_pcui->GetStringPref(PrefsCollectionUI::FirstVersionRun)));
  505. RETURN_IF_ERROR(download_all_snapshots.AppendFormat(UNI_L("%d"), m_download_all_snapshots));
  506. RETURN_IF_ERROR(string_time_since_last_check.AppendFormat(UNI_L("%d"), m_time_since_last_check));
  507. int first_run_timestamp = g_pcui->GetIntegerPref(PrefsCollectionUI::FirstRunTimestamp);
  508. if (m_opera_version.IsEmpty() ||
  509. m_build_number.IsEmpty() ||
  510. m_language.IsEmpty()
  511. )
  512. return OpStatus::ERR;
  513. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("opera")));
  514. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("product")));
  515. RETURN_IF_ERROR(fragment.AddText(product.CStr()));
  516. fragment.CloseElement();
  517. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("version")));
  518. RETURN_IF_ERROR(fragment.AddText(m_opera_version.CStr()));
  519. fragment.CloseElement();
  520. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("build-number")));
  521. RETURN_IF_ERROR(fragment.AddText(m_build_number.CStr()));
  522. fragment.CloseElement();
  523. if (level != UpdateLevelCountryCheck)
  524. {
  525. if (first_version.HasContent())
  526. {
  527. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("first-version")));
  528. RETURN_IF_ERROR(fragment.AddText(first_version.CStr()));
  529. fragment.CloseElement();
  530. }
  531. if (first_run_timestamp > 0)
  532. {
  533. OpString string_timestamp_first_run;
  534. RETURN_IF_ERROR(string_timestamp_first_run.AppendFormat(UNI_L("%d"), first_run_timestamp));
  535. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("first-run")));
  536. RETURN_IF_ERROR(fragment.AddText(string_timestamp_first_run.CStr()));
  537. fragment.CloseElement();
  538. }
  539. // send country code and region prefs so that we can collect stats on region settings (DSK-347797)
  540. OpStringC region_pref;
  541. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("user-country")));
  542. region_pref = g_pcui->GetStringPref(PrefsCollectionUI::CountryCode);
  543. RETURN_IF_ERROR(fragment.AddText(region_pref.HasContent() ? region_pref.CStr() : UNI_L("empty")));
  544. fragment.CloseElement();
  545. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("detected-country")));
  546. region_pref = g_pcui->GetStringPref(PrefsCollectionUI::DetectedCountryCode);
  547. RETURN_IF_ERROR(fragment.AddText(region_pref.HasContent() ? region_pref.CStr() : UNI_L("empty")));
  548. fragment.CloseElement();
  549. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("active-country")));
  550. region_pref = g_region_info->m_country;
  551. RETURN_IF_ERROR(fragment.AddText(region_pref.HasContent() ? region_pref.CStr() : UNI_L("empty")));
  552. fragment.CloseElement();
  553. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("active-region")));
  554. region_pref = g_region_info->m_region;
  555. RETURN_IF_ERROR(fragment.AddText(region_pref.HasContent() ? region_pref.CStr() : UNI_L("empty")));
  556. fragment.CloseElement();
  557. }
  558. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("language")));
  559. RETURN_IF_ERROR(fragment.AddText(m_language.CStr()));
  560. fragment.CloseElement();
  561. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("edition")));
  562. RETURN_IF_ERROR(fragment.AddText(m_edition.CStr()));
  563. fragment.CloseElement();
  564. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("time-since-last-check")));
  565. RETURN_IF_ERROR(fragment.AddText(string_time_since_last_check.CStr()));
  566. fragment.CloseElement();
  567. if (level != UpdateLevelCountryCheck)
  568. {
  569. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("should-serve-all")));
  570. RETURN_IF_ERROR(fragment.AddText(download_all_snapshots.CStr()));
  571. fragment.CloseElement();
  572. // See DSK-344128 for information about the <autoupdate-first-response> XML element
  573. if (!g_pcui->GetIntegerPref(PrefsCollectionUI::AutoUpdateResponded))
  574. {
  575. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("autoupdate-first-response")));
  576. RETURN_IF_ERROR(fragment.AddText(UNI_L("1")));
  577. fragment.CloseElement();
  578. }
  579. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("dirty")));
  580. OpString dirty_value;
  581. RETURN_IF_ERROR(dirty_value.AppendFormat("%d", m_dirty));
  582. RETURN_IF_ERROR(fragment.AddText(dirty_value));
  583. fragment.CloseElement();
  584. }
  585. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("modules")));
  586. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("browserjs-timestamp")));
  587. RETURN_IF_ERROR(fragment.AddText(string_timestamp_browser_js.CStr()));
  588. fragment.CloseElement();
  589. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("spoof-timestamp")));
  590. RETURN_IF_ERROR(fragment.AddText(string_timestamp_override_downloaded_ini.CStr()));
  591. fragment.CloseElement();
  592. #ifdef INTERNAL_SPELLCHECK_SUPPORT
  593. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("dictionary-timestamp")));
  594. RETURN_IF_ERROR(fragment.AddText(string_timestamp_dictionaries_xml.CStr()));
  595. fragment.CloseElement();
  596. RETURN_IF_ERROR(AppendXMLDictionaries(fragment, level));
  597. if (UpdateLevelInstallPlugins == level)
  598. RETURN_IF_ERROR(AppendXMLPlugins(fragment, level));
  599. #endif // INTERNAL_SPELLCHECK_SUPPORT
  600. if (level != UpdateLevelCountryCheck)
  601. {
  602. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("blocklist-timestamp")));
  603. RETURN_IF_ERROR(fragment.AddText(string_timestamp_hardware_blocklist.CStr()));
  604. fragment.CloseElement();
  605. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("handlers-ignore-timestamp")));
  606. RETURN_IF_ERROR(fragment.AddText(string_timestamp_handlers_ignore.CStr()));
  607. fragment.CloseElement();
  608. }
  609. fragment.CloseElement(); // modules
  610. fragment.CloseElement(); // opera
  611. return OpStatus::OK;
  612. }
  613. OP_STATUS AutoUpdateXML::AppendXMLDictionaries(XMLFragment& fragment, AutoUpdateLevel level)
  614. {
  615. #ifdef INTERNAL_SPELLCHECK_SUPPORT
  616. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("dictionary")));
  617. if (level != UpdateLevelCountryCheck)
  618. RETURN_IF_ERROR(AppendXMLExistingDictionaries(fragment, level));
  619. if (UpdateLevelInstallDictionaries == level)
  620. RETURN_IF_ERROR(AppendXMLNewDictionaries(fragment, level));
  621. fragment.CloseElement();
  622. #endif
  623. return OpStatus::OK;
  624. }
  625. OP_STATUS AutoUpdateXML::AppendXMLPlugins(XMLFragment& fragment, AutoUpdateLevel level)
  626. {
  627. #ifdef PLUGIN_AUTO_INSTALL
  628. OpString version, key;
  629. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("plugins")));
  630. // Plugin version is always set to 0 for plugin installation
  631. RETURN_IF_ERROR(version.Set(UNI_L("0")));
  632. for (UINT32 i=0; i<m_items.GetCount(); i++)
  633. {
  634. AdditionCheckerItem* item = m_items.Get(i);
  635. OP_ASSERT(item);
  636. OP_ASSERT(item->IsType(UpdatableResource::RTPlugin));
  637. RETURN_IF_ERROR(item->GetKey(key));
  638. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("plugin")));
  639. RETURN_IF_ERROR(fragment.SetAttribute(UNI_L("mime-type"), key.CStr()));
  640. RETURN_IF_ERROR(fragment.SetAttributeFormat(UNI_L("version"), version.CStr()));
  641. fragment.CloseElement();
  642. }
  643. fragment.CloseElement();
  644. #endif
  645. return OpStatus::OK;
  646. }
  647. OP_STATUS AutoUpdateXML::AppendXMLExistingDictionaries(XMLFragment& fragment, AutoUpdateLevel level)
  648. {
  649. #if defined(INTERNAL_SPELLCHECK_SUPPORT) && defined(SPELLCHECKER_CAP_GET_DICTIONARY_VERSION) && defined(WIC_CAP_GET_DICTIONARY_VERSION)
  650. // To update new Dictionaries
  651. OpSpellUiSessionImpl session(0);
  652. int number_of_dictionaries = session.GetInstalledLanguageCount();
  653. for (int i = 0; i < number_of_dictionaries; i++)
  654. {
  655. int language_version = 0;
  656. language_version = session.GetInstalledLanguageVersionAt(i);
  657. if (language_version > 0)
  658. {
  659. OpString language;
  660. OpString version;
  661. RETURN_IF_ERROR(language.Set(session.GetInstalledLanguageStringAt(i)));
  662. RETURN_IF_ERROR(version.AppendFormat(UNI_L("%d.0"), language_version));
  663. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("language")));
  664. RETURN_IF_ERROR(fragment.SetAttribute(UNI_L("version"), version.CStr()));
  665. RETURN_IF_ERROR(fragment.AddText(language));
  666. fragment.CloseElement();
  667. }
  668. }
  669. return OpStatus::OK;
  670. #else
  671. OP_ASSERT(!"Can't list dictionaries with this source configuration!");
  672. return OpStatus::ERR;
  673. #endif
  674. }
  675. OP_STATUS AutoUpdateXML::AppendXMLNewDictionaries(XMLFragment& fragment, AutoUpdateLevel level)
  676. {
  677. #ifdef INTERNAL_SPELLCHECK_SUPPORT
  678. OpString version, key;
  679. RETURN_IF_ERROR(version.Set(UNI_L("0")));
  680. for (UINT32 i=0; i<m_items.GetCount(); i++)
  681. {
  682. AdditionCheckerItem* item = m_items.Get(i);
  683. OP_ASSERT(item);
  684. OP_ASSERT(item->IsType(UpdatableResource::RTDictionary));
  685. RETURN_IF_ERROR(item->GetKey(key));
  686. RETURN_IF_ERROR(fragment.OpenElement(UNI_L("language")));
  687. RETURN_IF_ERROR(fragment.SetAttribute(UNI_L("version"), version.CStr()));
  688. RETURN_IF_ERROR(fragment.AddText(key.CStr()));
  689. fragment.CloseElement();
  690. }
  691. #endif
  692. return OpStatus::OK;
  693. }
  694. void AutoUpdateXML::ClearDirty()
  695. {
  696. m_dirty = 0;
  697. }
  698. void AutoUpdateXML::SetDirty(DirtyFlag flag)
  699. {
  700. m_dirty |= flag;
  701. }
  702. void AutoUpdateXML::CheckDirtyness()
  703. {
  704. // See if we can actually change the value of the "Time Of Last Upgrade Check" preference
  705. const uni_char* section = UNI_L("Auto Update");
  706. const uni_char* pref = UNI_L("Time Of Last Upgrade Check");
  707. PrefsFile* reader = const_cast<PrefsFile*>(g_prefsManager->GetReader());
  708. BOOL allowed = FALSE;
  709. OP_STATUS err = OpStatus::OK;
  710. if (reader)
  711. {
  712. TRAP(err, allowed = reader->AllowedToChangeL(section, pref));
  713. }
  714. if (OpStatus::IsError(err) || !allowed)
  715. // Not possible to change a pref value, remember that
  716. SetDirty(DF_OPERAPREFS);
  717. // Check if the first run data is set, try to set it to fallback values in case it is
  718. const uni_char* first_version_run_fallback = UNI_L("Old Installation");
  719. const int first_run_timestamp_fallback = 1;
  720. // Try to set the empty values to some default ones, ignore errors but signal them by setting the flags
  721. if (g_pcui->GetStringPref(PrefsCollectionUI::FirstVersionRun).IsEmpty())
  722. {
  723. SetDirty(DF_FIRSTRUNVER);
  724. TRAPD(err, g_pcui->WriteStringL(PrefsCollectionUI::FirstVersionRun, first_version_run_fallback));
  725. TRAP(err, g_prefsManager->CommitL());
  726. }
  727. if (g_pcui->GetIntegerPref(PrefsCollectionUI::FirstRunTimestamp) <= 0)
  728. {
  729. SetDirty(DF_FIRSTRUNTS);
  730. TRAPD(err, g_pcui->WriteIntegerL(PrefsCollectionUI::FirstRunTimestamp, first_run_timestamp_fallback));
  731. TRAP(err, g_prefsManager->CommitL());
  732. }
  733. #if defined(MSWIN)
  734. // Check and see if the current Opera binary is not located under the system temp path.
  735. // This might occur when there are problems with synchronisation of the different
  736. // processes run when applying an update, see DSK-345746.
  737. OpDesktopResources *resources = NULL;
  738. OpAutoPtr<OpDesktopResources> resources_guard;
  739. if (OpStatus::IsSuccess(OpDesktopResources::Create(&resources)))
  740. {
  741. resources_guard = resources;
  742. OpString binary_folder, temp_folder;
  743. RETURN_VOID_IF_ERROR(resources->GetBinaryResourceFolder(binary_folder));
  744. RETURN_VOID_IF_ERROR(resources->GetTempFolder(temp_folder));
  745. if (binary_folder.FindI(temp_folder.CStr()) != KNotFound)
  746. SetDirty(DF_RUNFROMTEMP);
  747. }
  748. #endif // MSWIN
  749. }
  750. void AutoUpdateXML::EnsureStringsHaveBuffers()
  751. {
  752. OpString* strings[] = {
  753. &m_opera_version,
  754. &m_build_number,
  755. &m_language,
  756. &m_edition,
  757. &m_os_name,
  758. &m_os_version,
  759. &m_architecture,
  760. &m_package_type,
  761. &m_gcc_version,
  762. &m_qt_version
  763. };
  764. int count = ARRAY_SIZE(strings);
  765. for (int i=0; i<count; i++)
  766. {
  767. OP_ASSERT(strings[i]);
  768. if (NULL == strings[i]->CStr())
  769. strings[i]->Set(UNI_L(""));
  770. }
  771. }
  772. #endif // AUTO_UPDATE_SUPPORT